mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-16 14:25:05 +00:00
Compare commits
693 Commits
Author | SHA1 | Date | |
---|---|---|---|
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 | |||
5c63e06b0f | |||
3be83e09f2 | |||
f24be2b055 | |||
484557935e | |||
485f573955 | |||
71e0521286 | |||
ecbf21acea | |||
45c89d084c | |||
56f90a2901 | |||
73d1f84072 | |||
da4a2d8552 | |||
dc9351b024 | |||
15baf09339 | |||
083dde8395 | |||
22b5de09b4 | |||
a5edfa368e | |||
9ebd6d6b0f | |||
58e32086c0 | |||
8c0d441a13 | |||
8766d4050c | |||
56883f9ff9 | |||
7cdd26add5 | |||
717b866605 | |||
f87e96026c | |||
8e1b3edd2c | |||
3d2ca457f8 | |||
1579f41056 | |||
70a4f73d73 | |||
7d43dffac4 | |||
804a062c3a | |||
22a4639162 | |||
619a9892e5 | |||
63b109f23e | |||
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 | |||
6e08b622b3 | |||
604900d4c5 | |||
6422ed7722 | |||
06a9c98ded | |||
5c7b05c2ba | |||
9c86763322 | |||
35490ca41c | |||
47c7872c88 | |||
f8ce01e2fd | |||
3907a2b6ba | |||
1171cd2493 | |||
e2579e0a2a | |||
5a9a576bfa | |||
b8caf34e62 | |||
dc757c25c8 | |||
73267ae077 | |||
8ec0a4d0d6 | |||
df65f1009c | |||
c19ab97610 | |||
dbaf851be7 | |||
19bd283807 | |||
20d1a048dd | |||
15b76a24b7 | |||
2d51971b84 | |||
f08e411cad | |||
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 |
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
|
|
281
.github/workflows/main.yml
vendored
Normal file
281
.github/workflows/main.yml
vendored
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
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: [7.4.20]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2 #needed for build.sh
|
||||||
|
- name: Check for PHP build cache
|
||||||
|
id: php-build-cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: "./bin"
|
||||||
|
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
|
||||||
|
|
||||||
|
- name: Compile PHP
|
||||||
|
if: steps.php-build-cache.outputs.cache-hit != 'true'
|
||||||
|
run: ./tests/gh-actions/build.sh "${{ matrix.php }}"
|
||||||
|
|
||||||
|
phpstan:
|
||||||
|
name: PHPStan analysis
|
||||||
|
needs: build-php
|
||||||
|
runs-on: ${{ matrix.image }}
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
image: [ubuntu-20.04]
|
||||||
|
php: [7.4.20]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Restore PHP build cache
|
||||||
|
id: php-build-cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: "./bin"
|
||||||
|
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
|
||||||
|
|
||||||
|
- name: Kill build on PHP build cache miss (should never happen)
|
||||||
|
if: steps.php-build-cache.outputs.cache-hit != 'true'
|
||||||
|
run: exit 1
|
||||||
|
|
||||||
|
- name: Install cached PHP's dependencies
|
||||||
|
if: steps.php-build-cache.outputs.cache-hit == 'true'
|
||||||
|
run: ./tests/gh-actions/install-dependencies.sh
|
||||||
|
|
||||||
|
- name: Prefix PHP to PATH
|
||||||
|
run: echo "$(pwd)/bin/php7/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
- 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: [7.4.20]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Restore PHP build cache
|
||||||
|
id: php-build-cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: "./bin"
|
||||||
|
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
|
||||||
|
|
||||||
|
- name: Kill build on PHP build cache miss (should never happen)
|
||||||
|
if: steps.php-build-cache.outputs.cache-hit != 'true'
|
||||||
|
run: exit 1
|
||||||
|
|
||||||
|
- name: Install cached PHP's dependencies
|
||||||
|
if: steps.php-build-cache.outputs.cache-hit == 'true'
|
||||||
|
run: ./tests/gh-actions/install-dependencies.sh
|
||||||
|
|
||||||
|
- name: Prefix PHP to PATH
|
||||||
|
run: echo "$(pwd)/bin/php7/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
- 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: [7.4.20]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
|
||||||
|
- name: Restore PHP build cache
|
||||||
|
id: php-build-cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: "./bin"
|
||||||
|
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
|
||||||
|
|
||||||
|
- name: Kill build on PHP build cache miss (should never happen)
|
||||||
|
if: steps.php-build-cache.outputs.cache-hit != 'true'
|
||||||
|
run: exit 1
|
||||||
|
|
||||||
|
- name: Install cached PHP's dependencies
|
||||||
|
if: steps.php-build-cache.outputs.cache-hit == 'true'
|
||||||
|
run: ./tests/gh-actions/install-dependencies.sh
|
||||||
|
|
||||||
|
- name: Prefix PHP to PATH
|
||||||
|
run: echo "$(pwd)/bin/php7/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
- 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: [7.4.20]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
|
||||||
|
- name: Restore PHP build cache
|
||||||
|
id: php-build-cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: "./bin"
|
||||||
|
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
|
||||||
|
|
||||||
|
- name: Kill build on PHP build cache miss (should never happen)
|
||||||
|
if: steps.php-build-cache.outputs.cache-hit != 'true'
|
||||||
|
run: exit 1
|
||||||
|
|
||||||
|
- name: Install cached PHP's dependencies
|
||||||
|
if: steps.php-build-cache.outputs.cache-hit == 'true'
|
||||||
|
run: ./tests/gh-actions/install-dependencies.sh
|
||||||
|
|
||||||
|
- name: Prefix PHP to PATH
|
||||||
|
run: echo "$(pwd)/bin/php7/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
- 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" --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.9.0
|
||||||
|
with:
|
||||||
|
php-version: 7.4
|
||||||
|
tools: php-cs-fixer
|
||||||
|
|
||||||
|
- 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
|
51
.github/workflows/update-php-versions.php
vendored
Normal file
51
.github/workflows/update-php-versions.php
vendored
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?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 = [
|
||||||
|
"7.3",
|
||||||
|
"7.4",
|
||||||
|
"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);
|
||||||
|
}
|
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
|
||||||
|
8
.gitmodules
vendored
8
.gitmodules
vendored
@ -1,12 +1,12 @@
|
|||||||
[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 "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
|
||||||
|
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} {
|
||||||
|
|
||||||
|
}
|
71
.php-cs-fixer.php
Normal file
71
.php-cs-fixer.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?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'
|
||||||
|
],
|
||||||
|
'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_trim' => true,
|
||||||
|
'phpdoc_trim_consecutive_blank_line_separation' => true,
|
||||||
|
'single_import_per_statement' => true,
|
||||||
|
'strict_param' => true,
|
||||||
|
])
|
||||||
|
->setFinder($finder)
|
||||||
|
->setIndent("\t")
|
||||||
|
->setLineEnding("\n");
|
33
.travis.yml
33
.travis.yml
@ -1,33 +0,0 @@
|
|||||||
language: php
|
|
||||||
|
|
||||||
php:
|
|
||||||
- 7.2
|
|
||||||
- 7.3
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- phpenv config-rm xdebug.ini
|
|
||||||
- echo | pecl install channel://pecl.php.net/yaml-2.1.0
|
|
||||||
- git clone https://github.com/pmmp/pthreads.git
|
|
||||||
- cd pthreads
|
|
||||||
- git checkout 646dac62ae0d48c1ada7b007e15575fb84f7d71d
|
|
||||||
- phpize
|
|
||||||
- ./configure
|
|
||||||
- make
|
|
||||||
- make install
|
|
||||||
- cd ..
|
|
||||||
- echo "extension=pthreads.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
|
|
||||||
|
|
||||||
script:
|
|
||||||
- composer install --prefer-dist
|
|
||||||
- ./vendor/bin/phpstan analyze --no-progress --memory-limit=2G
|
|
||||||
- ./vendor/bin/phpunit --bootstrap vendor/autoload.php --fail-on-warning tests/phpunit
|
|
||||||
- composer install --no-dev --prefer-dist
|
|
||||||
- ./tests/travis.sh -t4
|
|
||||||
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.composer/cache/files
|
|
||||||
- $HOME/.composer/cache/vcs
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
12
BUILDING.md
12
BUILDING.md
@ -2,13 +2,13 @@
|
|||||||
## Pre-requisites
|
## Pre-requisites
|
||||||
- A bash shell (git bash is sufficient for Windows)
|
- A bash shell (git bash is sufficient for Windows)
|
||||||
- [`git`](https://git-scm.com) available in your shell
|
- [`git`](https://git-scm.com) available in your shell
|
||||||
- PHP 7.2 or newer available in your shell
|
- PHP 7.3 or newer available in your shell
|
||||||
- [`composer`](https://getcomposer.org) available in your shell
|
- [`composer`](https://getcomposer.org) available in your shell
|
||||||
|
|
||||||
## Custom PHP binaries
|
## Custom PHP binaries
|
||||||
Because PocketMine-MP requires several non-standard PHP extensions and configuration, PMMP provides scripts to build custom binaries for running PocketMine-MP, as well as prebuilt binaries.
|
Because PocketMine-MP requires several non-standard PHP extensions and configuration, PMMP provides scripts to build custom binaries for running PocketMine-MP, as well as prebuilt binaries.
|
||||||
|
|
||||||
- [Prebuilt binaries](https://jenkins.pmmp.io/job/PHP-7.3-Aggregate)
|
- [Prebuilt binaries](https://jenkins.pmmp.io/job/PHP-7.4-Aggregate)
|
||||||
- [Compile scripts](https://github.com/pmmp/php-build-scripts) are provided as a submodule in the path `build/php`
|
- [Compile scripts](https://github.com/pmmp/php-build-scripts) are provided as a submodule in the path `build/php`
|
||||||
|
|
||||||
If you use a custom binary, you'll need to replace `composer` usages in this guide with `path/to/your/php path/to/your/composer.phar`.
|
If you use a custom binary, you'll need to replace `composer` usages in this guide with `path/to/your/php path/to/your/composer.phar`.
|
||||||
@ -30,9 +30,15 @@ If you use a custom binary, you'll need to replace `composer` usages in this gui
|
|||||||
Preprocessor requires that the `cpp` (c preprocessor) is available in your PATH.
|
Preprocessor requires that the `cpp` (c preprocessor) is available in your PATH.
|
||||||
|
|
||||||
## Building `PocketMine-MP.phar`
|
## Building `PocketMine-MP.phar`
|
||||||
Run `build/server-phar.php` using your preferred PHP binary. It'll drop a `PocketMine-MP.phar` into the current working directory.
|
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.
|
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 7.4.16 or 8.0.3.
|
||||||
|
|
||||||
## Running PocketMine-MP from source code
|
## Running PocketMine-MP from source code
|
||||||
Run `src/pocketmine/PocketMine.php` using your preferred PHP binary.
|
Run `src/pocketmine/PocketMine.php` using your preferred PHP binary.
|
||||||
|
@ -116,7 +116,7 @@ class ExampleClass{
|
|||||||
<!-- TODO: RFC and voting on the forums instead -->
|
<!-- TODO: RFC and voting on the forums instead -->
|
||||||
### RFC and Voting
|
### RFC and Voting
|
||||||
* These are big Pull Requests or contributions that change important behavior.
|
* These are big Pull Requests or contributions that change important behavior.
|
||||||
* RFCs will be tagged with the *PR: RFC* label
|
* RFCs will be tagged with the *Type: Request For Comments* label
|
||||||
* A vote will be held once the RFC is ready. All users can vote commenting on the Pull Request
|
* 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.
|
* 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.
|
* If your comment is a voting comment, specify the reason of your vote or it won't be counted.
|
||||||
|
10
README.md
10
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/)
|
||||||
@ -18,8 +23,9 @@
|
|||||||
|
|
||||||
## For developers
|
## For developers
|
||||||
* [Building and running from source](BUILDING.md)
|
* [Building and running from source](BUILDING.md)
|
||||||
|
* [Developer documentation](https://devdoc.pmmp.io) - General documentation for PocketMine-MP plugin developers
|
||||||
* [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)
|
||||||
|
|
||||||
|
33
SECURITY.md
Normal file
33
SECURITY.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
The following release lines are currently receiving active security updates and bug fixes:
|
||||||
|
|
||||||
|
| Version | Supported |
|
||||||
|
| -------- | ------------------ |
|
||||||
|
| 3.15.x | :white_check_mark: |
|
||||||
|
| < 3.15.0 | :x: |
|
||||||
|
|
||||||
|
## 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.
|
@ -37,7 +37,6 @@ use const STDIN;
|
|||||||
|
|
||||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
|
|
||||||
function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev) : void{
|
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(
|
||||||
@ -70,12 +69,16 @@ function main(array $argv) : void{
|
|||||||
$currentVer->getPatch() + 1
|
$currentVer->getPatch() + 1
|
||||||
));
|
));
|
||||||
|
|
||||||
$versionInfoPath = dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
|
|
||||||
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false);
|
|
||||||
|
|
||||||
echo "please add appropriate notes to the changelog and press enter...";
|
echo "please add appropriate notes to the changelog and press enter...";
|
||||||
fgets(STDIN);
|
fgets(STDIN);
|
||||||
system('git add "' . dirname(__DIR__) . '/changelogs"');
|
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);
|
||||||
system('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"');
|
system('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"');
|
||||||
system('git tag ' . $currentVer->getBaseVersion());
|
system('git tag ' . $currentVer->getBaseVersion());
|
||||||
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true);
|
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true);
|
||||||
@ -86,6 +89,4 @@ function main(array $argv) : void{
|
|||||||
system('git push origin HEAD ' . $currentVer->getBaseVersion());
|
system('git push origin HEAD ' . $currentVer->getBaseVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!defined('pocketmine\_PHPSTAN_ANALYSIS')){
|
main($argv);
|
||||||
main($argv);
|
|
||||||
}
|
|
||||||
|
Submodule build/php updated: d475b694e4...4bf8ec1ad0
Submodule build/preprocessor updated: da363df5f1...1b9304de61
@ -26,7 +26,6 @@ namespace pocketmine\build\server_phar;
|
|||||||
use pocketmine\utils\Git;
|
use pocketmine\utils\Git;
|
||||||
use function array_map;
|
use function array_map;
|
||||||
use function count;
|
use function count;
|
||||||
use function defined;
|
|
||||||
use function dirname;
|
use function dirname;
|
||||||
use function file_exists;
|
use function file_exists;
|
||||||
use function getcwd;
|
use function getcwd;
|
||||||
@ -41,6 +40,7 @@ use function rtrim;
|
|||||||
use function sprintf;
|
use function sprintf;
|
||||||
use function str_replace;
|
use function str_replace;
|
||||||
use function unlink;
|
use function unlink;
|
||||||
|
use const PHP_EOL;
|
||||||
|
|
||||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ require dirname(__DIR__) . '/vendor/autoload.php';
|
|||||||
*
|
*
|
||||||
* @return string[]
|
* @return string[]
|
||||||
*/
|
*/
|
||||||
function preg_quote_array(array $strings, string $delim = null) : array{
|
function preg_quote_array(array $strings, string $delim) : array{
|
||||||
return array_map(function(string $str) use ($delim) : string{ return preg_quote($str, $delim); }, $strings);
|
return array_map(function(string $str) use ($delim) : string{ return preg_quote($str, $delim); }, $strings);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,6 +129,10 @@ function main() : void{
|
|||||||
echo "Set phar.readonly to 0 with -dphar.readonly=0" . PHP_EOL;
|
echo "Set phar.readonly to 0 with -dphar.readonly=0" . PHP_EOL;
|
||||||
exit(1);
|
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:"]);
|
$opts = getopt("", ["out:", "git:"]);
|
||||||
if(isset($opts["git"])){
|
if(isset($opts["git"])){
|
||||||
@ -169,6 +173,4 @@ STUB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!defined('pocketmine\_PHPSTAN_ANALYSIS')){
|
main();
|
||||||
main();
|
|
||||||
}
|
|
||||||
|
@ -48,3 +48,11 @@ Plugin developers should **only** update their required API to this version if y
|
|||||||
|
|
||||||
# 3.12.4
|
# 3.12.4
|
||||||
- Fixed absorption hearts not being consumed.
|
- 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.
|
@ -5,11 +5,10 @@
|
|||||||
"homepage": "https://pmmp.io",
|
"homepage": "https://pmmp.io",
|
||||||
"license": "LGPL-3.0",
|
"license": "LGPL-3.0",
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.2.0",
|
"php": "^7.4 || ^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": "*",
|
||||||
@ -19,28 +18,30 @@
|
|||||||
"ext-phar": "*",
|
"ext-phar": "*",
|
||||||
"ext-pthreads": "~3.2.0",
|
"ext-pthreads": "~3.2.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.7",
|
"composer-runtime-api": "^2.0",
|
||||||
"pocketmine/spl": "^0.4.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/math": "^0.2.0",
|
|
||||||
"pocketmine/snooze": "^0.1.0",
|
|
||||||
"pocketmine/classloader": "^0.1.0",
|
"pocketmine/classloader": "^0.1.0",
|
||||||
"pocketmine/log": "^0.2.0",
|
"pocketmine/log": "^0.2.0",
|
||||||
"pocketmine/log-pthreads": "^0.1.0",
|
"pocketmine/log-pthreads": "^0.1.0",
|
||||||
"pocketmine/callback-validator": "^1.0.1",
|
"pocketmine/math": "^0.2.0",
|
||||||
"adhocore/json-comment": "^0.1.0"
|
"pocketmine/nbt": "^0.2.18",
|
||||||
|
"pocketmine/raklib": "^0.12.7",
|
||||||
|
"pocketmine/snooze": "^0.1.0",
|
||||||
|
"pocketmine/spl": "^0.4.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpstan/phpstan": "^0.12.25",
|
"phpstan/phpstan": "0.12.91",
|
||||||
"phpstan/phpstan-phpunit": "^0.12.6",
|
"phpstan/phpstan-phpunit": "^0.12.6",
|
||||||
"phpstan/phpstan-strict-rules": "^0.12.2",
|
"phpstan/phpstan-strict-rules": "^0.12.2",
|
||||||
"phpunit/phpunit": "^8.5"
|
"phpunit/phpunit": "^9.2"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
@ -56,5 +57,18 @@
|
|||||||
"psr-4": {
|
"psr-4": {
|
||||||
"pocketmine\\": "tests/phpunit/"
|
"pocketmine\\": "tests/phpunit/"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"platform": {
|
||||||
|
"php": "7.4.0"
|
||||||
|
},
|
||||||
|
"sort-packages": true
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"make-devtools": "@php -dphar.readonly=0 tests/plugins/DevTools/src/DevTools/ConsoleScript.php --make tests/plugins/DevTools --out plugins/DevTools.phar",
|
||||||
|
"make-server": [
|
||||||
|
"@composer install --no-dev --classmap-authoritative",
|
||||||
|
"@php -dphar.readonly=0 build/server-phar.php"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1724
composer.lock
generated
1724
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,7 +1,6 @@
|
|||||||
includes:
|
includes:
|
||||||
- tests/phpstan/configs/actual-problems.neon
|
- tests/phpstan/configs/actual-problems.neon
|
||||||
- tests/phpstan/configs/com-dotnet-magic.neon
|
- tests/phpstan/configs/check-explicit-mixed-baseline.neon
|
||||||
- tests/phpstan/configs/custom-leveldb.neon
|
|
||||||
- tests/phpstan/configs/gc-hacks.neon
|
- tests/phpstan/configs/gc-hacks.neon
|
||||||
- tests/phpstan/configs/l7-baseline.neon
|
- tests/phpstan/configs/l7-baseline.neon
|
||||||
- tests/phpstan/configs/l8-baseline.neon
|
- tests/phpstan/configs/l8-baseline.neon
|
||||||
@ -16,8 +15,13 @@ includes:
|
|||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
level: 8
|
level: 8
|
||||||
autoload_files:
|
checkExplicitMixed: true
|
||||||
|
checkMissingCallableSignature: true
|
||||||
|
bootstrapFiles:
|
||||||
- tests/phpstan/bootstrap.php
|
- tests/phpstan/bootstrap.php
|
||||||
|
scanDirectories:
|
||||||
|
- tests/plugins/TesterPlugin
|
||||||
|
scanFiles:
|
||||||
- src/pocketmine/PocketMine.php
|
- src/pocketmine/PocketMine.php
|
||||||
- build/make-release.php
|
- build/make-release.php
|
||||||
- build/server-phar.php
|
- build/server-phar.php
|
||||||
@ -26,12 +30,20 @@ parameters:
|
|||||||
- build/make-release.php
|
- build/make-release.php
|
||||||
- build/server-phar.php
|
- build/server-phar.php
|
||||||
- tests/phpunit
|
- tests/phpunit
|
||||||
|
- tests/plugins/TesterPlugin
|
||||||
dynamicConstantNames:
|
dynamicConstantNames:
|
||||||
- pocketmine\IS_DEVELOPMENT_BUILD
|
- pocketmine\IS_DEVELOPMENT_BUILD
|
||||||
- pocketmine\DEBUG
|
- pocketmine\DEBUG
|
||||||
stubFiles:
|
stubFiles:
|
||||||
- tests/phpstan/stubs/pthreads.stub
|
- tests/phpstan/stubs/pthreads.stub
|
||||||
- tests/phpstan/stubs/chunkutils.stub
|
- tests/phpstan/stubs/chunkutils.stub
|
||||||
|
- tests/phpstan/stubs/leveldb.stub
|
||||||
reportUnmatchedIgnoredErrors: false #no other way to silence platform-specific non-warnings
|
reportUnmatchedIgnoredErrors: false #no other way to silence platform-specific non-warnings
|
||||||
staticReflectionClassNamePatterns:
|
staticReflectionClassNamePatterns:
|
||||||
- "#^COM$#"
|
- "#^COM$#"
|
||||||
|
typeAliases:
|
||||||
|
#variadics don't work for this - mixed probably shouldn't work either, but for now it does
|
||||||
|
#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(mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed) : mixed'
|
||||||
|
anyClosure: '\Closure(mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed) : mixed'
|
||||||
|
@ -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";
|
||||||
@ -98,7 +102,7 @@ class CrashDump{
|
|||||||
private $server;
|
private $server;
|
||||||
/** @var resource */
|
/** @var resource */
|
||||||
private $fp;
|
private $fp;
|
||||||
/** @var int */
|
/** @var float */
|
||||||
private $time;
|
private $time;
|
||||||
/**
|
/**
|
||||||
* @var mixed[]
|
* @var mixed[]
|
||||||
@ -111,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();
|
||||||
@ -164,7 +170,9 @@ 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);
|
||||||
}
|
}
|
||||||
@ -176,7 +184,9 @@ class CrashDump{
|
|||||||
$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(),
|
||||||
@ -200,9 +210,16 @@ class CrashDump{
|
|||||||
|
|
||||||
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"] = "";
|
||||||
@ -228,7 +245,10 @@ class CrashDump{
|
|||||||
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",
|
||||||
@ -288,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:");
|
||||||
@ -303,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");
|
||||||
@ -314,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);
|
||||||
@ -325,6 +348,7 @@ class CrashDump{
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -332,6 +356,15 @@ class CrashDump{
|
|||||||
|
|
||||||
private function generalData() : void{
|
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;
|
||||||
@ -339,18 +372,22 @@ 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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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;
|
||||||
@ -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;
|
||||||
@ -225,7 +228,7 @@ class MemoryManager{
|
|||||||
|
|
||||||
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;
|
||||||
@ -271,6 +274,7 @@ class MemoryManager{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$cycles = gc_collect_cycles();
|
$cycles = gc_collect_cycles();
|
||||||
|
gc_mem_caches();
|
||||||
|
|
||||||
Timings::$garbageCollectorTimer->stopTiming();
|
Timings::$garbageCollectorTimer->stopTiming();
|
||||||
|
|
||||||
@ -304,6 +308,7 @@ class MemoryManager{
|
|||||||
*/
|
*/
|
||||||
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();
|
||||||
|
|
||||||
@ -403,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){
|
||||||
@ -418,8 +423,12 @@ 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);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -23,8 +23,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine {
|
namespace pocketmine {
|
||||||
|
|
||||||
|
use Composer\InstalledVersions;
|
||||||
use pocketmine\utils\Git;
|
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;
|
||||||
@ -34,7 +36,7 @@ namespace pocketmine {
|
|||||||
|
|
||||||
require_once __DIR__ . '/VersionInfo.php';
|
require_once __DIR__ . '/VersionInfo.php';
|
||||||
|
|
||||||
const MIN_PHP_VERSION = "7.2.0";
|
const MIN_PHP_VERSION = "7.4.0";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $message
|
* @param string $message
|
||||||
@ -72,7 +74,6 @@ namespace pocketmine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$extensions = [
|
$extensions = [
|
||||||
"bcmath" => "BC Math",
|
|
||||||
"curl" => "cURL",
|
"curl" => "cURL",
|
||||||
"ctype" => "ctype",
|
"ctype" => "ctype",
|
||||||
"date" => "Date",
|
"date" => "Date",
|
||||||
@ -205,6 +206,19 @@ namespace pocketmine {
|
|||||||
|
|
||||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||||
|
|
||||||
|
$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"]);
|
||||||
|
|
||||||
define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR);
|
define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR);
|
||||||
@ -214,7 +228,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
|
||||||
@ -279,7 +298,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 +307,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();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,7 @@ use pocketmine\updater\AutoUpdater;
|
|||||||
use pocketmine\utils\Config;
|
use pocketmine\utils\Config;
|
||||||
use pocketmine\utils\Internet;
|
use pocketmine\utils\Internet;
|
||||||
use pocketmine\utils\MainLogger;
|
use pocketmine\utils\MainLogger;
|
||||||
|
use pocketmine\utils\Process;
|
||||||
use pocketmine\utils\Terminal;
|
use pocketmine\utils\Terminal;
|
||||||
use pocketmine\utils\TextFormat;
|
use pocketmine\utils\TextFormat;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
@ -125,7 +126,6 @@ use function file_put_contents;
|
|||||||
use function filemtime;
|
use function filemtime;
|
||||||
use function function_exists;
|
use function function_exists;
|
||||||
use function get_class;
|
use function get_class;
|
||||||
use function getmypid;
|
|
||||||
use function getopt;
|
use function getopt;
|
||||||
use function gettype;
|
use function gettype;
|
||||||
use function implode;
|
use function implode;
|
||||||
@ -692,29 +692,32 @@ class Server{
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getPlayerDataPath(string $username) : string{
|
||||||
|
return $this->getDataPath() . '/players/' . strtolower($username) . '.dat';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the server has stored any saved data for this player.
|
* Returns whether the server has stored any saved data for this player.
|
||||||
*/
|
*/
|
||||||
public function hasOfflinePlayerData(string $name) : bool{
|
public function hasOfflinePlayerData(string $name) : bool{
|
||||||
$name = strtolower($name);
|
return file_exists($this->getPlayerDataPath($name));
|
||||||
return file_exists($this->getDataPath() . "players/$name.dat");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getOfflinePlayerData(string $name) : CompoundTag{
|
public function getOfflinePlayerData(string $name) : CompoundTag{
|
||||||
$name = strtolower($name);
|
$name = strtolower($name);
|
||||||
$path = $this->getDataPath() . "players/";
|
$path = $this->getPlayerDataPath($name);
|
||||||
if($this->shouldSavePlayerData()){
|
if($this->shouldSavePlayerData()){
|
||||||
if(file_exists($path . "$name.dat")){
|
if(file_exists($path)){
|
||||||
try{
|
try{
|
||||||
$nbt = new BigEndianNBTStream();
|
$nbt = new BigEndianNBTStream();
|
||||||
$compound = $nbt->readCompressed(file_get_contents($path . "$name.dat"));
|
$compound = $nbt->readCompressed(file_get_contents($path));
|
||||||
if(!($compound instanceof CompoundTag)){
|
if(!($compound instanceof CompoundTag)){
|
||||||
throw new \RuntimeException("Invalid data found in \"$name.dat\", expected " . CompoundTag::class . ", got " . (is_object($compound) ? get_class($compound) : gettype($compound)));
|
throw new \RuntimeException("Invalid data found in \"$name.dat\", expected " . CompoundTag::class . ", got " . (is_object($compound) ? get_class($compound) : gettype($compound)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $compound;
|
return $compound;
|
||||||
}catch(\Throwable $e){ //zlib decode error / corrupt data
|
}catch(\Throwable $e){ //zlib decode error / corrupt data
|
||||||
rename($path . "$name.dat", $path . "$name.dat.bak");
|
rename($path, $path . '.bak');
|
||||||
$this->logger->notice($this->getLanguage()->translateString("pocketmine.data.playerCorrupted", [$name]));
|
$this->logger->notice($this->getLanguage()->translateString("pocketmine.data.playerCorrupted", [$name]));
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@ -775,7 +778,7 @@ class Server{
|
|||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
$nbt = new BigEndianNBTStream();
|
$nbt = new BigEndianNBTStream();
|
||||||
try{
|
try{
|
||||||
file_put_contents($this->getDataPath() . "players/" . strtolower($name) . ".dat", $nbt->writeCompressed($ev->getSaveData()));
|
file_put_contents($this->getPlayerDataPath($name), $nbt->writeCompressed($ev->getSaveData()));
|
||||||
}catch(\Throwable $e){
|
}catch(\Throwable $e){
|
||||||
$this->logger->critical($this->getLanguage()->translateString("pocketmine.data.saveError", [$name, $e->getMessage()]));
|
$this->logger->critical($this->getLanguage()->translateString("pocketmine.data.saveError", [$name, $e->getMessage()]));
|
||||||
$this->logger->logException($e);
|
$this->logger->logException($e);
|
||||||
@ -1396,10 +1399,10 @@ class Server{
|
|||||||
Network::$BATCH_THRESHOLD = -1;
|
Network::$BATCH_THRESHOLD = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->networkCompressionLevel = (int) $this->getProperty("network.compression-level", 7);
|
$this->networkCompressionLevel = (int) $this->getProperty("network.compression-level", 6);
|
||||||
if($this->networkCompressionLevel < 1 or $this->networkCompressionLevel > 9){
|
if($this->networkCompressionLevel < 1 or $this->networkCompressionLevel > 9){
|
||||||
$this->logger->warning("Invalid network compression level $this->networkCompressionLevel set, setting to default 7");
|
$this->logger->warning("Invalid network compression level $this->networkCompressionLevel set, setting to default 6");
|
||||||
$this->networkCompressionLevel = 7;
|
$this->networkCompressionLevel = 6;
|
||||||
}
|
}
|
||||||
$this->networkCompressionAsync = (bool) $this->getProperty("network.async-compression", true);
|
$this->networkCompressionAsync = (bool) $this->getProperty("network.async-compression", true);
|
||||||
|
|
||||||
@ -1458,8 +1461,7 @@ class Server{
|
|||||||
|
|
||||||
$this->onlineMode = $this->getConfigBool("xbox-auth", true);
|
$this->onlineMode = $this->getConfigBool("xbox-auth", true);
|
||||||
if($this->onlineMode){
|
if($this->onlineMode){
|
||||||
$this->logger->notice($this->getLanguage()->translateString("pocketmine.server.auth.enabled"));
|
$this->logger->info($this->getLanguage()->translateString("pocketmine.server.auth.enabled"));
|
||||||
$this->logger->notice($this->getLanguage()->translateString("pocketmine.server.authProperty.enabled"));
|
|
||||||
}else{
|
}else{
|
||||||
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.auth.disabled"));
|
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.auth.disabled"));
|
||||||
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.authWarning"));
|
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.authWarning"));
|
||||||
@ -1539,7 +1541,7 @@ class Server{
|
|||||||
if(isset($options["generator"])){
|
if(isset($options["generator"])){
|
||||||
$generatorOptions = explode(":", $options["generator"]);
|
$generatorOptions = explode(":", $options["generator"]);
|
||||||
$generator = GeneratorManager::getGenerator(array_shift($generatorOptions));
|
$generator = GeneratorManager::getGenerator(array_shift($generatorOptions));
|
||||||
if(count($options) > 0){
|
if(count($generatorOptions) > 0){
|
||||||
$options["preset"] = implode(":", $generatorOptions);
|
$options["preset"] = implode(":", $generatorOptions);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@ -1665,7 +1667,7 @@ class Server{
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach($recipients as $recipient){
|
foreach($recipients as $recipient){
|
||||||
$recipient->addTitle($title, $subtitle, $fadeIn, $stay, $fadeOut);
|
$recipient->sendTitle($title, $subtitle, $fadeIn, $stay, $fadeOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
return count($recipients);
|
return count($recipients);
|
||||||
@ -1935,7 +1937,7 @@ class Server{
|
|||||||
}catch(\Throwable $e){
|
}catch(\Throwable $e){
|
||||||
$this->logger->logException($e);
|
$this->logger->logException($e);
|
||||||
$this->logger->emergency("Crashed while crashing, killing process");
|
$this->logger->emergency("Crashed while crashing, killing process");
|
||||||
@Utils::kill(getmypid());
|
@Process::kill(Process::pid());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -2091,17 +2093,24 @@ class Server{
|
|||||||
|
|
||||||
if($report){
|
if($report){
|
||||||
$url = ((bool) $this->getProperty("auto-report.use-https", true) ? "https" : "http") . "://" . $this->getProperty("auto-report.host", "crash.pmmp.io") . "/submit/api";
|
$url = ((bool) $this->getProperty("auto-report.use-https", true) ? "https" : "http") . "://" . $this->getProperty("auto-report.host", "crash.pmmp.io") . "/submit/api";
|
||||||
|
$postUrlError = "Unknown error";
|
||||||
$reply = Internet::postURL($url, [
|
$reply = Internet::postURL($url, [
|
||||||
"report" => "yes",
|
"report" => "yes",
|
||||||
"name" => $this->getName() . " " . $this->getPocketMineVersion(),
|
"name" => $this->getName() . " " . $this->getPocketMineVersion(),
|
||||||
"email" => "crash@pocketmine.net",
|
"email" => "crash@pocketmine.net",
|
||||||
"reportPaste" => base64_encode($dump->getEncodedData())
|
"reportPaste" => base64_encode($dump->getEncodedData())
|
||||||
]);
|
], 10, [], $postUrlError);
|
||||||
|
|
||||||
if($reply !== false and ($data = json_decode($reply)) !== null and isset($data->crashId) and isset($data->crashUrl)){
|
if($reply !== false and ($data = json_decode($reply)) !== null){
|
||||||
|
if(isset($data->crashId) and isset($data->crashUrl)){
|
||||||
$reportId = $data->crashId;
|
$reportId = $data->crashId;
|
||||||
$reportUrl = $data->crashUrl;
|
$reportUrl = $data->crashUrl;
|
||||||
$this->logger->emergency($this->getLanguage()->translateString("pocketmine.crash.archive", [$reportUrl, $reportId]));
|
$this->logger->emergency($this->getLanguage()->translateString("pocketmine.crash.archive", [$reportUrl, $reportId]));
|
||||||
|
}elseif(isset($data->error)){
|
||||||
|
$this->logger->emergency("Automatic crash report submission failed: $data->error");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
$this->logger->emergency("Failed to communicate with crash archive: $postUrlError");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2121,7 +2130,7 @@ class Server{
|
|||||||
echo "--- Waiting $spacing seconds to throttle automatic restart (you can kill the process safely now) ---" . PHP_EOL;
|
echo "--- Waiting $spacing seconds to throttle automatic restart (you can kill the process safely now) ---" . PHP_EOL;
|
||||||
sleep($spacing);
|
sleep($spacing);
|
||||||
}
|
}
|
||||||
@Utils::kill(getmypid());
|
@Process::kill(Process::pid());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2322,10 +2331,10 @@ class Server{
|
|||||||
|
|
||||||
private function titleTick() : void{
|
private function titleTick() : void{
|
||||||
Timings::$titleTickTimer->startTiming();
|
Timings::$titleTickTimer->startTiming();
|
||||||
$d = Utils::getRealMemoryUsage();
|
$d = Process::getRealMemoryUsage();
|
||||||
|
|
||||||
$u = Utils::getMemoryUsage(true);
|
$u = Process::getAdvancedMemoryUsage();
|
||||||
$usage = sprintf("%g/%g/%g/%g MB @ %d threads", round(($u[0] / 1024) / 1024, 2), round(($d[0] / 1024) / 1024, 2), round(($u[1] / 1024) / 1024, 2), round(($u[2] / 1024) / 1024, 2), Utils::getThreadCount());
|
$usage = sprintf("%g/%g/%g/%g MB @ %d threads", round(($u[0] / 1024) / 1024, 2), round(($d[0] / 1024) / 1024, 2), round(($u[1] / 1024) / 1024, 2), round(($u[2] / 1024) / 1024, 2), Process::getThreadCount());
|
||||||
|
|
||||||
echo "\x1b]0;" . $this->getName() . " " .
|
echo "\x1b]0;" . $this->getName() . " " .
|
||||||
$this->getPocketMineVersion() .
|
$this->getPocketMineVersion() .
|
||||||
|
@ -76,11 +76,9 @@ abstract class Thread extends \Thread{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int|null $options TODO: pthreads bug
|
|
||||||
*
|
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function start(?int $options = PTHREADS_INHERIT_ALL){
|
public function start(int $options = PTHREADS_INHERIT_ALL){
|
||||||
ThreadManager::getInstance()->add($this);
|
ThreadManager::getInstance()->add($this);
|
||||||
|
|
||||||
if($this->getClassLoader() === null){
|
if($this->getClassLoader() === null){
|
||||||
|
@ -33,6 +33,6 @@ 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.12.4";
|
const BASE_VERSION = "3.21.1";
|
||||||
const IS_DEVELOPMENT_BUILD = false;
|
const IS_DEVELOPMENT_BUILD = false;
|
||||||
const BUILD_NUMBER = 0;
|
const BUILD_NUMBER = 0;
|
||||||
|
@ -76,11 +76,9 @@ abstract class Worker extends \Worker{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int|null $options TODO: pthreads bug
|
|
||||||
*
|
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function start(?int $options = PTHREADS_INHERIT_ALL){
|
public function start(int $options = PTHREADS_INHERIT_ALL){
|
||||||
ThreadManager::getInstance()->add($this);
|
ThreadManager::getInstance()->add($this);
|
||||||
|
|
||||||
if($this->getClassLoader() === null){
|
if($this->getClassLoader() === null){
|
||||||
@ -97,7 +95,7 @@ abstract class Worker extends \Worker{
|
|||||||
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();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
@ -279,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ 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);
|
||||||
@ -137,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);
|
||||||
|
|
||||||
@ -168,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;
|
||||||
}
|
}
|
||||||
@ -194,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;
|
||||||
@ -154,7 +154,7 @@ 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.
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -204,7 +204,7 @@ 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
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -479,7 +479,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
*/
|
*/
|
||||||
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)));
|
||||||
|
@ -25,7 +25,7 @@ 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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
@ -52,7 +52,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
$item->pop();
|
$item->pop();
|
||||||
@ -65,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ class Dandelion 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() === 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;
|
||||||
}
|
}
|
||||||
@ -52,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;
|
||||||
|
@ -201,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,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;
|
||||||
}
|
}
|
||||||
@ -85,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ abstract class Fallable extends Solid{
|
|||||||
$nbt->setInt("TileID", $this->getId());
|
$nbt->setInt("TileID", $this->getId());
|
||||||
$nbt->setByte("Data", $this->getDamage());
|
$nbt->setByte("Data", $this->getDamage());
|
||||||
|
|
||||||
$fall = Entity::createEntity("FallingSand", $this->getLevel(), $nbt);
|
$fall = Entity::createEntity("FallingSand", $this->getLevelNonNull(), $nbt);
|
||||||
|
|
||||||
if($fall !== null){
|
if($fall !== null){
|
||||||
$fall->spawnToAll();
|
$fall->spawnToAll();
|
||||||
|
@ -69,7 +69,7 @@ class FenceGate 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->meta = ($player instanceof Player ? ($player->getDirection() - 1) & 0x03 : 0);
|
$this->meta = ($player instanceof Player ? ($player->getDirection() - 1) & 0x03 : 0);
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
$this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ class FenceGate extends Transparent{
|
|||||||
$this->meta |= (($player->getDirection() - 1) & 0x02);
|
$this->meta |= (($player->getDirection() - 1) & 0x02);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->getLevel()->setBlock($this, $this, true);
|
$this->getLevelNonNull()->setBlock($this, $this, true);
|
||||||
$this->level->addSound(new DoorSound($this));
|
$this->level->addSound(new DoorSound($this));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ class Fire extends Flowable{
|
|||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if(!$this->getSide(Vector3::SIDE_DOWN)->isSolid() and !$this->hasAdjacentFlammableBlocks()){
|
if(!$this->getSide(Vector3::SIDE_DOWN)->isSolid() and !$this->hasAdjacentFlammableBlocks()){
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
$this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||||
}else{
|
}else{
|
||||||
$this->level->scheduleDelayedBlockUpdate($this, mt_rand(30, 40));
|
$this->level->scheduleDelayedBlockUpdate($this, mt_rand(30, 40));
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ class Flower 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() === 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);
|
$this->getLevelNonNull()->setBlock($blockReplace, $this, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@ class Flower 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,19 +62,19 @@ class FlowerPot extends Flowable{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
$this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
|
||||||
Tile::createTile(Tile::FLOWER_POT, $this->getLevel(), TileFlowerPot::createNBT($this, $face, $item, $player));
|
Tile::createTile(Tile::FLOWER_POT, $this->getLevelNonNull(), TileFlowerPot::createNBT($this, $face, $item, $player));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
$pot = $this->getLevel()->getTile($this);
|
$pot = $this->getLevelNonNull()->getTile($this);
|
||||||
if(!($pot instanceof TileFlowerPot)){
|
if(!($pot instanceof TileFlowerPot)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -83,7 +83,7 @@ class FlowerPot extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->setDamage(self::STATE_FULL); //specific damage value is unnecessary, it just needs to be non-zero to show an item.
|
$this->setDamage(self::STATE_FULL); //specific damage value is unnecessary, it just needs to be non-zero to show an item.
|
||||||
$this->getLevel()->setBlock($this, $this, true, false);
|
$this->getLevelNonNull()->setBlock($this, $this, true, false);
|
||||||
$pot->setItem($item->pop());
|
$pot->setItem($item->pop());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -96,7 +96,7 @@ class FlowerPot extends Flowable{
|
|||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
$items = parent::getDropsForCompatibleTool($item);
|
$items = parent::getDropsForCompatibleTool($item);
|
||||||
|
|
||||||
$tile = $this->getLevel()->getTile($this);
|
$tile = $this->getLevelNonNull()->getTile($this);
|
||||||
if($tile instanceof TileFlowerPot){
|
if($tile instanceof TileFlowerPot){
|
||||||
$item = $tile->getItem();
|
$item = $tile->getItem();
|
||||||
if($item->getId() !== Item::AIR){
|
if($item->getId() !== Item::AIR){
|
||||||
|
@ -53,7 +53,7 @@ class GlazedTerracotta extends Solid{
|
|||||||
$this->meta = $faces[(~($player->getDirection() - 1)) & 0x03];
|
$this->meta = $faces[(~($player->getDirection() - 1)) & 0x03];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->getLevel()->setBlock($blockReplace, $this, true, true);
|
return $this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
public function getVariantBitmask() : int{
|
||||||
|
@ -53,6 +53,6 @@ class GlowingRedstoneOre extends RedstoneOre{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onRandomTick() : void{
|
public function onRandomTick() : void{
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::REDSTONE_ORE, $this->meta), false, false);
|
$this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::REDSTONE_ORE, $this->meta), false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,17 +100,17 @@ class Grass extends Solid{
|
|||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){
|
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){
|
||||||
$item->pop();
|
$item->pop();
|
||||||
TallGrassObject::growGrass($this->getLevel(), $this, new Random(mt_rand()), 8, 2);
|
TallGrassObject::growGrass($this->getLevelNonNull(), $this, new Random(mt_rand()), 8, 2);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}elseif($item instanceof Hoe){
|
}elseif($item instanceof Hoe){
|
||||||
$item->applyDamage(1);
|
$item->applyDamage(1);
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND));
|
$this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::FARMLAND));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}elseif($item instanceof Shovel and $this->getSide(Vector3::SIDE_UP)->getId() === Block::AIR){
|
}elseif($item instanceof Shovel and $this->getSide(Vector3::SIDE_UP)->getId() === Block::AIR){
|
||||||
$item->applyDamage(1);
|
$item->applyDamage(1);
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::GRASS_PATH));
|
$this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::GRASS_PATH));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ class HayBale 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);
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
$this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ class Ice extends Transparent{
|
|||||||
|
|
||||||
public function onBreak(Item $item, Player $player = null) : bool{
|
public function onBreak(Item $item, Player $player = null) : bool{
|
||||||
if(($player === null or $player->isSurvival()) and !$item->hasEnchantment(Enchantment::SILK_TOUCH)){
|
if(($player === null or $player->isSurvival()) and !$item->hasEnchantment(Enchantment::SILK_TOUCH)){
|
||||||
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::WATER), true);
|
return $this->getLevelNonNull()->setBlock($this, BlockFactory::get(Block::WATER), true);
|
||||||
}
|
}
|
||||||
return parent::onBreak($item, $player);
|
return parent::onBreak($item, $player);
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ class ItemFrame extends Flowable{
|
|||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
$tile = $this->level->getTile($this);
|
$tile = $this->level->getTile($this);
|
||||||
if(!($tile instanceof TileItemFrame)){
|
if(!($tile instanceof TileItemFrame)){
|
||||||
$tile = Tile::createTile(Tile::ITEM_FRAME, $this->getLevel(), TileItemFrame::createNBT($this));
|
$tile = Tile::createTile(Tile::ITEM_FRAME, $this->getLevelNonNull(), TileItemFrame::createNBT($this));
|
||||||
if(!($tile instanceof TileItemFrame)){
|
if(!($tile instanceof TileItemFrame)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -88,7 +88,7 @@ class ItemFrame extends Flowable{
|
|||||||
$this->meta = $faces[$face];
|
$this->meta = $faces[$face];
|
||||||
$this->level->setBlock($blockReplace, $this, true, true);
|
$this->level->setBlock($blockReplace, $this, true, true);
|
||||||
|
|
||||||
Tile::createTile(Tile::ITEM_FRAME, $this->getLevel(), TileItemFrame::createNBT($this, $face, $item, $player));
|
Tile::createTile(Tile::ITEM_FRAME, $this->getLevelNonNull(), TileItemFrame::createNBT($this, $face, $item, $player));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
|
use pocketmine\entity\Living;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
@ -58,7 +59,7 @@ class Ladder extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onEntityCollide(Entity $entity) : void{
|
public function onEntityCollide(Entity $entity) : void{
|
||||||
if($entity->asVector3()->floor()->distanceSquared($this) < 1){ //entity coordinates must be inside block
|
if($entity instanceof Living and $entity->asVector3()->floor()->distanceSquared($this) < 1){ //entity coordinates must be inside block
|
||||||
$entity->resetFallDistance();
|
$entity->resetFallDistance();
|
||||||
$entity->onGround = true;
|
$entity->onGround = true;
|
||||||
}
|
}
|
||||||
@ -100,7 +101,7 @@ class Ladder extends Transparent{
|
|||||||
];
|
];
|
||||||
if(isset($faces[$face])){
|
if(isset($faces[$face])){
|
||||||
$this->meta = $faces[$face];
|
$this->meta = $faces[$face];
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
$this->getLevelNonNull()->setBlock($blockReplace, $this, true, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -115,8 +115,8 @@ class Lava extends Liquid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
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{
|
||||||
$ret = $this->getLevel()->setBlock($this, $this, true, false);
|
$ret = $this->getLevelNonNull()->setBlock($this, $this, true, false);
|
||||||
$this->getLevel()->scheduleDelayedBlockUpdate($this, $this->tickRate());
|
$this->getLevelNonNull()->scheduleDelayedBlockUpdate($this, $this->tickRate());
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ class Leaves extends Transparent{
|
|||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if(($this->meta & 0b00001100) === 0){
|
if(($this->meta & 0b00001100) === 0){
|
||||||
$this->meta |= 0x08;
|
$this->meta |= 0x08;
|
||||||
$this->getLevel()->setBlock($this, $this, true, false);
|
$this->getLevelNonNull()->setBlock($this, $this, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,16 +155,16 @@ class Leaves extends Transparent{
|
|||||||
$ev = new LeavesDecayEvent($this);
|
$ev = new LeavesDecayEvent($this);
|
||||||
$ev->call();
|
$ev->call();
|
||||||
if($ev->isCancelled() or $this->findLog($this, $visited, 0)){
|
if($ev->isCancelled() or $this->findLog($this, $visited, 0)){
|
||||||
$this->getLevel()->setBlock($this, $this, false, false);
|
$this->getLevelNonNull()->setBlock($this, $this, false, false);
|
||||||
}else{
|
}else{
|
||||||
$this->getLevel()->useBreakOn($this);
|
$this->getLevelNonNull()->useBreakOn($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 |= 0x04;
|
$this->meta |= 0x04;
|
||||||
return $this->getLevel()->setBlock($this, $this, true);
|
return $this->getLevelNonNull()->setBlock($this, $this, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
public function getVariantBitmask() : int{
|
||||||
|
@ -418,6 +418,9 @@ abstract class Liquid extends Transparent{
|
|||||||
return $isOptimalFlowDirection;
|
return $isOptimalFlowDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @phpstan-impure This function modifies the adjacent sources count (premature optimisation)
|
||||||
|
*/
|
||||||
private function getSmallestFlowDecay(Block $block, int $decay) : int{
|
private function getSmallestFlowDecay(Block $block, int $decay) : int{
|
||||||
$blockDecay = $this->getFlowDecay($block);
|
$blockDecay = $this->getFlowDecay($block);
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ class MelonStem extends Crops{
|
|||||||
$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);
|
$this->getLevelNonNull()->setBlock($this, $ev->getNewState(), true);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
for($side = 2; $side <= 5; ++$side){
|
for($side = 2; $side <= 5; ++$side){
|
||||||
@ -64,7 +64,7 @@ class MelonStem extends Crops{
|
|||||||
$ev = new BlockGrowEvent($side, BlockFactory::get(Block::MELON_BLOCK));
|
$ev = new BlockGrowEvent($side, BlockFactory::get(Block::MELON_BLOCK));
|
||||||
$ev->call();
|
$ev->call();
|
||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
$this->getLevel()->setBlock($side, $ev->getNewState(), true);
|
$this->getLevelNonNull()->setBlock($side, $ev->getNewState(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,13 +64,13 @@ class Mycelium extends Solid{
|
|||||||
$x = mt_rand($this->x - 1, $this->x + 1);
|
$x = mt_rand($this->x - 1, $this->x + 1);
|
||||||
$y = mt_rand($this->y - 2, $this->y + 2);
|
$y = mt_rand($this->y - 2, $this->y + 2);
|
||||||
$z = mt_rand($this->z - 1, $this->z + 1);
|
$z = mt_rand($this->z - 1, $this->z + 1);
|
||||||
$block = $this->getLevel()->getBlockAt($x, $y, $z);
|
$block = $this->getLevelNonNull()->getBlockAt($x, $y, $z);
|
||||||
if($block->getId() === Block::DIRT){
|
if($block->getId() === Block::DIRT){
|
||||||
if($block->getSide(Vector3::SIDE_UP) instanceof Transparent){
|
if($block->getSide(Vector3::SIDE_UP) instanceof Transparent){
|
||||||
$ev = new BlockSpreadEvent($block, $this, BlockFactory::get(Block::MYCELIUM));
|
$ev = new BlockSpreadEvent($block, $this, BlockFactory::get(Block::MYCELIUM));
|
||||||
$ev->call();
|
$ev->call();
|
||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
$this->getLevel()->setBlock($block, $ev->getNewState());
|
$this->getLevelNonNull()->setBlock($block, $ev->getNewState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ class NetherWartPlant 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() === Block::SOUL_SAND){
|
if($down->getId() === Block::SOUL_SAND){
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, false, true);
|
$this->getLevelNonNull()->setBlock($blockReplace, $this, false, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ class NetherWartPlant extends Flowable{
|
|||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::SOUL_SAND){
|
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::SOUL_SAND){
|
||||||
$this->getLevel()->useBreakOn($this);
|
$this->getLevelNonNull()->useBreakOn($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ class NetherWartPlant 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(), false, true);
|
$this->getLevelNonNull()->setBlock($this, $ev->getNewState(), false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,6 @@ class Podzol extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
return 2.5;
|
return 0.5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,9 +40,13 @@ class Potato extends Crops{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [
|
$result = [
|
||||||
ItemFactory::get(Item::POTATO, 0, $this->getDamage() >= 0x07 ? mt_rand(1, 4) : 1)
|
ItemFactory::get(Item::POTATO, 0, $this->getDamage() >= 0x07 ? mt_rand(1, 5) : 1)
|
||||||
];
|
];
|
||||||
|
if($this->getDamage() >= 7 && mt_rand(0, 49) === 0){
|
||||||
|
$result[] = ItemFactory::get(Item::POISONOUS_POTATO);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPickedItem() : Item{
|
public function getPickedItem() : Item{
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user