mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-08 19:02:59 +00:00
Compare commits
709 Commits
Author | SHA1 | Date | |
---|---|---|---|
1614206a6d | |||
4f59c1b26c | |||
00916ade0c | |||
f4ee2912db | |||
03e8cd3ed4 | |||
7af4e70f64 | |||
92ed9e6125 | |||
c32026333f | |||
915224c8e5 | |||
734bc6c4a7 | |||
d36b24c518 | |||
d554d8060b | |||
b48243fd09 | |||
92cffc00d0 | |||
e87e974323 | |||
a3f6338626 | |||
21aef97ba7 | |||
ed0d1978aa | |||
d64561b0b1 | |||
d234d3e45e | |||
5056754cea | |||
2dc3cf8162 | |||
8c5a81cf5c | |||
2b58f2bafd | |||
5dadf12374 | |||
0d4e473bdd | |||
11cedc4011 | |||
3f2455f090 | |||
9d26a224a2 | |||
c4ad390463 | |||
42e14f749e | |||
3f07f06874 | |||
10279e11ed | |||
673e444456 | |||
89c49d77c6 | |||
c3a795e876 | |||
4199c3796f | |||
bf6af269c8 | |||
a29424f5b3 | |||
ff3af492f8 | |||
80b804f7aa | |||
3a78735982 | |||
ab32784c74 | |||
816234a379 | |||
b7bf92a5e9 | |||
dcca000ead | |||
c4ea51f985 | |||
8202bb1cd8 | |||
b75758e35e | |||
38a06f76f8 | |||
84f99ed418 | |||
fd63f19199 | |||
66d44aa814 | |||
f3089f577e | |||
9516ef1632 | |||
e982a57cb5 | |||
f57fa2252b | |||
02cc370855 | |||
0a5d14a840 | |||
3ec2994d7f | |||
786f416f2e | |||
a67d2ae978 | |||
089180fef4 | |||
fffa4b9501 | |||
71a8b0340c | |||
e544055bbc | |||
8f5db7c297 | |||
27f55e4c96 | |||
9b6b3f50a1 | |||
1fb0ba6fc0 | |||
f1d378468e | |||
25fb5140a2 | |||
f5a49b6d55 | |||
189f12a644 | |||
5a8917f6f2 | |||
f3e436592a | |||
35747874f6 | |||
59445902b8 | |||
2eb62c85f6 | |||
ad2a39bf13 | |||
0847358070 | |||
54f41dc145 | |||
ded45bddfe | |||
b044550475 | |||
a70fa15690 | |||
bd1d7b8d75 | |||
1513a0e092 | |||
c4150d4520 | |||
2f47597d75 | |||
ef97c8f99e | |||
84932ce908 | |||
6bfc309a0a | |||
06e8c6a3ad | |||
71271a0e03 | |||
b63ad032a9 | |||
d9b0e373bb | |||
32262d9bb5 | |||
4c1b10b24b | |||
61dc9d7f6b | |||
da9731ef59 | |||
e6f64c609e | |||
8c7fbf379b | |||
34a3e0d8b1 | |||
d42217ff57 | |||
39d02a67d2 | |||
77d45bf116 | |||
f79182852b | |||
a107ad7404 | |||
7a072931df | |||
f428a9bf52 | |||
2e720b48d9 | |||
a6e79bedf5 | |||
a5ba570fdf | |||
0d5164af02 | |||
534af770f8 | |||
79ed377c7a | |||
20f3030709 | |||
3aa58f54dc | |||
5c12a95151 | |||
5f07c5df1c | |||
5f33ef35e3 | |||
ec949840b2 | |||
e45e84b236 | |||
dfe68c9788 | |||
35b8f0bf25 | |||
d4dc1c8a0c | |||
517f9a3c3a | |||
636c35dcf1 | |||
d22f0da1de | |||
310de5a2b2 | |||
f84abcd1fe | |||
b5dd147ec7 | |||
0dd68e587f | |||
330e93e5e3 | |||
2020fcd18e | |||
456d9a722a | |||
344c980cff | |||
167492087f | |||
db215283a2 | |||
6a507bb149 | |||
a72e6ee706 | |||
89ea7f0a76 | |||
a6ca37429c | |||
4bf9fb278b | |||
15d81154e6 | |||
93e5c80962 | |||
7aa8bd18d3 | |||
53067c26d7 | |||
04581e2700 | |||
93597dcd50 | |||
778814a35e | |||
3cd1da196a | |||
365d4a1592 | |||
2d7f37ac47 | |||
50fcdd6e7e | |||
10317527e4 | |||
46ac4cbca1 | |||
cb9e79b398 | |||
2f1fad2745 | |||
44182dccbd | |||
2f3d2d4a0b | |||
8ac7f7f11f | |||
dbe7caab7b | |||
b581fab31a | |||
7b7dfc36d1 | |||
d63d6b73f6 | |||
a860ccd259 | |||
2bb497b716 | |||
613bd40601 | |||
398b636759 | |||
1257378198 | |||
758a68aa2c | |||
bfce478e72 | |||
681dd469a2 | |||
3edbea8545 | |||
ada8cbb545 | |||
0ac5e03ce9 | |||
9b02b8e51e | |||
6c7dada232 | |||
25bc95cd1e | |||
213bf8366a | |||
4e693e91e6 | |||
a1622fa345 | |||
0ec869932f | |||
79acaa3253 | |||
da3742b39e | |||
d26fcf7dee | |||
812424a619 | |||
1bdc61dd5f | |||
86fc33fe26 | |||
70eb41470c | |||
3a5709bf5e | |||
5ad66c3c9b | |||
7885b54824 | |||
532dc0fb6f | |||
54ccc330d5 | |||
e12618c705 | |||
7d5f2eac8d | |||
e964dd2ca8 | |||
dbb594f130 | |||
8f434b9edd | |||
34972c3327 | |||
037c34d961 | |||
4518d9d9ce | |||
1a5228e7a6 | |||
495bfda044 | |||
41b1fa7b48 | |||
e689fd545b | |||
889cd5e206 | |||
e1ddf90695 | |||
2f325b8c91 | |||
ac4f00be81 | |||
914450c30b | |||
25554f0d61 | |||
e1a61cb51a | |||
fe5620f097 | |||
faef4e8736 | |||
0d19f6c968 | |||
ecf662bf74 | |||
8cba2e0346 | |||
dfc8a6ffdd | |||
262728b091 | |||
4572ec8175 | |||
0f6949ac34 | |||
df8e0cf1f5 | |||
ad87c11ae1 | |||
fa82cb26d8 | |||
fd2a7797bd | |||
e5a2cfb65f | |||
b96bb7d824 | |||
896cca0778 | |||
59cf8e95f0 | |||
99038c752c | |||
88afedd1e8 | |||
c43e21235d | |||
3f7e7352fb | |||
32d6ea0fba | |||
28c787371a | |||
dba14c9f08 | |||
0e35ee8cb7 | |||
da5b7f47df | |||
d418dd7a09 | |||
f3209ccc33 | |||
4a4c28cd8c | |||
eba8d77034 | |||
13e4772f98 | |||
4bc2f28c6d | |||
663469dfa7 | |||
963abb718f | |||
1f2fb73297 | |||
ff55b520b9 | |||
cedd8abf0c | |||
496732999c | |||
6a8105f5a0 | |||
0a566f8218 | |||
829dd02eea | |||
b11c350b2b | |||
f624e36faf | |||
14ce9c10bb | |||
b27aaaeeb2 | |||
f1083bd9c4 | |||
199fa61aef | |||
af82a6bbe1 | |||
004f7ef82e | |||
89ebd2b880 | |||
799183e13e | |||
260ac47588 | |||
4ff4434a22 | |||
5d8bb84269 | |||
9eebfa7cc3 | |||
d3021c6281 | |||
9097d6c4d3 | |||
da43ae82fe | |||
60b405d944 | |||
92a752053d | |||
0537c66849 | |||
d94995e161 | |||
58bc08838b | |||
fc0619ee6e | |||
a5764b3ae9 | |||
8bf469f7fc | |||
3b9a5c5ccc | |||
4c36ca58e2 | |||
a67fa5c007 | |||
839a789180 | |||
e61c3e8bf6 | |||
7ce6c8aa13 | |||
9abcc99c10 | |||
5c8a625d88 | |||
259f0425a9 | |||
9cdea43794 | |||
e007fad5b8 | |||
5cf2fcbbb7 | |||
9e6cbb5b6a | |||
64b3d02974 | |||
640df1003c | |||
2b402e525a | |||
e2871fad8e | |||
41d02003c2 | |||
156ecd9bd8 | |||
fa7736efbb | |||
d71a7ff2fa | |||
8184a6b114 | |||
b8d44ff162 | |||
f6611a38bc | |||
24ed823d96 | |||
f624871b3f | |||
9cd6b3e1c7 | |||
aad1eb5b3e | |||
bff5bf25ae | |||
cda90fd7f1 | |||
9f44adf04a | |||
c4793241f5 | |||
7532c609fb | |||
13f28d8454 | |||
5a97c378fc | |||
e5d62ec901 | |||
cfd975009e | |||
73257ffde7 | |||
8252bea699 | |||
ea935a1af5 | |||
e8a5fa8a37 | |||
db734675d8 | |||
6ede56015d | |||
5334099fbf | |||
82e9072223 | |||
2c11742f9e | |||
bd4a63b668 | |||
cd36af46bf | |||
aa7d55e21d | |||
31e8efa6d1 | |||
facca13139 | |||
fffeeddca6 | |||
e6ba3ce8a6 | |||
11cae2f0c0 | |||
f5a18df835 | |||
1cc7027f92 | |||
8776b71d63 | |||
0b9d0f3cdc | |||
e419d76367 | |||
36cde9f352 | |||
05c602a044 | |||
0db7e57a15 | |||
205e47c0c4 | |||
e328d00cca | |||
ccbcc14600 | |||
e544bc0d4b | |||
fd27227cc7 | |||
b42966f61b | |||
ca86ec2ec2 | |||
97b6183404 | |||
0587d03c03 | |||
c7f1b605f2 | |||
f069df65a8 | |||
1e624e7bb9 | |||
f16a530849 | |||
7137b8a8a4 | |||
ab57914322 | |||
260869c0d5 | |||
9135877da1 | |||
07cb603231 | |||
f59094e6d6 | |||
d8acae5495 | |||
239fe909be | |||
c22576a266 | |||
bac788fd00 | |||
f6d96c5827 | |||
b1458db47b | |||
2d2c9379cd | |||
3400771770 | |||
e12ecaf629 | |||
1303cbfe02 | |||
ad4a211cba | |||
d1e56c4611 | |||
d9bbab54f4 | |||
07cf4eb7a9 | |||
50a7663369 | |||
651ef500a3 | |||
30f2e75278 | |||
2cfc25b4f8 | |||
5bded9cff8 | |||
5816ff85ba | |||
8f7d8347ee | |||
3614d9a78d | |||
818d0e19ab | |||
17720041a3 | |||
c329ff7d4f | |||
8794292788 | |||
0a39e580e9 | |||
c4580dd56d | |||
fab81d28bc | |||
039478223e | |||
64b5db4bf2 | |||
c85f4256c7 | |||
1192b8bdf1 | |||
6dcd2a4ece | |||
3fff0a0656 | |||
e1e1bfa5e3 | |||
1eedac87b2 | |||
cda3e6f4dc | |||
e6a58e2690 | |||
27350c4673 | |||
0d5704b156 | |||
f355044626 | |||
4794ba236a | |||
6490a49c70 | |||
5cd7e11b29 | |||
08e3b8ffdc | |||
9232f4509c | |||
cef77907c6 | |||
06ec8b8397 | |||
ee08286eca | |||
a83211f96a | |||
0b3c4ee496 | |||
54de518634 | |||
a908197907 | |||
3e23a568ca | |||
dadc5c1b87 | |||
a37d740111 | |||
2de0ec02ba | |||
d83820477f | |||
8726604899 | |||
9cbe378e8c | |||
494660102e | |||
216138a37e | |||
b08c38f8f9 | |||
911b6feaf9 | |||
2cb6990698 | |||
f7d66613df | |||
95c32d26df | |||
9e1f6a2486 | |||
76994f15ac | |||
cf73d74bd0 | |||
37a8d95464 | |||
9a4b72add5 | |||
919534d978 | |||
cb598155a4 | |||
00888fdc55 | |||
77795ae3bc | |||
f39fc7e525 | |||
77f7595e0e | |||
e8d3a25028 | |||
1370930ea9 | |||
70c3008b7b | |||
46930b98b7 | |||
92be8c8ec0 | |||
62069bc7af | |||
26230c1f9b | |||
a9fafbc5eb | |||
b8778cb791 | |||
73c5fe5cf9 | |||
b3cfa5a3a0 | |||
6127a02a8b | |||
dbca36e5e2 | |||
1171bae691 | |||
494f8e8251 | |||
3c9af56e06 | |||
40a2211a5a | |||
0196aa21d7 | |||
833f3e574b | |||
a386ff8ce7 | |||
e6c3b0fc0d | |||
9568364277 | |||
73d4ff6b52 | |||
7e98aa1497 | |||
f00c69c513 | |||
50a4c42f3f | |||
6b61efcfc8 | |||
1a99938e4b | |||
a4d68fb32b | |||
5682cc8d53 | |||
4eb59c0372 | |||
3486db3f1b | |||
733d530ed0 | |||
c10ce84035 | |||
82d9e481d2 | |||
d27c7f7141 | |||
394c999710 | |||
6399dacba7 | |||
b6bbf655d7 | |||
3d2c018442 | |||
da8c54cf8b | |||
8e984a1bc3 | |||
124e60301a | |||
4d13c48e5c | |||
9159e8f002 | |||
f5aa461945 | |||
16817ff301 | |||
18863b1098 | |||
e3cffca34b | |||
d20d9fb689 | |||
7b1ae2a822 | |||
8ecf5e02b9 | |||
39c607cbd5 | |||
d867ffc60d | |||
c57eb26fd5 | |||
c35d91a104 | |||
9fc260fb1a | |||
73d0f799c2 | |||
ecb2e6e3af | |||
7b75b6928d | |||
753a8a6937 | |||
bc76b1cafe | |||
00e415fc79 | |||
dbbe1f2d5c | |||
740f0a2314 | |||
7fdfe947b0 | |||
b7c4379700 | |||
20b7418916 | |||
85521f5e7a | |||
f37ea6a203 | |||
abf8081ebc | |||
8594cb3e74 | |||
d155de35ed | |||
e37c8e3a5d | |||
e38c0c0fe1 | |||
ce27c03774 | |||
c4a8781b5c | |||
dbab8b5733 | |||
2b08bbc7b1 | |||
17037f5e9c | |||
fee3c17148 | |||
25e6cb74b3 | |||
8d2e59222e | |||
cd778661c2 | |||
c2afc05e7c | |||
9be95bf263 | |||
4b65e1cbe1 | |||
5caae37768 | |||
92e1811b06 | |||
293c2710d0 | |||
8a7017fd6b | |||
15f8886958 | |||
3226a9dc6a | |||
1a1e3ff63b | |||
ea413d0882 | |||
0890b5fc99 | |||
163ed225f2 | |||
a4a6d3e094 | |||
ecbf3e9722 | |||
47a959dace | |||
3968f85c82 | |||
d8188b807a | |||
8e68655fc7 | |||
6d109bfc6f | |||
b7a5a53c9d | |||
76bd0f452c | |||
363556e9b6 | |||
6f08853b29 | |||
42d8357821 | |||
f2ac63d235 | |||
5d17405b92 | |||
3dd53ad998 | |||
a303c4b294 | |||
fa56290bb4 | |||
01d6cbe9c3 | |||
f682c16740 | |||
74c09dc202 | |||
0917b67573 | |||
5cb0eafcb2 | |||
221e6db47d | |||
8d06018d81 | |||
600e16d9f6 | |||
4340349db7 | |||
6105198313 | |||
c96ba13c23 | |||
c8d0cb315b | |||
be9c413a9e | |||
3e4366b30d | |||
7f3460190b | |||
10d44292e1 | |||
70f81334ae | |||
ead572fab9 | |||
ef8e286277 | |||
ba5a5981a0 | |||
c428596009 | |||
a81d8dd6d5 | |||
5bcbef90ea | |||
1c67f094e3 | |||
99d350914e | |||
49a9e0a880 | |||
7b152def7d | |||
3eb78fb0ff | |||
38c759c86e | |||
314ce1d012 | |||
7fcd40df15 | |||
ba39327b28 | |||
8d2e3894ef | |||
8ee0fbccc5 | |||
fe4354959b | |||
19377c86a4 | |||
fb23aade34 | |||
57e9fe78a3 | |||
6b97281c58 | |||
da67a085fc | |||
e2fc7cdf88 | |||
635bb08fb9 | |||
308d9ce3a8 | |||
5a76c38363 | |||
54530da6c1 | |||
dd55a0bccd | |||
f03bd982b5 | |||
025cb73bf5 | |||
2a6ffb5aa9 | |||
d53b84386f | |||
a7ed933b37 | |||
29cc9283f8 | |||
e60962c31f | |||
f6b5301e17 | |||
73b923e3a1 | |||
d2e4eb40b3 | |||
6a31628e78 | |||
bfb1ad1327 | |||
dfa603c335 | |||
eef979db4c | |||
6166c90bfd | |||
35d1d0080a | |||
3bacb1a9cb | |||
898af49e97 | |||
3061eb4157 | |||
b8d1d8f212 | |||
8c6189775b | |||
932418b951 | |||
95812252d6 | |||
7dec912d15 | |||
dbd36d66ae | |||
40b4166a6e | |||
51d18ffb89 | |||
af3c7b7c76 | |||
3511ac010d | |||
cac3c356a5 | |||
07f19dd4a1 | |||
17a17c31f3 | |||
75742b487f | |||
4e9a2b6d8c | |||
4ea907ae1a | |||
8b912c1363 | |||
080209c469 | |||
5b11ddee35 | |||
3b7ded0ba3 | |||
c5d3e9be76 | |||
714f4dc023 | |||
a86bcd5110 | |||
7ffc477d76 | |||
4cb0b319c0 | |||
5ebe9859e9 | |||
cd2b60a860 | |||
5edff79f5f | |||
0c91d568b4 | |||
35fabc7765 | |||
b5a98a993f | |||
0840ba8067 | |||
274cf58ccf | |||
1bce5d0bc2 | |||
0d5d5e21a8 | |||
a145e18c1e | |||
d1ca779c1a | |||
abbb8bbf55 | |||
86c7870427 | |||
48080b7f90 | |||
b216fb8910 | |||
d3171d6a8e | |||
c063a4da29 | |||
cc79dfa64c | |||
d6b9950901 | |||
1815fe5b46 | |||
3e993250d8 | |||
1163ac1d7a | |||
9a51ba697a | |||
32ad9d0c1a | |||
3d840e969d | |||
d1b70bd400 | |||
29f002b32c | |||
da17ade575 | |||
f0c36f3413 | |||
77d8f133f1 | |||
43ebb23085 | |||
e198c8fa8b | |||
cc3285c8fe | |||
305c63ba4d | |||
acaa0e33b0 | |||
f63857deed | |||
eda3d9b5e4 | |||
c3872619cd | |||
39cc590829 | |||
f347345bb3 | |||
bb05cfb36c | |||
7d5c3c9b46 | |||
cff2d37add | |||
447477c5fb | |||
abdbb2bf0e | |||
783c13926f | |||
45329ddf67 | |||
20af789963 | |||
93cb9390e0 | |||
0aed7f86f5 | |||
bf44bd016d | |||
04e4a36653 | |||
7439e1971d | |||
b961b4e003 | |||
d9eac8fc0a | |||
aeeee5eb53 | |||
13994055d9 | |||
247875e3d5 | |||
ee60a7bc36 | |||
348c2a599b | |||
562b47a1e5 | |||
4e060bc13f | |||
2807f14fcd |
7
.gitignore
vendored
7
.gitignore
vendored
@ -13,6 +13,7 @@ server.properties
|
||||
memory_dumps/*
|
||||
resource_packs/
|
||||
server.lock
|
||||
/phpstan.neon
|
||||
|
||||
# Common IDEs
|
||||
.idea/
|
||||
@ -40,3 +41,9 @@ test_data/*
|
||||
|
||||
# Doxygen
|
||||
Documentation/*
|
||||
|
||||
# PHPUnit
|
||||
/.phpunit.result.cache
|
||||
|
||||
# php-cs-fixer
|
||||
/.php_cs.cache
|
||||
|
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -7,9 +7,9 @@
|
||||
[submodule "tests/plugins/PocketMine-DevTools"]
|
||||
path = tests/plugins/PocketMine-DevTools
|
||||
url = https://github.com/pmmp/PocketMine-DevTools.git
|
||||
[submodule "src/pocketmine/resources/vanilla"]
|
||||
path = src/pocketmine/resources/vanilla
|
||||
url = https://github.com/pmmp/BedrockData.git
|
||||
[submodule "build/php"]
|
||||
path = build/php
|
||||
url = https://github.com/pmmp/php-build-scripts.git
|
||||
[submodule "src/pocketmine/resources/vanilla"]
|
||||
path = src/pocketmine/resources/vanilla
|
||||
url = https://github.com/pmmp/BedrockData.git
|
||||
|
16
.travis.yml
16
.travis.yml
@ -5,21 +5,29 @@ php:
|
||||
- 7.3
|
||||
|
||||
before_script:
|
||||
# - pecl install channel://pecl.php.net/pthreads-3.1.6
|
||||
- echo | pecl install channel://pecl.php.net/yaml-2.0.4
|
||||
- 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 6ca019c58b4fa09ee2ff490f2444e34bef0773d0
|
||||
- git checkout 646dac62ae0d48c1ada7b007e15575fb84f7d71d
|
||||
- phpize
|
||||
- ./configure
|
||||
- make
|
||||
- make install
|
||||
- cd ..
|
||||
- echo "extension=pthreads.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
|
||||
- composer install
|
||||
|
||||
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
|
||||
|
38
BUILDING.md
Normal file
38
BUILDING.md
Normal file
@ -0,0 +1,38 @@
|
||||
# Building
|
||||
## Pre-requisites
|
||||
- A bash shell (git bash is sufficient for Windows)
|
||||
- [`git`](https://git-scm.com) available in your shell
|
||||
- PHP 7.2 or newer available in your shell
|
||||
- [`composer`](https://getcomposer.org) available in your shell
|
||||
|
||||
## Custom PHP binaries
|
||||
Because PocketMine-MP requires several non-standard PHP extensions and configuration, PMMP provides scripts to build custom binaries for running PocketMine-MP, as well as prebuilt binaries.
|
||||
|
||||
- [Prebuilt binaries](https://jenkins.pmmp.io/job/PHP-7.3-Aggregate)
|
||||
- [Compile scripts](https://github.com/pmmp/php-build-scripts) are provided as a submodule in the path `build/php`
|
||||
|
||||
If you use a custom binary, you'll need to replace `composer` usages in this guide with `path/to/your/php path/to/your/composer.phar`.
|
||||
|
||||
## Setting up environment
|
||||
1. `git clone --recursive https://github.com/pmmp/PocketMine-MP.git`
|
||||
2. `composer install`
|
||||
|
||||
## Checking out a different branch to build
|
||||
1. `git checkout <branch to checkout>`
|
||||
2. `git submodule update --init`
|
||||
3. Re-run `composer install` to synchronize dependencies.
|
||||
|
||||
## Optimizing for release builds
|
||||
1. Add the flags `--no-dev --classmap-authoritative` to your `composer install` command. This will reduce build size and improve autoloading speed.
|
||||
2. Preprocess the source code by running `build/preprocessor/PreProcessor.php`. Usage instructions are provided in `build/preprocessor/README.md`.
|
||||
|
||||
### Note
|
||||
Preprocessor requires that the `cpp` (c preprocessor) is available in your PATH.
|
||||
|
||||
## Building `PocketMine-MP.phar`
|
||||
Run `build/server-phar.php` 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.
|
||||
|
||||
## Running PocketMine-MP from source code
|
||||
Run `src/pocketmine/PocketMine.php` using your preferred PHP binary.
|
@ -13,10 +13,11 @@
|
||||
|
||||
## Discussion/Help
|
||||
- [Forums](https://forums.pmmp.io/)
|
||||
- [Community Discord](https://discord.gg/bmSAZBG)
|
||||
- [Discord](https://discord.gg/bmSAZBG)
|
||||
- [StackOverflow](https://stackoverflow.com/tags/pocketmine)
|
||||
|
||||
## For developers
|
||||
* [Building and running from source](BUILDING.md)
|
||||
* [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
|
||||
* [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
|
||||
@ -25,6 +26,7 @@
|
||||
## Donate
|
||||
- Bitcoin Cash (BCH): `qq3r46hn6ljnhnqnfwxt5pg3g447eq9jhvw5ddfear`
|
||||
- Bitcoin (BTC): `171u8K9e4FtU6j3e5sqNoxKUgEw9qWQdRV`
|
||||
- Stellar Lumens (XLM): `GAAC5WZ33HCTE3BFJFZJXONMEIBNHFLBXM2HJVAZHXXPYA3HP5XPPS7T`
|
||||
- [Patreon](https://www.patreon.com/pocketminemp)
|
||||
|
||||
## Licensing information
|
||||
|
@ -21,14 +21,13 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\build_script;
|
||||
namespace pocketmine\build\make_release;
|
||||
|
||||
use pocketmine\utils\VersionString;
|
||||
use function dirname;
|
||||
use function fgets;
|
||||
use function file_get_contents;
|
||||
use function file_put_contents;
|
||||
use function preg_quote;
|
||||
use function preg_replace;
|
||||
use function sleep;
|
||||
use function sprintf;
|
||||
@ -36,20 +35,8 @@ use function system;
|
||||
use const pocketmine\BASE_VERSION;
|
||||
use const STDIN;
|
||||
|
||||
require_once dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
|
||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
if(isset($argv[1])){
|
||||
$currentVer = new VersionString($argv[1]);
|
||||
}else{
|
||||
$currentVer = new VersionString(BASE_VERSION);
|
||||
}
|
||||
$nextVer = new VersionString(sprintf(
|
||||
"%u.%u.%u",
|
||||
$currentVer->getMajor(),
|
||||
$currentVer->getMinor(),
|
||||
$currentVer->getPatch() + 1
|
||||
));
|
||||
|
||||
function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev) : void{
|
||||
$versionInfo = file_get_contents($versionInfoPath);
|
||||
@ -60,22 +47,45 @@ function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev
|
||||
);
|
||||
$versionInfo = preg_replace(
|
||||
'/^const IS_DEVELOPMENT_BUILD = (?:true|false);$/m',
|
||||
'const IS_DEVELOPMENT_BUILD = ' . ($isDev ? 'true' : 'false'). ';',
|
||||
'const IS_DEVELOPMENT_BUILD = ' . ($isDev ? 'true' : 'false') . ';',
|
||||
$versionInfo
|
||||
);
|
||||
file_put_contents($versionInfoPath, $versionInfo);
|
||||
}
|
||||
$versionInfoPath = dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
|
||||
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false);
|
||||
|
||||
echo "please add appropriate notes to the changelog and press enter...";
|
||||
fgets(STDIN);
|
||||
system('git add "' . dirname(__DIR__) . '/changelogs"');
|
||||
system('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"');
|
||||
system('git tag ' . $currentVer->getBaseVersion());
|
||||
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true);
|
||||
system('git add "' . $versionInfoPath . '"');
|
||||
system('git commit -m "' . $nextVer->getBaseVersion() . ' is next" --include "' . $versionInfoPath . '"');
|
||||
echo "pushing changes in 10 seconds\n";
|
||||
sleep(10);
|
||||
system('git push origin HEAD ' . $currentVer->getBaseVersion());
|
||||
/**
|
||||
* @param string[] $argv
|
||||
* @phpstan-param list<string> $argv
|
||||
*/
|
||||
function main(array $argv) : void{
|
||||
if(isset($argv[1])){
|
||||
$currentVer = new VersionString($argv[1]);
|
||||
}else{
|
||||
$currentVer = new VersionString(BASE_VERSION);
|
||||
}
|
||||
$nextVer = new VersionString(sprintf(
|
||||
"%u.%u.%u",
|
||||
$currentVer->getMajor(),
|
||||
$currentVer->getMinor(),
|
||||
$currentVer->getPatch() + 1
|
||||
));
|
||||
|
||||
$versionInfoPath = dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
|
||||
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false);
|
||||
|
||||
echo "please add appropriate notes to the changelog and press enter...";
|
||||
fgets(STDIN);
|
||||
system('git add "' . dirname(__DIR__) . '/changelogs"');
|
||||
system('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"');
|
||||
system('git tag ' . $currentVer->getBaseVersion());
|
||||
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true);
|
||||
system('git add "' . $versionInfoPath . '"');
|
||||
system('git commit -m "' . $nextVer->getBaseVersion() . ' is next" --include "' . $versionInfoPath . '"');
|
||||
echo "pushing changes in 5 seconds\n";
|
||||
sleep(5);
|
||||
system('git push origin HEAD ' . $currentVer->getBaseVersion());
|
||||
}
|
||||
|
||||
if(!defined('pocketmine\_PHPSTAN_ANALYSIS')){
|
||||
main($argv);
|
||||
}
|
||||
|
Submodule build/php updated: ffc465f4f8...0aa88d2765
Submodule build/preprocessor updated: b01f50c50e...da363df5f1
174
build/server-phar.php
Normal file
174
build/server-phar.php
Normal file
@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\build\server_phar;
|
||||
|
||||
use pocketmine\utils\Git;
|
||||
use function array_map;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function dirname;
|
||||
use function file_exists;
|
||||
use function getcwd;
|
||||
use function getopt;
|
||||
use function implode;
|
||||
use function ini_get;
|
||||
use function microtime;
|
||||
use function preg_quote;
|
||||
use function realpath;
|
||||
use function round;
|
||||
use function rtrim;
|
||||
use function sprintf;
|
||||
use function str_replace;
|
||||
use function unlink;
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
/**
|
||||
* @param string[] $strings
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
function preg_quote_array(array $strings, string $delim = null) : array{
|
||||
return array_map(function(string $str) use ($delim) : string{ return preg_quote($str, $delim); }, $strings);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $includedPaths
|
||||
* @param mixed[] $metadata
|
||||
* @phpstan-param array<string, mixed> $metadata
|
||||
*
|
||||
* @return \Generator|string[]
|
||||
*/
|
||||
function buildPhar(string $pharPath, string $basePath, array $includedPaths, array $metadata, string $stub, int $signatureAlgo = \Phar::SHA1, ?int $compression = null){
|
||||
$basePath = rtrim(str_replace("/", DIRECTORY_SEPARATOR, $basePath), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||
$includedPaths = array_map(function(string $path) : string{
|
||||
return rtrim(str_replace("/", DIRECTORY_SEPARATOR, $path), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||
}, $includedPaths);
|
||||
yield "Creating output file $pharPath";
|
||||
if(file_exists($pharPath)){
|
||||
yield "Phar file already exists, overwriting...";
|
||||
try{
|
||||
\Phar::unlinkArchive($pharPath);
|
||||
}catch(\PharException $e){
|
||||
//unlinkArchive() doesn't like dodgy phars
|
||||
unlink($pharPath);
|
||||
}
|
||||
}
|
||||
|
||||
yield "Adding files...";
|
||||
|
||||
$start = microtime(true);
|
||||
$phar = new \Phar($pharPath);
|
||||
$phar->setMetadata($metadata);
|
||||
$phar->setStub($stub);
|
||||
$phar->setSignatureAlgorithm($signatureAlgo);
|
||||
$phar->startBuffering();
|
||||
|
||||
//If paths contain any of these, they will be excluded
|
||||
$excludedSubstrings = preg_quote_array([
|
||||
realpath($pharPath), //don't add the phar to itself
|
||||
], '/');
|
||||
|
||||
$folderPatterns = preg_quote_array([
|
||||
DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR,
|
||||
DIRECTORY_SEPARATOR . '.' //"Hidden" files, git dirs etc
|
||||
], '/');
|
||||
|
||||
//Only exclude these within the basedir, otherwise the project won't get built if it itself is in a directory that matches these patterns
|
||||
$basePattern = preg_quote(rtrim($basePath, DIRECTORY_SEPARATOR), '/');
|
||||
foreach($folderPatterns as $p){
|
||||
$excludedSubstrings[] = $basePattern . '.*' . $p;
|
||||
}
|
||||
|
||||
$regex = sprintf('/^(?!.*(%s))^%s(%s).*/i',
|
||||
implode('|', $excludedSubstrings), //String may not contain any of these substrings
|
||||
preg_quote($basePath, '/'), //String must start with this path...
|
||||
implode('|', preg_quote_array($includedPaths, '/')) //... and must be followed by one of these relative paths, if any were specified. If none, this will produce a null capturing group which will allow anything.
|
||||
);
|
||||
|
||||
$directory = new \RecursiveDirectoryIterator($basePath, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS | \FilesystemIterator::CURRENT_AS_PATHNAME); //can't use fileinfo because of symlinks
|
||||
$iterator = new \RecursiveIteratorIterator($directory);
|
||||
$regexIterator = new \RegexIterator($iterator, $regex);
|
||||
|
||||
$count = count($phar->buildFromIterator($regexIterator, $basePath));
|
||||
yield "Added $count files";
|
||||
|
||||
if($compression !== null){
|
||||
yield "Compressing files...";
|
||||
$phar->compressFiles($compression);
|
||||
yield "Finished compression";
|
||||
}
|
||||
$phar->stopBuffering();
|
||||
|
||||
yield "Done in " . round(microtime(true) - $start, 3) . "s";
|
||||
}
|
||||
|
||||
function main() : void{
|
||||
if(ini_get("phar.readonly") == 1){
|
||||
echo "Set phar.readonly to 0 with -dphar.readonly=0" . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$opts = getopt("", ["out:", "git:"]);
|
||||
if(isset($opts["git"])){
|
||||
$gitHash = $opts["git"];
|
||||
}else{
|
||||
$gitHash = Git::getRepositoryStatePretty(dirname(__DIR__));
|
||||
echo "Git hash detected as $gitHash" . PHP_EOL;
|
||||
}
|
||||
foreach(buildPhar(
|
||||
$opts["out"] ?? getcwd() . DIRECTORY_SEPARATOR . "PocketMine-MP.phar",
|
||||
dirname(__DIR__) . DIRECTORY_SEPARATOR,
|
||||
[
|
||||
'src',
|
||||
'vendor'
|
||||
],
|
||||
[
|
||||
'git' => $gitHash
|
||||
],
|
||||
<<<'STUB'
|
||||
<?php
|
||||
|
||||
$tmpDir = sys_get_temp_dir();
|
||||
if(!is_readable($tmpDir) or !is_writable($tmpDir)){
|
||||
echo "ERROR: tmpdir $tmpDir is not accessible." . PHP_EOL;
|
||||
echo "Check that the directory exists, and that the current user has read/write permissions for it." . PHP_EOL;
|
||||
echo "Alternatively, set 'sys_temp_dir' to a different directory in your php.ini file." . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require("phar://" . __FILE__ . "/src/pocketmine/PocketMine.php");
|
||||
__HALT_COMPILER();
|
||||
STUB
|
||||
,
|
||||
\Phar::SHA1,
|
||||
\Phar::GZ
|
||||
) as $line){
|
||||
echo $line . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
if(!defined('pocketmine\_PHPSTAN_ANALYSIS')){
|
||||
main();
|
||||
}
|
20
changelogs/3.10.md
Normal file
20
changelogs/3.10.md
Normal file
@ -0,0 +1,20 @@
|
||||
**For Minecraft: Bedrock Edition 1.13.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.10.0
|
||||
- Added support for Minecraft: Bedrock Edition 1.13.0
|
||||
- Removed compatibility with 1.12.0
|
||||
|
||||
## Note about skins
|
||||
PocketMine-MP **does not support skins made in the Charactor Creator** (known as Persona skins), due to technical changes which would require premature backwards compatibility breaks. The dev team has decided not to support Persona yet.
|
||||
These skins will be **replaced with a random solid-colour skin. This is not a bug.**
|
||||
Skins chosen from the Classic tab (classic skins) will continue to work as normal.
|
||||
|
||||
# 3.10.1
|
||||
- Fixed custom plugin-created skins being invisible when no geometry name was specified.
|
||||
- Updated RakLib to 0.12.6 to fix security bugs.
|
97
changelogs/3.11.md
Normal file
97
changelogs/3.11.md
Normal file
@ -0,0 +1,97 @@
|
||||
**For Minecraft: Bedrock Edition 1.14.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.11.0
|
||||
- Added support for Minecraft: Bedrock Edition 1.14.0
|
||||
- Removed compatibility with 1.13.0
|
||||
|
||||
# 3.11.1
|
||||
- Fixed blocks with incorrect properties when placed or interacted with.
|
||||
|
||||
# 3.11.2
|
||||
## Core
|
||||
- PHPStan 0.12.3 with level 5 is now used for automated static analysis.
|
||||
- Fixed a possible crash when plugins override the `EnderChest` tile class with something incompatible.
|
||||
- Fixed disconnected players being considered as never played.
|
||||
- Fixed enchantments with IDs outside the range 0-255 in item NBT crashing the server.
|
||||
- Fixed particles rendering incorrectly.
|
||||
- Timings handlers are no longer able to underflow; they now throw exceptions when attempting to be stopped more times than they were started.
|
||||
- Fixed explosion rays getting stuck in empty subchunks (possible incorrect behaviour in large caves).
|
||||
- Fixed bad tile/entity NBT data being propagated from world providers in some cases.
|
||||
- Fixed a possible crash when detecting timezone on CentOS.
|
||||
- Fixed many cases of incorrectly documented types in the API found by PHPStan.
|
||||
- Generation tasks no longer assume that generator instances stored in TLS are always valid, fixing a possible crash.
|
||||
|
||||
## Protocol
|
||||
- Fixed skin animation image corruption in LoginPacket handling caused by incorrect data handling.
|
||||
- Fixed skin animation extra data not being decoded from LoginPacket.
|
||||
- `SkinImage` now throws `InvalidArgumentException` if it receives an unexpected amount of bytes for the given image heigh/width.
|
||||
- Fixed broken code in `PlayerAuthInputPacket::create()`.
|
||||
- Removed some dead constants from `NetworkInventoryAction`.
|
||||
|
||||
# 3.11.3
|
||||
- Fixed some PHPStan false-positives in release builds.
|
||||
- Git hash is now correctly detected for source builds when the working directory is not the repository root.
|
||||
- Added a specialized build script `build/server-phar.php` for creating server phars.
|
||||
- Fixed timings crashing the server.
|
||||
- Timings chains now work correctly.
|
||||
- Fixed some minor timing errors in chained timings.
|
||||
- Forcing resource packs no longer causes removal of client-sided resource packs. If this behaviour is desired, use a vanilla resource pack at the bottom of your resource stack (as was necessary for non-forced packs).
|
||||
- Added documentation to the API to clarify that effect durations are in ticks.
|
||||
|
||||
# 3.11.4
|
||||
- Fixed performance issue in leaf decay.
|
||||
- Fixed entity position desync when entities stop moving, but still have velocity on the client.
|
||||
- Fixed a crash when encountering truncated `level.dat` files in LevelDB worlds.
|
||||
- Core code is now analyzed using PHPStan level 6.
|
||||
- The core constants `pocketmine\PATH` and `pocketmine\RESOURCE_PATH` are now unconditionally available when including the Composer autoloader.
|
||||
- Populate type information in lots of places where it was previously missing; this will improve the quality of static analysis for plugins.
|
||||
- `MainLogger::logException()` now logs previous exceptions recursively.
|
||||
- `MainLogger::logException()` now always logs exceptions as `critical`.
|
||||
|
||||
# 3.11.5
|
||||
- PHPStan and PHPUnit are now managed as Composer dev dependencies.
|
||||
- Core code is now analyzed using PHPStan level 6 (full, including iterable types checking).
|
||||
- Improved type information available to PHPStan in many areas.
|
||||
- Mass-removal of useless PHPDoc.
|
||||
- Fixed incorrect documentation of `Internet::getURL()`, `Internet::postURL()` and `Internet::simpleCurl()`.
|
||||
- Fixed crash on use of case-mismatched recursive command aliases.
|
||||
- Basic build instructions are now provided in `BUILDING.md`.
|
||||
- `build/server-phar.php` now uses GZIP compression on created phars, providing a 75% size reduction.
|
||||
- `ClientboundMapItemDataPacket` now uses `MapDecoration` objects for decorations instead of associative arrays.
|
||||
- Updated Composer dependencies to get bug fixes in `pocketmine/nbt` and other libraries.
|
||||
- Packages `pocketmine/classloader` and `pocketmine/log` are now required; these provide classes previously part of `pocketmine/spl`. This change has no effect on API compatibility.
|
||||
|
||||
# 3.11.6
|
||||
- Core code, tests and build scripts are now analyzed using `phpstan-strict-rules` and `phpstan-phpunit` rules.
|
||||
- Added more PHPStan-specific type annotations to improve static analysis.
|
||||
- Fixed more incorrect PHPDoc types.
|
||||
- Added a workaround for player movement not working since 1.14.30.
|
||||
- Fixed lava and water buckets being edible since 1.13.
|
||||
- `AutoUpdater` is now created before any plugins are loaded.
|
||||
- Fixed trees not generating below y=2 in custom generators.
|
||||
- Fixed crash when opening a chest improperly unpaired from its pair (destroyed, setBlock(), unloaded, etc.).
|
||||
- `ThreadManager` is now lazily initialized.
|
||||
- Removed raw NBT storage from `Item` internals. The following methods are now deprecated:
|
||||
- `Item::setCompoundTag()`
|
||||
|
||||
# 3.11.7
|
||||
- Build system: Fixed crash reports of Jenkins builds being rejected by the crash archive as invalid.
|
||||
- Introduced a new dependency on `pocketmine/log-pthreads`, which contains classes separated from `pocketmine/log`.
|
||||
- Fixed minimum composer stability preventing any newer version of `pocketmine/pocketmine-mp` being installed than 3.3.4 by replacing `daverandom/callback-validator` with [`pocketmine/callback-validator`](https://github.com/pmmp/CallbackValidator).
|
||||
- Fixed every player seeing eating particles when any player eats.
|
||||
- Fixed setting held item not working during `BlockBreakEvent`, `PlayerInteractEvent` and `EntityDamageEvent`.
|
||||
- Fixed some incorrect documented types in `PlayerQuitEvent` reported by PHPStan.
|
||||
- Fixed documentation of `Item->pop()` return value.
|
||||
- Fixed server crash on encountering corrupted compressed data stored in region files.
|
||||
- Protocol: Split screen header is now properly accounted for during decoding. Note that split screen is still not supported natively, but their packets can be decoded properly now.
|
||||
- Protocol: Fixed wrong order of fields in `UpdateTradePacket`.
|
||||
- Protocol: Fixed loss of `fullSkinId` when decoding network skins.
|
||||
- Fixed RCON not being able to bind to port after a fast server restart.
|
||||
|
||||
|
53
changelogs/3.12.md
Normal file
53
changelogs/3.12.md
Normal file
@ -0,0 +1,53 @@
|
||||
**For Minecraft: Bedrock Edition 1.14.60**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 3.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 3.12.0
|
||||
- Added support for Minecraft: Bedrock Edition 1.14.60
|
||||
- Removed compatibility with 1.14.0-1.14.30
|
||||
|
||||
# 3.12.1
|
||||
- Fixed parsing of single-line doc comments for event handlers, e.g. `/** @ignoreCancelled */` should now work correctly.
|
||||
- The server will no longer crash on failure to load `level.dat` contents, but will gracefully shutdown instead without producing a crashdump.
|
||||
- Fixed some bugs in login verification that could cause undefined behaviour.
|
||||
- Fixed item-use behaviour when sneaking - sneaking and clicking a block with an empty hand, and sneaking and using an item, both now follow vanilla behaviour.
|
||||
- `start.sh` will now work on platforms where `/bin/bash` is not available, as long as `/usr/bin/env` knows where bash is.
|
||||
|
||||
# 3.12.2
|
||||
- Fixed permission default timings not being reported in timings reports (they were never stopped, only started).
|
||||
- Resource packs with a directory tree like `pack.zip/MyPack/manifest.json` are now supported. Note that the manifest closest to the root will be used.
|
||||
- Fixed `SkinImage` height and width being inverted at the protocol layer.
|
||||
- Fixed blocks being able to be placed inside the spawn protection radius by clicking the side of a block outside the radius.
|
||||
- Fixed server crash when `network.compression-level` is overridden by a CLI parameter.
|
||||
- Fixed moving entities spawning themselves to players registered on chunks when the players haven't received the chunk yet.
|
||||
- Cocoa pods now drop cocoa beans when broken instead of the block itself.
|
||||
|
||||
# 3.12.3
|
||||
- Core code is now analyzed using PHPStan level 8 (using baselines). While not all the code is level 8 compliant, this does mean that new code will be held to a higher standard, ensuring quality going forwards.
|
||||
- Players no longer burn when melee-attacked by other players. (vanilla parity)
|
||||
- Arrows shot by burning players are no longer on fire. (vanilla parity)
|
||||
- Fixed a crash that could occur with plugins on Unix filesystems that had backslashes in their names.
|
||||
- Cleaned up a whole bunch of unknowns in the protocol layer. Many new constants have been added.
|
||||
- Fixed player walking sounds.
|
||||
- Default generation queue size has been raised to 32 (previously 8). The previous default was selected in a time when PHP was much less performant than it is today, and in today's world it just needlessly slows things down.
|
||||
- Double plants are now burned away by fire.
|
||||
- Snow layers can now be stacked. (vanilla parity)
|
||||
- Resource pack sending chunk size has been reduced to 128 KB (previously 1 MB). This change was made after analyzing the effects that larger pack chunk sizes have on RakNet. Given the technical evidence, a smaller size, while slightly less bandwidth-efficient, should be more manageable for RakNet due to lower split reassembly overhead and reduced memory pressure.
|
||||
- Fixed "switching" (an exploit often complained about by PvP players). Now, the previous damage is subtracted from current damage when an entity is attacked while on cooldown. This means that attacking with a wooden sword and then diamond sword while attack cooldown is active will only deal as much damage as the diamond sword would have, instead of the combined total. This can be controlled using the `EntityDamageEvent::MODIFIER_PREVIOUS_DAMAGE_COOLDOWN` modifier. (vanilla parity)
|
||||
- Fixed projectiles knocking mobs back in unexpected directions on collision.
|
||||
- Fixed inventories not being synchronized on failed inventory transactions.
|
||||
- Vector3s decoded from packets are no longer rounded directly. Instead, the player movement handler takes responsibility for rounding the coordinates to prevent anti cheat doing something it's not supposed to.
|
||||
- `mobflame` particle can now be spawned using the `/particle` command.
|
||||
- Fixed several internal errors that could occur while modifying writable books.
|
||||
- Fixed swapping writable book pages not working in some cases.
|
||||
- `WritableBook->getPageText()` no longer throws an exception when the page doesn't exist, but returns null (as it was originally intended to).
|
||||
|
||||
# 3.12.4
|
||||
- Fixed absorption hearts not being consumed.
|
||||
|
||||
# 3.12.5
|
||||
- Fixed broken attack cooldowns.
|
@ -74,3 +74,56 @@ Plugin developers should **only** update their required API to this version if y
|
||||
- Fixed some issues with multiple consecutive commas inside quotes in form responses.
|
||||
- Fixed server crash when the manifest json does not contain a json object in a resource pack.
|
||||
- Ender pearls no longer collide with blocks that do not have any collision boxes.
|
||||
|
||||
# 3.9.6
|
||||
- Updated Composer dependencies to their latest versions.
|
||||
- Prevent clients repeating the resource pack sequence. This fixes error spam with bugged 1.12 clients.
|
||||
- `Internet::simpleCurl()` now includes the PocketMine-MP version in the user-agent string.
|
||||
- Spawn protection is now disabled by default in the setup wizard.
|
||||
- Default difficulty is now NORMAL(2) instead of EASY(1).
|
||||
- Fixed crashing on corrupted world manifest and unsupported world formats.
|
||||
- Fixed `/transferserver` being usable without appropriate permissions.
|
||||
- `RegionLoader->removeChunk()` now writes the region header as appropriate.
|
||||
- Fixed performance issue when loading large regions (bug in header validation).
|
||||
- Fixed skin geometry being removed when the JSON contained comments.
|
||||
- Added new constants to `EventPacket`.
|
||||
- Added encode/decode for `StructureTemplateDataExportRequestPacket` and `StructureTemplateDataExportResponsePacket`.
|
||||
- Fixed broken type asserts in `LevelChunkPacket::withCache()` and `ClientCacheMissResponsePacket::create()`.
|
||||
- `types\CommandParameter` field `byte1` has been renamed to `flags`.
|
||||
- Cleaned up public interface of `AvailableCommandsPacket`, removing fields which exposed details of the encoding scheme.
|
||||
- Improved documentation for the following API methods:
|
||||
- `pocketmine\item\Item`:
|
||||
- `addCreativeItem()`
|
||||
- `removeCreativeItem()`
|
||||
- `clearCreativeItems()`
|
||||
- `pocketmine\level\Explosion`:
|
||||
- `explodeA()`
|
||||
- `explodeB()`
|
||||
- Fixed various cosmetic documentation inconsistencies in the core and dependencies.
|
||||
|
||||
# 3.9.7
|
||||
- Fixed a crash that could occur during timezone detection.
|
||||
- Squid no longer spin around constantly in enclosed spaces. Their performance impact is reduced.
|
||||
- Cleaned up the bootstrap file.
|
||||
|
||||
# 3.9.8
|
||||
- Added [PHPStan](https://github.com/phpstan/phpstan) configuration. PHPStan is now used on CI for automated QA, which should improve stability and quality going forward.
|
||||
- The following constants are now autoloaded when loading the Composer autoloader:
|
||||
- `pocketmine\NAME`
|
||||
- `pocketmine\BASE_VERSION`
|
||||
- `pocketmine\IS_DEVELOPMENT_BUILD`
|
||||
- `pocketmine\BUILD_NUMBER`
|
||||
- `INT32_MIN`
|
||||
- `INT32_MAX`
|
||||
- `INT32_MASK`
|
||||
- Fixed memory leaks and crashes caused by plugin use of `Player->showPlayer()` and `Entity->spawnTo()`.
|
||||
- Fixed crashes that could occur when tile classes were overridden with classes incompatible with the originals.
|
||||
- Fixed improper handling of non-Compound root NBT tags on network itemstack decoding.
|
||||
- Fixed paintings dropping multiple items when destroyed by block updates.
|
||||
- Fixed `var_dump()` not showing private and protected properties of `DataPacket` subclasses.
|
||||
- Fixed overloads with zero arguments being missing when decoding `AvailableCommandsPacket`.
|
||||
- `CraftingDataPacket` now retains the `cleanRecipes` field when decoding.
|
||||
- Fixed `Block->getMetadata()` returning null (non-iterable).
|
||||
- `PlayerChatEvent` documentation has been updated to specify that `CommandSender` recipients are accepted. This behaviour was already present in previous versions, but incorrectly documented.
|
||||
- Fixed various issues with PHPDoc comments reported by PHPStan.
|
||||
- Fixed various minor code nits reported by PHPStan.
|
||||
|
@ -24,49 +24,37 @@
|
||||
"ext-yaml": ">=2.0.0",
|
||||
"ext-zip": "*",
|
||||
"ext-zlib": ">=1.2.11",
|
||||
"pocketmine/raklib": "^0.12.5",
|
||||
"pocketmine/spl": "^0.3.0",
|
||||
"pocketmine/raklib": "^0.12.7",
|
||||
"pocketmine/spl": "^0.4.0",
|
||||
"pocketmine/binaryutils": "^0.1.9",
|
||||
"pocketmine/nbt": "^0.2.10",
|
||||
"pocketmine/math": "^0.2.0",
|
||||
"pocketmine/snooze": "^0.1.0",
|
||||
"daverandom/callback-validator": "dev-master",
|
||||
"adhocore/json-comment": "^0.0.7"
|
||||
"pocketmine/classloader": "^0.1.0",
|
||||
"pocketmine/log": "^0.2.0",
|
||||
"pocketmine/log-pthreads": "^0.1.0",
|
||||
"pocketmine/callback-validator": "^1.0.1",
|
||||
"adhocore/json-comment": "^0.1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^0.12.25",
|
||||
"phpstan/phpstan-phpunit": "^0.12.6",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.2",
|
||||
"phpunit/phpunit": "^8.5"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"": ["src"]
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src/pocketmine/CoreConstants.php",
|
||||
"src/pocketmine/GlobalConstants.php",
|
||||
"src/pocketmine/VersionInfo.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"pocketmine\\": "tests/phpunit/"
|
||||
}
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/pmmp/RakLib"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/pmmp/SPL"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/pmmp/BinaryUtils"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/pmmp/NBT"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/pmmp/Math"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/pmmp/Snooze"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
1967
composer.lock
generated
1967
composer.lock
generated
File diff suppressed because it is too large
Load Diff
37
phpstan.neon.dist
Normal file
37
phpstan.neon.dist
Normal file
@ -0,0 +1,37 @@
|
||||
includes:
|
||||
- tests/phpstan/configs/actual-problems.neon
|
||||
- tests/phpstan/configs/com-dotnet-magic.neon
|
||||
- tests/phpstan/configs/custom-leveldb.neon
|
||||
- tests/phpstan/configs/gc-hacks.neon
|
||||
- tests/phpstan/configs/l7-baseline.neon
|
||||
- tests/phpstan/configs/l8-baseline.neon
|
||||
- tests/phpstan/configs/php-bugs.neon
|
||||
- tests/phpstan/configs/phpstan-bugs.neon
|
||||
- tests/phpstan/configs/phpunit-wiring-tests.neon
|
||||
- tests/phpstan/configs/pthreads-bugs.neon
|
||||
- tests/phpstan/configs/runtime-type-checks.neon
|
||||
- vendor/phpstan/phpstan-phpunit/extension.neon
|
||||
- vendor/phpstan/phpstan-phpunit/rules.neon
|
||||
- vendor/phpstan/phpstan-strict-rules/rules.neon
|
||||
|
||||
parameters:
|
||||
level: 8
|
||||
autoload_files:
|
||||
- tests/phpstan/bootstrap.php
|
||||
- src/pocketmine/PocketMine.php
|
||||
- build/make-release.php
|
||||
- build/server-phar.php
|
||||
paths:
|
||||
- src
|
||||
- build/make-release.php
|
||||
- build/server-phar.php
|
||||
- tests/phpunit
|
||||
dynamicConstantNames:
|
||||
- pocketmine\IS_DEVELOPMENT_BUILD
|
||||
- pocketmine\DEBUG
|
||||
stubFiles:
|
||||
- tests/phpstan/stubs/pthreads.stub
|
||||
- tests/phpstan/stubs/chunkutils.stub
|
||||
reportUnmatchedIgnoredErrors: false #no other way to silence platform-specific non-warnings
|
||||
staticReflectionClassNamePatterns:
|
||||
- "#^COM$#"
|
@ -30,9 +30,7 @@ use pocketmine\utils\TextFormat;
|
||||
* Handles the achievement list and a bit more
|
||||
*/
|
||||
abstract class Achievement{
|
||||
/**
|
||||
* @var array[]
|
||||
*/
|
||||
/** @var array[] */
|
||||
public static $list = [
|
||||
/*"openInventory" => array(
|
||||
"name" => "Taking Inventory",
|
||||
@ -106,13 +104,6 @@ abstract class Achievement{
|
||||
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @param Player $player
|
||||
* @param string $achievementId
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function broadcast(Player $player, string $achievementId) : bool{
|
||||
if(isset(Achievement::$list[$achievementId])){
|
||||
$translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"] . TextFormat::RESET]);
|
||||
@ -129,11 +120,7 @@ abstract class Achievement{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $achievementId
|
||||
* @param string $achievementName
|
||||
* @param array $requires
|
||||
*
|
||||
* @return bool
|
||||
* @param string[] $requires
|
||||
*/
|
||||
public static function add(string $achievementId, string $achievementName, array $requires = []) : bool{
|
||||
if(!isset(Achievement::$list[$achievementId])){
|
||||
|
@ -25,12 +25,16 @@ namespace pocketmine;
|
||||
|
||||
abstract class Collectable extends \Threaded{
|
||||
|
||||
/** @var bool */
|
||||
private $isGarbage = false;
|
||||
|
||||
public function isGarbage() : bool{
|
||||
return $this->isGarbage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setGarbage(){
|
||||
$this->isGarbage = true;
|
||||
}
|
||||
|
37
src/pocketmine/CoreConstants.php
Normal file
37
src/pocketmine/CoreConstants.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use function define;
|
||||
use function defined;
|
||||
use function dirname;
|
||||
|
||||
// composer autoload doesn't use require_once and also pthreads can inherit things
|
||||
if(defined('pocketmine\_CORE_CONSTANTS_INCLUDED')){
|
||||
return;
|
||||
}
|
||||
define('pocketmine\_CORE_CONSTANTS_INCLUDED', true);
|
||||
|
||||
define('pocketmine\PATH', dirname(__DIR__, 2) . '/');
|
||||
define('pocketmine\RESOURCE_PATH', __DIR__ . '/resources/');
|
@ -96,8 +96,14 @@ class CrashDump{
|
||||
|
||||
/** @var Server */
|
||||
private $server;
|
||||
/** @var resource */
|
||||
private $fp;
|
||||
/** @var int */
|
||||
private $time;
|
||||
/**
|
||||
* @var mixed[]
|
||||
* @phpstan-var array<string, mixed>
|
||||
*/
|
||||
private $data = [];
|
||||
/** @var string */
|
||||
private $encodedData = "";
|
||||
@ -134,15 +140,22 @@ class CrashDump{
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getEncodedData(){
|
||||
return $this->encodedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
* @phpstan-return array<string, mixed>
|
||||
*/
|
||||
public function getData() : array{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
private function encodeData(){
|
||||
private function encodeData() : void{
|
||||
$this->addLine();
|
||||
$this->addLine("----------------------REPORT THE DATA BELOW THIS LINE-----------------------");
|
||||
$this->addLine();
|
||||
@ -158,7 +171,7 @@ class CrashDump{
|
||||
$this->addLine("===END CRASH DUMP===");
|
||||
}
|
||||
|
||||
private function pluginsData(){
|
||||
private function pluginsData() : void{
|
||||
if($this->server->getPluginManager() instanceof PluginManager){
|
||||
$this->addLine();
|
||||
$this->addLine("Loaded plugins:");
|
||||
@ -182,7 +195,7 @@ class CrashDump{
|
||||
}
|
||||
}
|
||||
|
||||
private function extraData(){
|
||||
private function extraData() : void{
|
||||
global $argv;
|
||||
|
||||
if($this->server->getProperty("auto-report.send-settings", true) !== false){
|
||||
@ -209,7 +222,7 @@ class CrashDump{
|
||||
}
|
||||
}
|
||||
|
||||
private function baseCrash(){
|
||||
private function baseCrash() : void{
|
||||
global $lastExceptionError, $lastError;
|
||||
|
||||
if(isset($lastExceptionError)){
|
||||
@ -317,7 +330,7 @@ class CrashDump{
|
||||
return false;
|
||||
}
|
||||
|
||||
private function generalData(){
|
||||
private function generalData() : void{
|
||||
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
|
||||
$this->data["general"] = [];
|
||||
$this->data["general"]["name"] = $this->server->getName();
|
||||
@ -333,17 +346,27 @@ class CrashDump{
|
||||
$this->data["general"]["php_os"] = PHP_OS;
|
||||
$this->data["general"]["os"] = Utils::getOS();
|
||||
$this->addLine($this->server->getName() . " version: " . $version->getFullVersion(true) . " [Protocol " . ProtocolInfo::CURRENT_PROTOCOL . "]");
|
||||
$this->addLine("Git commit: " . GIT_COMMIT);
|
||||
$this->addLine("Git commit: " . \pocketmine\GIT_COMMIT);
|
||||
$this->addLine("uname -a: " . php_uname("a"));
|
||||
$this->addLine("PHP Version: " . phpversion());
|
||||
$this->addLine("Zend version: " . zend_version());
|
||||
$this->addLine("OS : " . PHP_OS . ", " . Utils::getOS());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $line
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addLine($line = ""){
|
||||
fwrite($this->fp, $line . PHP_EOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($str){
|
||||
fwrite($this->fp, $str);
|
||||
}
|
||||
|
32
src/pocketmine/GlobalConstants.php
Normal file
32
src/pocketmine/GlobalConstants.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?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);
|
||||
|
||||
// composer autoload doesn't use require_once and also pthreads can inherit things
|
||||
if(defined('pocketmine\_GLOBAL_CONSTANTS_INCLUDED')){
|
||||
return;
|
||||
}
|
||||
define('pocketmine\_GLOBAL_CONSTANTS_INCLUDED', true);
|
||||
|
||||
const INT32_MIN = -0x80000000;
|
||||
const INT32_MAX = 0x7fffffff;
|
||||
const INT32_MASK = 0xffffffff;
|
@ -27,33 +27,21 @@ use pocketmine\permission\ServerOperator;
|
||||
|
||||
interface IPlayer extends ServerOperator{
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isOnline() : bool;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() : string;
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isBanned() : bool;
|
||||
|
||||
/**
|
||||
* @param bool $banned
|
||||
* @return void
|
||||
*/
|
||||
public function setBanned(bool $banned);
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isWhitelisted() : bool;
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
* @return void
|
||||
*/
|
||||
public function setWhitelisted(bool $value);
|
||||
|
||||
@ -72,9 +60,6 @@ interface IPlayer extends ServerOperator{
|
||||
*/
|
||||
public function getLastPlayed();
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasPlayedBefore() : bool;
|
||||
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ class MemoryManager{
|
||||
$this->init();
|
||||
}
|
||||
|
||||
private function init(){
|
||||
private function init() : void{
|
||||
$this->memoryLimit = ((int) $this->server->getProperty("memory.main-limit", 0)) * 1024 * 1024;
|
||||
|
||||
$defaultMemory = 1024;
|
||||
@ -169,38 +169,25 @@ class MemoryManager{
|
||||
gc_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isLowMemory() : bool{
|
||||
return $this->lowMemory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function canUseChunkCache() : bool{
|
||||
return !$this->lowMemory or !$this->lowMemDisableChunkCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the allowed chunk radius based on the current memory usage.
|
||||
*
|
||||
* @param int $distance
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getViewDistance(int $distance) : int{
|
||||
return ($this->lowMemory and $this->lowMemChunkRadiusOverride > 0) ? (int) min($this->lowMemChunkRadiusOverride, $distance) : $distance;
|
||||
return ($this->lowMemory and $this->lowMemChunkRadiusOverride > 0) ? min($this->lowMemChunkRadiusOverride, $distance) : $distance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers garbage collection and cache cleanup to try and free memory.
|
||||
*
|
||||
* @param int $memory
|
||||
* @param int $limit
|
||||
* @param bool $global
|
||||
* @param int $triggerCount
|
||||
* @return void
|
||||
*/
|
||||
public function trigger(int $memory, int $limit, bool $global = false, int $triggerCount = 0){
|
||||
$this->server->getLogger()->debug(sprintf("[Memory Manager] %sLow memory triggered, limit %gMB, using %gMB",
|
||||
@ -230,6 +217,8 @@ class MemoryManager{
|
||||
|
||||
/**
|
||||
* Called every tick to update the memory manager state.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function check(){
|
||||
Timings::$memoryManagerTimer->startTiming();
|
||||
@ -268,9 +257,6 @@ class MemoryManager{
|
||||
Timings::$memoryManagerTimer->stopTiming();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function triggerGarbageCollector() : int{
|
||||
Timings::$garbageCollectorTimer->startTiming();
|
||||
|
||||
@ -294,9 +280,7 @@ class MemoryManager{
|
||||
/**
|
||||
* Dumps the server memory into the specified output folder.
|
||||
*
|
||||
* @param string $outputFolder
|
||||
* @param int $maxNesting
|
||||
* @param int $maxStringSize
|
||||
* @return void
|
||||
*/
|
||||
public function dumpServerMemory(string $outputFolder, int $maxNesting, int $maxStringSize){
|
||||
$this->server->getLogger()->notice("[Dump] After the memory dump is done, the server might crash");
|
||||
@ -314,11 +298,8 @@ class MemoryManager{
|
||||
* Static memory dumper accessible from any thread.
|
||||
*
|
||||
* @param mixed $startingObject
|
||||
* @param string $outputFolder
|
||||
* @param int $maxNesting
|
||||
* @param int $maxStringSize
|
||||
* @param \Logger $logger
|
||||
*
|
||||
* @return void
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger){
|
||||
@ -356,7 +337,7 @@ class MemoryManager{
|
||||
}
|
||||
|
||||
$staticCount++;
|
||||
self::continueDump($property->getValue(), $staticProperties[$className][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
$staticProperties[$className][$property->getName()] = self::continueDump($property->getValue(), $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
|
||||
if(count($staticProperties[$className]) === 0){
|
||||
@ -389,14 +370,14 @@ class MemoryManager{
|
||||
}
|
||||
|
||||
$globalCount++;
|
||||
self::continueDump($value, $globalVariables[$varName], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
$globalVariables[$varName] = self::continueDump($value, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
|
||||
file_put_contents($outputFolder . "/globalVariables.js", json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
$logger->info("[Dump] Wrote $globalCount global variables");
|
||||
}
|
||||
|
||||
self::continueDump($startingObject, $data, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
$data = self::continueDump($startingObject, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
|
||||
do{
|
||||
$continue = false;
|
||||
@ -444,14 +425,13 @@ class MemoryManager{
|
||||
$property->setAccessible(true);
|
||||
}
|
||||
|
||||
self::continueDump($property->getValue($object), $info["properties"][$name], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
$info["properties"][$name] = self::continueDump($property->getValue($object), $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
}
|
||||
|
||||
fwrite($obData, "$hash@$className: " . json_encode($info, JSON_UNESCAPED_SLASHES) . "\n");
|
||||
}
|
||||
|
||||
|
||||
}while($continue);
|
||||
|
||||
$logger->info("[Dump] Wrote " . count($objects) . " objects");
|
||||
@ -472,17 +452,14 @@ class MemoryManager{
|
||||
|
||||
/**
|
||||
* @param mixed $from
|
||||
* @param mixed &$data
|
||||
* @param object[] &$objects
|
||||
* @param int[] &$refCounts
|
||||
* @param int $recursion
|
||||
* @param int $maxNesting
|
||||
* @param int $maxStringSize
|
||||
* @param object[] $objects reference parameter
|
||||
* @param int[] $refCounts reference parameter
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private static function continueDump($from, &$data, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize){
|
||||
private static function continueDump($from, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize){
|
||||
if($maxNesting <= 0){
|
||||
$data = "(error) NESTING LIMIT REACHED";
|
||||
return;
|
||||
return "(error) NESTING LIMIT REACHED";
|
||||
}
|
||||
|
||||
--$maxNesting;
|
||||
@ -498,12 +475,11 @@ class MemoryManager{
|
||||
$data = "(object) $hash@" . get_class($from);
|
||||
}elseif(is_array($from)){
|
||||
if($recursion >= 5){
|
||||
$data = "(error) ARRAY RECURSION LIMIT REACHED";
|
||||
return;
|
||||
return "(error) ARRAY RECURSION LIMIT REACHED";
|
||||
}
|
||||
$data = [];
|
||||
foreach($from as $key => $value){
|
||||
self::continueDump($value, $data[$key], $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize);
|
||||
$data[$key] = self::continueDump($value, $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize);
|
||||
}
|
||||
}elseif(is_string($from)){
|
||||
$data = "(string) len(" . strlen($from) . ") " . substr(Utils::printable($from), 0, $maxStringSize);
|
||||
@ -512,5 +488,7 @@ class MemoryManager{
|
||||
}else{
|
||||
$data = $from;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
@ -37,10 +37,6 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
||||
/** @var CompoundTag|null */
|
||||
private $namedtag = null;
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct(Server $server, string $name){
|
||||
$this->server = $server;
|
||||
$this->name = $name;
|
||||
@ -57,6 +53,9 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Server
|
||||
*/
|
||||
public function getServer(){
|
||||
return $this->server;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,13 +21,9 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace {
|
||||
const INT32_MIN = -0x80000000;
|
||||
const INT32_MAX = 0x7fffffff;
|
||||
}
|
||||
|
||||
namespace pocketmine {
|
||||
|
||||
use pocketmine\utils\Git;
|
||||
use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\ServerKiller;
|
||||
use pocketmine\utils\Terminal;
|
||||
@ -40,6 +36,10 @@ namespace pocketmine {
|
||||
|
||||
const MIN_PHP_VERSION = "7.2.0";
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
function critical_error($message){
|
||||
echo "[ERROR] $message" . PHP_EOL;
|
||||
}
|
||||
@ -57,18 +57,18 @@ namespace pocketmine {
|
||||
if(version_compare(MIN_PHP_VERSION, PHP_VERSION) > 0){
|
||||
//If PHP version isn't high enough, anything below might break, so don't bother checking it.
|
||||
return [
|
||||
\pocketmine\NAME . " requires PHP >= " . MIN_PHP_VERSION . ", but you have PHP " . PHP_VERSION . "."
|
||||
"PHP >= " . MIN_PHP_VERSION . " is required, but you have PHP " . PHP_VERSION . "."
|
||||
];
|
||||
}
|
||||
|
||||
$messages = [];
|
||||
|
||||
if(PHP_INT_SIZE < 8){
|
||||
$messages[] = "Running " . \pocketmine\NAME . " with 32-bit systems/PHP is no longer supported. Please upgrade to a 64-bit system, or use a 64-bit PHP binary if this is a 64-bit system.";
|
||||
$messages[] = "32-bit systems/PHP are no longer supported. Please upgrade to a 64-bit system, or use a 64-bit PHP binary if this is a 64-bit system.";
|
||||
}
|
||||
|
||||
if(php_sapi_name() !== "cli"){
|
||||
$messages[] = "You must run " . \pocketmine\NAME . " using the CLI.";
|
||||
$messages[] = "Only PHP CLI is supported.";
|
||||
}
|
||||
|
||||
$extensions = [
|
||||
@ -121,8 +121,41 @@ namespace pocketmine {
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Logger $logger
|
||||
* @return void
|
||||
*/
|
||||
function emit_performance_warnings(\Logger $logger){
|
||||
if(extension_loaded("xdebug")){
|
||||
$logger->warning("Xdebug extension is enabled. This has a major impact on performance.");
|
||||
}
|
||||
if(!extension_loaded("pocketmine_chunkutils")){
|
||||
$logger->warning("ChunkUtils extension is missing. Anvil-format worlds will experience degraded performance.");
|
||||
}
|
||||
if(((int) ini_get('zend.assertions')) !== -1){
|
||||
$logger->warning("Debugging assertions are enabled. This may degrade performance. To disable them, set `zend.assertions = -1` in php.ini.");
|
||||
}
|
||||
if(\Phar::running(true) === ""){
|
||||
$logger->warning("Non-packaged installation detected. This will degrade autoloading speed and make startup times longer.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
function set_ini_entries(){
|
||||
ini_set("allow_url_fopen", '1');
|
||||
ini_set("display_errors", '1');
|
||||
ini_set("display_startup_errors", '1');
|
||||
ini_set("default_charset", "utf-8");
|
||||
ini_set('assert.exception', '1');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
function server(){
|
||||
if(!empty($messages = check_platform_dependencies())){
|
||||
if(count($messages = check_platform_dependencies()) > 0){
|
||||
echo PHP_EOL;
|
||||
$binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown";
|
||||
critical_error("Selected PHP binary ($binary) does not satisfy some requirements.");
|
||||
@ -136,47 +169,41 @@ namespace pocketmine {
|
||||
unset($messages);
|
||||
|
||||
error_reporting(-1);
|
||||
|
||||
if(\Phar::running(true) !== ""){
|
||||
define('pocketmine\PATH', \Phar::running(true) . "/");
|
||||
}else{
|
||||
define('pocketmine\PATH', dirname(__FILE__, 3) . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
set_ini_entries();
|
||||
|
||||
$opts = getopt("", ["bootstrap:"]);
|
||||
if(isset($opts["bootstrap"])){
|
||||
$bootstrap = realpath($opts["bootstrap"]) ?: $opts["bootstrap"];
|
||||
$bootstrap = ($real = realpath($opts["bootstrap"])) !== false ? $real : $opts["bootstrap"];
|
||||
}else{
|
||||
$bootstrap = \pocketmine\PATH . 'vendor/autoload.php';
|
||||
$bootstrap = dirname(__FILE__, 3) . '/vendor/autoload.php';
|
||||
}
|
||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
|
||||
|
||||
if(\pocketmine\COMPOSER_AUTOLOADER_PATH !== false and is_file(\pocketmine\COMPOSER_AUTOLOADER_PATH)){
|
||||
require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH);
|
||||
}else{
|
||||
if($bootstrap === false or !is_file($bootstrap)){
|
||||
critical_error("Composer autoloader not found at " . $bootstrap);
|
||||
critical_error("Please install/update Composer dependencies or use provided builds.");
|
||||
exit(1);
|
||||
}
|
||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
|
||||
require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH);
|
||||
|
||||
set_error_handler([Utils::class, 'errorExceptionHandler']);
|
||||
|
||||
/*
|
||||
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
|
||||
*/
|
||||
$autoloader = new \BaseClassLoader();
|
||||
$autoloader->register(false);
|
||||
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
|
||||
define('pocketmine\VERSION', $version->getFullVersion(true));
|
||||
|
||||
set_time_limit(0); //Who set it to 30 seconds?!?!
|
||||
$gitHash = str_repeat("00", 20);
|
||||
|
||||
ini_set("allow_url_fopen", '1');
|
||||
ini_set("display_errors", '1');
|
||||
ini_set("display_startup_errors", '1');
|
||||
ini_set("default_charset", "utf-8");
|
||||
if(\Phar::running(true) === ""){
|
||||
$gitHash = Git::getRepositoryStatePretty(\pocketmine\PATH);
|
||||
}else{
|
||||
$phar = new \Phar(\Phar::running(false));
|
||||
$meta = $phar->getMetadata();
|
||||
if(isset($meta["git"])){
|
||||
$gitHash = $meta["git"];
|
||||
}
|
||||
}
|
||||
|
||||
ini_set("memory_limit", '-1');
|
||||
|
||||
define('pocketmine\RESOURCE_PATH', \pocketmine\PATH . 'src' . DIRECTORY_SEPARATOR . 'pocketmine' . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR);
|
||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||
|
||||
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]);
|
||||
|
||||
@ -187,8 +214,7 @@ namespace pocketmine {
|
||||
mkdir(\pocketmine\DATA, 0777, true);
|
||||
}
|
||||
|
||||
define('pocketmine\LOCK_FILE_PATH', \pocketmine\DATA . 'server.lock');
|
||||
define('pocketmine\LOCK_FILE', fopen(\pocketmine\LOCK_FILE_PATH, "a+b"));
|
||||
define('pocketmine\LOCK_FILE', fopen(\pocketmine\DATA . 'server.lock', "a+b"));
|
||||
if(!flock(\pocketmine\LOCK_FILE, LOCK_EX | LOCK_NB)){
|
||||
//wait for a shared lock to avoid race conditions if two servers started at the same time - this makes sure the
|
||||
//other server wrote its PID and released exclusive lock before we get our lock
|
||||
@ -222,42 +248,7 @@ namespace pocketmine {
|
||||
}
|
||||
unset($tzError);
|
||||
|
||||
if(extension_loaded("xdebug")){
|
||||
$logger->warning(PHP_EOL . PHP_EOL . PHP_EOL . "\tYou are running " . \pocketmine\NAME . " with xdebug enabled. This has a major impact on performance." . PHP_EOL . PHP_EOL);
|
||||
}
|
||||
if(!extension_loaded("pocketmine_chunkutils")){
|
||||
$logger->warning("ChunkUtils extension is missing. Anvil-format worlds will experience degraded performance.");
|
||||
}
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
$logger->warning("Non-packaged " . \pocketmine\NAME . " installation detected. Consider using a phar in production for better performance.");
|
||||
}
|
||||
|
||||
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
|
||||
define('pocketmine\VERSION', $version->getFullVersion(true));
|
||||
|
||||
$gitHash = str_repeat("00", 20);
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
if(Utils::execute("git rev-parse HEAD", $out) === 0 and $out !== false and strlen($out = trim($out)) === 40){
|
||||
$gitHash = trim($out);
|
||||
if(Utils::execute("git diff --quiet") === 1 or Utils::execute("git diff --cached --quiet") === 1){ //Locally-modified
|
||||
$gitHash .= "-dirty";
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$phar = new \Phar(\Phar::running(false));
|
||||
$meta = $phar->getMetadata();
|
||||
if(isset($meta["git"])){
|
||||
$gitHash = $meta["git"];
|
||||
}
|
||||
}
|
||||
|
||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||
|
||||
|
||||
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
|
||||
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors
|
||||
emit_performance_warnings($logger);
|
||||
|
||||
$exitCode = 0;
|
||||
do{
|
||||
@ -271,7 +262,13 @@ namespace pocketmine {
|
||||
|
||||
//TODO: move this to a Server field
|
||||
define('pocketmine\START_TIME', microtime(true));
|
||||
ThreadManager::init();
|
||||
|
||||
/*
|
||||
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
|
||||
*/
|
||||
$autoloader = new \BaseClassLoader();
|
||||
$autoloader->register(false);
|
||||
|
||||
new Server($autoloader, $logger, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
|
||||
|
||||
$logger->info("Stopping other threads");
|
||||
@ -281,9 +278,7 @@ namespace pocketmine {
|
||||
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
|
||||
|
||||
if(ThreadManager::getInstance()->stopAll() > 0){
|
||||
if(\pocketmine\DEBUG > 1){
|
||||
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
|
||||
}
|
||||
$logger->debug("Some threads could not be stopped, performing a force-kill");
|
||||
Utils::kill(getmypid());
|
||||
}
|
||||
}while(false);
|
||||
@ -296,5 +291,7 @@ namespace pocketmine {
|
||||
exit($exitCode);
|
||||
}
|
||||
|
||||
\pocketmine\server();
|
||||
if(!defined('pocketmine\_PHPSTAN_ANALYSIS')){
|
||||
\pocketmine\server();
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,6 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use const PTHREADS_INHERIT_ALL;
|
||||
|
||||
/**
|
||||
* This class must be extended by all custom threading classes
|
||||
*/
|
||||
@ -33,12 +35,19 @@ abstract class Thread extends \Thread{
|
||||
/** @var string|null */
|
||||
protected $composerAutoloaderPath;
|
||||
|
||||
/** @var bool */
|
||||
protected $isKilled = false;
|
||||
|
||||
/**
|
||||
* @return \ClassLoader|null
|
||||
*/
|
||||
public function getClassLoader(){
|
||||
return $this->classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setClassLoader(\ClassLoader $loader = null){
|
||||
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
|
||||
|
||||
@ -54,6 +63,8 @@ abstract class Thread extends \Thread{
|
||||
* WARNING: This method MUST be called from any descendent threads' run() method to make autoloading usable.
|
||||
* If you do not do this, you will not be able to use new classes that were not loaded when the thread was started
|
||||
* (unless you are using a custom autoloader).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function registerClassLoader(){
|
||||
if($this->composerAutoloaderPath !== null){
|
||||
@ -64,7 +75,12 @@ abstract class Thread extends \Thread{
|
||||
}
|
||||
}
|
||||
|
||||
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
||||
/**
|
||||
* @param int|null $options TODO: pthreads bug
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function start(?int $options = PTHREADS_INHERIT_ALL){
|
||||
ThreadManager::getInstance()->add($this);
|
||||
|
||||
if($this->getClassLoader() === null){
|
||||
@ -75,6 +91,8 @@ abstract class Thread extends \Thread{
|
||||
|
||||
/**
|
||||
* Stops the thread using the best way possible. Try to stop it yourself before calling this.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function quit(){
|
||||
$this->isKilled = true;
|
||||
|
@ -28,9 +28,13 @@ use function spl_object_hash;
|
||||
|
||||
class ThreadManager extends \Volatile{
|
||||
|
||||
/** @var ThreadManager */
|
||||
/** @var ThreadManager|null */
|
||||
private static $instance = null;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @return void
|
||||
*/
|
||||
public static function init(){
|
||||
self::$instance = new ThreadManager();
|
||||
}
|
||||
@ -39,24 +43,31 @@ class ThreadManager extends \Volatile{
|
||||
* @return ThreadManager
|
||||
*/
|
||||
public static function getInstance(){
|
||||
if(self::$instance === null){
|
||||
self::$instance = new ThreadManager();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Worker|Thread $thread
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($thread){
|
||||
if($thread instanceof Thread or $thread instanceof Worker){
|
||||
$this->{spl_object_hash($thread)} = $thread;
|
||||
$this[spl_object_hash($thread)] = $thread;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Worker|Thread $thread
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function remove($thread){
|
||||
if($thread instanceof Thread or $thread instanceof Worker){
|
||||
unset($this->{spl_object_hash($thread)});
|
||||
unset($this[spl_object_hash($thread)]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,9 +19,20 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use function defined;
|
||||
|
||||
// composer autoload doesn't use require_once and also pthreads can inherit things
|
||||
// TODO: drop this file and use a final class with constants
|
||||
if(defined('pocketmine\_VERSION_INFO_INCLUDED')){
|
||||
return;
|
||||
}
|
||||
const _VERSION_INFO_INCLUDED = true;
|
||||
|
||||
const NAME = "PocketMine-MP";
|
||||
const BASE_VERSION = "3.9.5";
|
||||
const BASE_VERSION = "3.12.6";
|
||||
const IS_DEVELOPMENT_BUILD = false;
|
||||
const BUILD_NUMBER = 0;
|
||||
|
@ -23,6 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use const PTHREADS_INHERIT_ALL;
|
||||
|
||||
/**
|
||||
* This class must be extended by all custom threading classes
|
||||
*/
|
||||
@ -33,12 +35,19 @@ abstract class Worker extends \Worker{
|
||||
/** @var string|null */
|
||||
protected $composerAutoloaderPath;
|
||||
|
||||
/** @var bool */
|
||||
protected $isKilled = false;
|
||||
|
||||
/**
|
||||
* @return \ClassLoader|null
|
||||
*/
|
||||
public function getClassLoader(){
|
||||
return $this->classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setClassLoader(\ClassLoader $loader = null){
|
||||
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
|
||||
|
||||
@ -54,6 +63,8 @@ abstract class Worker extends \Worker{
|
||||
* WARNING: This method MUST be called from any descendent threads' run() method to make autoloading usable.
|
||||
* If you do not do this, you will not be able to use new classes that were not loaded when the thread was started
|
||||
* (unless you are using a custom autoloader).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function registerClassLoader(){
|
||||
if($this->composerAutoloaderPath !== null){
|
||||
@ -64,7 +75,12 @@ abstract class Worker extends \Worker{
|
||||
}
|
||||
}
|
||||
|
||||
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
||||
/**
|
||||
* @param int|null $options TODO: pthreads bug
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function start(?int $options = PTHREADS_INHERIT_ALL){
|
||||
ThreadManager::getInstance()->add($this);
|
||||
|
||||
if($this->getClassLoader() === null){
|
||||
@ -75,6 +91,8 @@ abstract class Worker extends \Worker{
|
||||
|
||||
/**
|
||||
* Stops the thread using the best way possible. Try to stop it yourself before calling this.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function quit(){
|
||||
$this->isKilled = true;
|
||||
|
@ -26,7 +26,6 @@ namespace pocketmine\block;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
|
||||
|
||||
/**
|
||||
* Air block
|
||||
*/
|
||||
|
@ -78,7 +78,7 @@ class Anvil extends Fallable{
|
||||
public function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
$inset = 0.125;
|
||||
|
||||
if($this->meta & 0x01){ //east/west
|
||||
if(($this->meta & 0x01) !== 0){ //east/west
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
|
@ -99,6 +99,11 @@ abstract class BaseRail extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $connections
|
||||
* @param int[][] $lookup
|
||||
* @phpstan-param array<int, list<int>> $lookup
|
||||
*/
|
||||
protected static function searchState(array $connections, array $lookup) : int{
|
||||
$meta = array_search($connections, $lookup, true);
|
||||
if($meta === false){
|
||||
@ -114,9 +119,7 @@ abstract class BaseRail extends Flowable{
|
||||
/**
|
||||
* Returns a meta value for the rail with the given connections.
|
||||
*
|
||||
* @param array $connections
|
||||
*
|
||||
* @return int
|
||||
* @param int[] $connections
|
||||
*
|
||||
* @throws \InvalidArgumentException if no state matches the given connections
|
||||
*/
|
||||
@ -164,6 +167,12 @@ abstract class BaseRail extends Flowable{
|
||||
return $connections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $constraints
|
||||
*
|
||||
* @return true[]
|
||||
* @phpstan-return array<int, true>
|
||||
*/
|
||||
private function getPossibleConnectionDirections(array $constraints) : array{
|
||||
switch(count($constraints)){
|
||||
case 0:
|
||||
@ -188,6 +197,10 @@ abstract class BaseRail extends Flowable{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true[]
|
||||
* @phpstan-return array<int, true>
|
||||
*/
|
||||
protected function getPossibleConnectionDirectionsOneConstraint(int $constraint) : array{
|
||||
$opposite = Vector3::getOppositeSide($constraint & ~self::FLAG_ASCEND);
|
||||
|
||||
@ -247,6 +260,9 @@ abstract class BaseRail extends Flowable{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $connections
|
||||
*/
|
||||
private function updateState(array $connections) : void{
|
||||
if(count($connections) === 1){
|
||||
$connections[] = Vector3::getOppositeSide($connections[0] & ~self::FLAG_ASCEND);
|
||||
|
@ -69,13 +69,13 @@ class Bed extends Transparent{
|
||||
return ($this->meta & self::BITFLAG_HEAD) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isOccupied() : bool{
|
||||
return ($this->meta & self::BITFLAG_OCCUPIED) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setOccupied(bool $occupied = true){
|
||||
if($occupied){
|
||||
$this->meta |= self::BITFLAG_OCCUPIED;
|
||||
@ -90,12 +90,6 @@ class Bed extends Transparent{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $meta
|
||||
* @param bool $isHead
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getOtherHalfSide(int $meta, bool $isHead = false) : int{
|
||||
$rotation = $meta & 0x03;
|
||||
$side = -1;
|
||||
@ -122,9 +116,6 @@ class Bed extends Transparent{
|
||||
return $side;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Bed|null
|
||||
*/
|
||||
public function getOtherHalf() : ?Bed{
|
||||
$other = $this->getSide(self::getOtherHalfSide($this->meta, $this->isHeadPart()));
|
||||
if($other instanceof Bed and $other->getId() === $this->getId() and $other->isHeadPart() !== $this->isHeadPart() and (($other->getDamage() & 0x03) === ($this->getDamage() & 0x03))){
|
||||
|
@ -40,6 +40,7 @@ use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\plugin\Plugin;
|
||||
use function array_merge;
|
||||
use function count;
|
||||
use function get_class;
|
||||
use const PHP_INT_MAX;
|
||||
|
||||
@ -49,12 +50,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* Returns a new Block instance with the specified ID, meta and position.
|
||||
*
|
||||
* This function redirects to {@link BlockFactory#get}.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $meta
|
||||
* @param Position|null $pos
|
||||
*
|
||||
* @return Block
|
||||
*/
|
||||
public static function get(int $id, int $meta = 0, Position $pos = null) : Block{
|
||||
return BlockFactory::get($id, $meta, $pos);
|
||||
@ -69,10 +64,9 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
/** @var int|null */
|
||||
protected $itemId;
|
||||
|
||||
/** @var AxisAlignedBB */
|
||||
/** @var AxisAlignedBB|null */
|
||||
protected $boundingBox = null;
|
||||
|
||||
|
||||
/** @var AxisAlignedBB[]|null */
|
||||
protected $collisionBoxes = null;
|
||||
|
||||
@ -89,16 +83,10 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
$this->itemId = $itemId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() : string{
|
||||
return $this->fallbackName ?? "Unknown";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
final public function getId() : int{
|
||||
return $this->id;
|
||||
}
|
||||
@ -106,8 +94,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
/**
|
||||
* Returns the ID of the item form of the block.
|
||||
* Used for drops for blocks (some blocks such as doors have a different item ID).
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getItemId() : int{
|
||||
return $this->itemId ?? $this->getId();
|
||||
@ -115,22 +101,15 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @return int
|
||||
*/
|
||||
public function getRuntimeId() : int{
|
||||
return RuntimeBlockMapping::toStaticRuntimeId($this->getId(), $this->getDamage());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
final public function getDamage() : int{
|
||||
return $this->meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $meta
|
||||
*/
|
||||
final public function setDamage(int $meta) : void{
|
||||
if($meta < 0 or $meta > 0xf){
|
||||
throw new \InvalidArgumentException("Block damage values must be 0-15, not $meta");
|
||||
@ -144,8 +123,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
*
|
||||
* If your block should not have any meta value when it's dropped as an item, override this to return 0 in
|
||||
* descendent classes.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getVariantBitmask() : int{
|
||||
return -1;
|
||||
@ -153,24 +130,18 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Returns the block meta, stripped of non-variant flags.
|
||||
* @return int
|
||||
*/
|
||||
public function getVariant() : int{
|
||||
return $this->meta & $this->getVariantBitmask();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* AKA: Block->isPlaceable
|
||||
* @return bool
|
||||
*/
|
||||
public function canBePlaced() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function canBeReplaced() : bool{
|
||||
return false;
|
||||
}
|
||||
@ -181,15 +152,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Places the Block, using block space and block target, and side. Returns if the block has been placed.
|
||||
*
|
||||
* @param Item $item
|
||||
* @param Block $blockReplace
|
||||
* @param Block $blockClicked
|
||||
* @param int $face
|
||||
* @param Vector3 $clickVector
|
||||
* @param Player|null $player
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
return $this->getLevel()->setBlock($this, $this, true, true);
|
||||
@ -197,18 +159,11 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Returns if the block can be broken with an specific Item
|
||||
*
|
||||
* @param Item $item
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isBreakable(Item $item) : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_NONE;
|
||||
}
|
||||
@ -222,8 +177,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* Otherwise, 1 should be returned if a tool is required, 0 if not.
|
||||
*
|
||||
* @see Item::getBlockToolHarvestLevel()
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getToolHarvestLevel() : int{
|
||||
return 0;
|
||||
@ -235,10 +188,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
*
|
||||
* In most cases this is also used to determine whether block drops should be created or not, except in some
|
||||
* special cases such as vines.
|
||||
*
|
||||
* @param Item $tool
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isCompatibleWithTool(Item $tool) : bool{
|
||||
if($this->getHardness() < 0){
|
||||
@ -253,23 +202,14 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Do the actions needed so the block is broken with the Item
|
||||
*
|
||||
* @param Item $item
|
||||
* @param Player|null $player
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function onBreak(Item $item, Player $player = null) : bool{
|
||||
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the seconds that this block takes to be broken using an specific Item
|
||||
*
|
||||
* @param Item $item
|
||||
*
|
||||
* @return float
|
||||
* @throws \InvalidArgumentException if the item efficiency is not a positive number
|
||||
*/
|
||||
public function getBreakTime(Item $item) : float{
|
||||
@ -299,8 +239,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Returns whether random block updates will be done on this block.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function ticksRandomly() : bool{
|
||||
return false;
|
||||
@ -323,11 +261,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Do actions when activated by Item. Returns if it has done anything
|
||||
*
|
||||
* @param Item $item
|
||||
* @param Player|null $player
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
return false;
|
||||
@ -335,7 +268,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Returns a base value used to compute block break times.
|
||||
* @return float
|
||||
*/
|
||||
public function getHardness() : float{
|
||||
return 10;
|
||||
@ -343,15 +275,11 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Returns the block's resistance to explosions. Usually 5x hardness.
|
||||
* @return float
|
||||
*/
|
||||
public function getBlastResistance() : float{
|
||||
return $this->getHardness() * 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getFrictionFactor() : float{
|
||||
return 0.6;
|
||||
}
|
||||
@ -379,16 +307,11 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* Examples of this behaviour include leaves and cobwebs.
|
||||
*
|
||||
* Light-diffusing blocks are included by the heightmap.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function diffusesSkyLight() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isTransparent() : bool{
|
||||
return false;
|
||||
}
|
||||
@ -399,7 +322,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* AKA: Block->isFlowable
|
||||
* @return bool
|
||||
*/
|
||||
public function canBeFlowedInto() : bool{
|
||||
return false;
|
||||
@ -415,21 +337,17 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Returns whether entities can climb up this block.
|
||||
* @return bool
|
||||
*/
|
||||
public function canClimb() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function addVelocityToEntity(Entity $entity, Vector3 $vector) : void{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the block position to a new Position object
|
||||
*
|
||||
* @param Position $v
|
||||
*/
|
||||
final public function position(Position $v) : void{
|
||||
$this->x = (int) $v->x;
|
||||
@ -442,8 +360,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
/**
|
||||
* Returns an array of Item objects to be dropped
|
||||
*
|
||||
* @param Item $item
|
||||
*
|
||||
* @return Item[]
|
||||
*/
|
||||
public function getDrops(Item $item) : array{
|
||||
@ -461,8 +377,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
/**
|
||||
* Returns an array of Items to be dropped when the block is broken using the correct tool type.
|
||||
*
|
||||
* @param Item $item
|
||||
*
|
||||
* @return Item[]
|
||||
*/
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
@ -474,8 +388,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
/**
|
||||
* Returns an array of Items to be dropped when the block is broken using a compatible Silk Touch-enchanted tool.
|
||||
*
|
||||
* @param Item $item
|
||||
*
|
||||
* @return Item[]
|
||||
*/
|
||||
public function getSilkTouchDrops(Item $item) : array{
|
||||
@ -486,10 +398,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Returns how much XP will be dropped by breaking this block with the given item.
|
||||
*
|
||||
* @param Item $item
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getXpDropForTool(Item $item) : int{
|
||||
if($item->hasEnchantment(Enchantment::SILK_TOUCH) or !$this->isCompatibleWithTool($item)){
|
||||
@ -501,8 +409,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Returns how much XP this block will drop when broken with an appropriate tool.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getXpDropAmount() : int{
|
||||
return 0;
|
||||
@ -511,8 +417,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
/**
|
||||
* Returns whether Silk Touch enchanted tools will cause this block to drop as itself. Since most blocks drop
|
||||
* themselves anyway, this is implicitly true.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return true;
|
||||
@ -520,7 +424,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Returns the item that players will equip when middle-clicking on this block.
|
||||
* @return Item
|
||||
*/
|
||||
public function getPickedItem() : Item{
|
||||
return ItemFactory::get($this->getItemId(), $this->getVariant());
|
||||
@ -528,7 +431,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Returns the time in ticks which the block will fuel a furnace for.
|
||||
* @return int
|
||||
*/
|
||||
public function getFuelTime() : int{
|
||||
return 0;
|
||||
@ -537,8 +439,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
/**
|
||||
* Returns the chance that the block will catch fire from nearby fire sources. Higher values lead to faster catching
|
||||
* fire.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getFlameEncouragement() : int{
|
||||
return 0;
|
||||
@ -546,8 +446,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Returns the base flammability of this block. Higher values lead to the block burning away more quickly.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getFlammability() : int{
|
||||
return 0;
|
||||
@ -555,8 +453,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Returns whether fire lit on this block will burn indefinitely.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function burnsForever() : bool{
|
||||
return false;
|
||||
@ -564,8 +460,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Returns whether this block can catch fire.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isFlammable() : bool{
|
||||
return $this->getFlammability() > 0;
|
||||
@ -581,9 +475,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
/**
|
||||
* Returns the Block on the side $side, works like Vector3::getSide()
|
||||
*
|
||||
* @param int $side
|
||||
* @param int $step
|
||||
*
|
||||
* @return Block
|
||||
*/
|
||||
public function getSide(int $side, int $step = 1){
|
||||
@ -642,10 +533,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
/**
|
||||
* Checks for collision against an AxisAlignedBB
|
||||
*
|
||||
* @param AxisAlignedBB $bb
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function collidesWithBB(AxisAlignedBB $bb) : bool{
|
||||
foreach($this->getCollisionBoxes() as $bb2){
|
||||
@ -657,9 +544,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entity $entity
|
||||
*/
|
||||
public function onEntityCollide(Entity $entity) : void{
|
||||
|
||||
}
|
||||
@ -679,16 +563,13 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @return AxisAlignedBB[]
|
||||
*/
|
||||
protected function recalculateCollisionBoxes() : array{
|
||||
if($bb = $this->recalculateBoundingBox()){
|
||||
if(($bb = $this->recalculateBoundingBox()) !== null){
|
||||
return [$bb];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AxisAlignedBB|null
|
||||
*/
|
||||
public function getBoundingBox() : ?AxisAlignedBB{
|
||||
if($this->boundingBox === null){
|
||||
$this->boundingBox = $this->recalculateBoundingBox();
|
||||
@ -696,9 +577,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
return $this->boundingBox;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AxisAlignedBB|null
|
||||
*/
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
@ -719,15 +597,9 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
$this->collisionBoxes = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Vector3 $pos1
|
||||
* @param Vector3 $pos2
|
||||
*
|
||||
* @return RayTraceResult|null
|
||||
*/
|
||||
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{
|
||||
$bbs = $this->getCollisionBoxes();
|
||||
if(empty($bbs)){
|
||||
if(count($bbs) === 0){
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -763,7 +635,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
return $this->level->getBlockMetadata()->getMetadata($this, $metadataKey);
|
||||
}
|
||||
|
||||
return null;
|
||||
return [];
|
||||
}
|
||||
|
||||
public function hasMetadata(string $metadataKey) : bool{
|
||||
|
@ -32,23 +32,47 @@ use function min;
|
||||
* Manages block registration and instance creation
|
||||
*/
|
||||
class BlockFactory{
|
||||
/** @var \SplFixedArray<Block> */
|
||||
private static $fullList = null;
|
||||
/**
|
||||
* @var \SplFixedArray|Block[]
|
||||
* @phpstan-var \SplFixedArray<Block>
|
||||
*/
|
||||
private static $fullList;
|
||||
|
||||
/** @var \SplFixedArray<bool> */
|
||||
public static $solid = null;
|
||||
/** @var \SplFixedArray<bool> */
|
||||
public static $transparent = null;
|
||||
/** @var \SplFixedArray<float> */
|
||||
public static $hardness = null;
|
||||
/** @var \SplFixedArray<int> */
|
||||
public static $light = null;
|
||||
/** @var \SplFixedArray<int> */
|
||||
public static $lightFilter = null;
|
||||
/** @var \SplFixedArray<bool> */
|
||||
public static $diffusesSkyLight = null;
|
||||
/** @var \SplFixedArray<float> */
|
||||
public static $blastResistance = null;
|
||||
/**
|
||||
* @var \SplFixedArray|bool[]
|
||||
* @phpstan-var \SplFixedArray<bool>
|
||||
*/
|
||||
public static $solid;
|
||||
/**
|
||||
* @var \SplFixedArray|bool[]
|
||||
* @phpstan-var \SplFixedArray<bool>
|
||||
*/
|
||||
public static $transparent;
|
||||
/**
|
||||
* @var \SplFixedArray|float[]
|
||||
* @phpstan-var \SplFixedArray<float>
|
||||
*/
|
||||
public static $hardness;
|
||||
/**
|
||||
* @var \SplFixedArray|int[]
|
||||
* @phpstan-var \SplFixedArray<int>
|
||||
*/
|
||||
public static $light;
|
||||
/**
|
||||
* @var \SplFixedArray|int[]
|
||||
* @phpstan-var \SplFixedArray<int>
|
||||
*/
|
||||
public static $lightFilter;
|
||||
/**
|
||||
* @var \SplFixedArray|bool[]
|
||||
* @phpstan-var \SplFixedArray<bool>
|
||||
*/
|
||||
public static $diffusesSkyLight;
|
||||
/**
|
||||
* @var \SplFixedArray|float[]
|
||||
* @phpstan-var \SplFixedArray<float>
|
||||
*/
|
||||
public static $blastResistance;
|
||||
|
||||
/**
|
||||
* Initializes the block factory. By default this is called only once on server start, however you may wish to use
|
||||
@ -334,7 +358,6 @@ class BlockFactory{
|
||||
* NOTE: If you are registering a new block type, you will need to add it to the creative inventory yourself - it
|
||||
* will not automatically appear there.
|
||||
*
|
||||
* @param Block $block
|
||||
* @param bool $override Whether to override existing registrations
|
||||
*
|
||||
* @throws \RuntimeException if something attempted to override an already-registered block without specifying the
|
||||
@ -364,12 +387,6 @@ class BlockFactory{
|
||||
|
||||
/**
|
||||
* Returns a new Block instance with the specified ID, meta and position.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $meta
|
||||
* @param Position $pos
|
||||
*
|
||||
* @return Block
|
||||
*/
|
||||
public static function get(int $id, int $meta = 0, Position $pos = null) : Block{
|
||||
if($meta < 0 or $meta > 0xf){
|
||||
@ -398,7 +415,7 @@ class BlockFactory{
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @return \SplFixedArray
|
||||
* @phpstan-return \SplFixedArray<Block>
|
||||
*/
|
||||
public static function getBlockStatesArray() : \SplFixedArray{
|
||||
return self::$fullList;
|
||||
@ -406,10 +423,6 @@ class BlockFactory{
|
||||
|
||||
/**
|
||||
* Returns whether a specified block ID is already registered in the block factory.
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isRegistered(int $id) : bool{
|
||||
$b = self::$fullList[$id << 4];
|
||||
@ -419,11 +432,6 @@ class BlockFactory{
|
||||
/**
|
||||
* @internal
|
||||
* @deprecated
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $meta
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function toStaticRuntimeId(int $id, int $meta = 0) : int{
|
||||
return RuntimeBlockMapping::toStaticRuntimeId($id, $meta);
|
||||
@ -433,8 +441,6 @@ class BlockFactory{
|
||||
* @deprecated
|
||||
* @internal
|
||||
*
|
||||
* @param int $runtimeId
|
||||
*
|
||||
* @return int[] [id, meta]
|
||||
*/
|
||||
public static function fromStaticRuntimeId(int $runtimeId) : array{
|
||||
|
@ -80,6 +80,9 @@ class BurningFurnace extends Solid{
|
||||
$furnace = $this->getLevel()->getTile($this);
|
||||
if(!($furnace instanceof TileFurnace)){
|
||||
$furnace = Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this));
|
||||
if(!($furnace instanceof TileFurnace)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$furnace->canOpenWith($item->getCustomName())){
|
||||
|
@ -109,11 +109,14 @@ class Chest extends Transparent{
|
||||
$chest = $t;
|
||||
}else{
|
||||
$chest = Tile::createTile(Tile::CHEST, $this->getLevel(), TileChest::createNBT($this));
|
||||
if(!($chest instanceof TileChest)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(
|
||||
!$this->getSide(Vector3::SIDE_UP)->isTransparent() or
|
||||
($chest->isPaired() and !$chest->getPair()->getBlock()->getSide(Vector3::SIDE_UP)->isTransparent()) or
|
||||
(($pair = $chest->getPair()) !== null and !$pair->getBlock()->getSide(Vector3::SIDE_UP)->isTransparent()) or
|
||||
!$chest->canOpenWith($item->getCustomName())
|
||||
){
|
||||
return true;
|
||||
|
@ -111,6 +111,9 @@ class CobblestoneWall extends Transparent{
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function canConnect(Block $block){
|
||||
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
|
||||
}
|
||||
|
@ -23,6 +23,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\ItemIds;
|
||||
use function mt_rand;
|
||||
|
||||
class CocoaBlock extends Transparent{
|
||||
|
||||
protected $id = self::COCOA_BLOCK;
|
||||
@ -48,4 +53,14 @@ class CocoaBlock extends Transparent{
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(ItemIds::DYE, 3, ($this->meta >> 2) === 2 ? mt_rand(2, 3) : 1)
|
||||
];
|
||||
}
|
||||
|
||||
public function getPickedItem() : Item{
|
||||
return ItemFactory::get(ItemIds::DYE, 3);
|
||||
}
|
||||
}
|
||||
|
@ -53,16 +53,10 @@ class ConcretePowder extends Fallable{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|Block
|
||||
*/
|
||||
public function tickFalling() : ?Block{
|
||||
return $this->checkAdjacentWater();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|Block
|
||||
*/
|
||||
private function checkAdjacentWater() : ?Block{
|
||||
for($i = 1; $i < 6; ++$i){ //Do not check underneath
|
||||
if($this->getSide($i) instanceof Water){
|
||||
|
@ -41,7 +41,6 @@ abstract class Crops extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($this->meta < 7 and $item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
||||
$block = clone $this;
|
||||
@ -56,7 +55,7 @@ abstract class Crops extends Flowable{
|
||||
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
|
||||
}
|
||||
|
||||
$item->count--;
|
||||
$item->pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -39,7 +39,6 @@ class Dandelion extends Flowable{
|
||||
return "Dandelion";
|
||||
}
|
||||
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() === Block::GRASS or $down->getId() === Block::DIRT or $down->getId() === Block::FARMLAND){
|
||||
|
@ -29,14 +29,13 @@ use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
|
||||
abstract class Door extends Transparent{
|
||||
|
||||
public function isSolid() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getFullDamage(){
|
||||
private function getFullDamage() : int{
|
||||
$damage = $this->getDamage();
|
||||
$isUp = ($damage & 0x08) > 0;
|
||||
|
||||
|
@ -68,10 +68,9 @@ class DoublePlant extends Flowable{
|
||||
|
||||
/**
|
||||
* Returns whether this double-plant has a corresponding other half.
|
||||
* @return bool
|
||||
*/
|
||||
public function isValidHalfPlant() : bool{
|
||||
if($this->meta & self::BITFLAG_TOP){
|
||||
if(($this->meta & self::BITFLAG_TOP) !== 0){
|
||||
$other = $this->getSide(Vector3::SIDE_DOWN);
|
||||
}else{
|
||||
$other = $this->getSide(Vector3::SIDE_UP);
|
||||
@ -103,7 +102,7 @@ class DoublePlant extends Flowable{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($this->meta & self::BITFLAG_TOP){
|
||||
if(($this->meta & self::BITFLAG_TOP) !== 0){
|
||||
if($this->isCompatibleWithTool($item)){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
@ -125,4 +124,12 @@ class DoublePlant extends Flowable{
|
||||
|
||||
return parent::getAffectedBlocks();
|
||||
}
|
||||
|
||||
public function getFlameEncouragement() : int{
|
||||
return 60;
|
||||
}
|
||||
|
||||
public function getFlammability() : int{
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +84,9 @@ class EnderChest extends Chest{
|
||||
$enderChest = $t;
|
||||
}else{
|
||||
$enderChest = Tile::createTile(Tile::ENDER_CHEST, $this->getLevel(), TileEnderChest::createNBT($this));
|
||||
if(!($enderChest instanceof TileEnderChest)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$this->getSide(Vector3::SIDE_UP)->isTransparent()){
|
||||
|
@ -45,9 +45,6 @@ abstract class Fallable extends Solid{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|Block
|
||||
*/
|
||||
public function tickFalling() : ?Block{
|
||||
return null;
|
||||
}
|
||||
|
@ -48,7 +48,6 @@ class Farmland extends Transparent{
|
||||
return BlockToolType::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use function count;
|
||||
|
||||
abstract class Fence extends Transparent{
|
||||
|
||||
@ -85,7 +86,7 @@ abstract class Fence extends Transparent{
|
||||
);
|
||||
}
|
||||
|
||||
if(empty($bbs)){
|
||||
if(count($bbs) === 0){
|
||||
//centre post AABB (only needed if not connected on any axis - other BBs overlapping will do this if any connections are made)
|
||||
return [
|
||||
new AxisAlignedBB(
|
||||
@ -102,6 +103,9 @@ abstract class Fence extends Transparent{
|
||||
return $bbs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function canConnect(Block $block){
|
||||
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
|
||||
}
|
||||
|
@ -39,7 +39,6 @@ class FenceGate extends Transparent{
|
||||
return BlockToolType::TYPE_AXE;
|
||||
}
|
||||
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
|
||||
if(($this->getDamage() & 0x04) > 0){
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class Furnace extends BurningFurnace{
|
||||
|
||||
protected $id = self::FURNACE;
|
||||
|
@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class GlowingObsidian extends Solid{
|
||||
|
@ -99,7 +99,7 @@ class Grass extends Solid{
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){
|
||||
$item->count--;
|
||||
$item->pop();
|
||||
TallGrassObject::growGrass($this->getLevel(), $this, new Random(mt_rand()), 8, 2);
|
||||
|
||||
return true;
|
||||
|
@ -47,6 +47,9 @@ class ItemFrame extends Flowable{
|
||||
$tile = $this->level->getTile($this);
|
||||
if(!($tile instanceof TileItemFrame)){
|
||||
$tile = Tile::createTile(Tile::ITEM_FRAME, $this->getLevel(), TileItemFrame::createNBT($this));
|
||||
if(!($tile instanceof TileItemFrame)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if($tile->hasItem()){
|
||||
|
@ -90,7 +90,6 @@ class Ladder extends Transparent{
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
if(!$blockClicked->isTransparent()){
|
||||
$faces = [
|
||||
|
@ -39,6 +39,7 @@ class Leaves extends Transparent{
|
||||
public const DARK_OAK = 1;
|
||||
|
||||
protected $id = self::LEAVES;
|
||||
/** @var int */
|
||||
protected $woodType = self::WOOD;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
@ -67,8 +68,11 @@ class Leaves extends Transparent{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
protected function findLog(Block $pos, array $visited, int $distance, ?int $fromSide = null) : bool{
|
||||
/**
|
||||
* @param true[] $visited reference parameter
|
||||
* @phpstan-param array<string, true> $visited
|
||||
*/
|
||||
protected function findLog(Block $pos, array &$visited, int $distance, ?int $fromSide = null) : bool{
|
||||
$index = $pos->x . "." . $pos->y . "." . $pos->z;
|
||||
if(isset($visited[$index])){
|
||||
return false;
|
||||
@ -168,7 +172,7 @@ class Leaves extends Transparent{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->getBlockToolType() & BlockToolType::TYPE_SHEARS){
|
||||
if(($item->getBlockToolType() & BlockToolType::TYPE_SHEARS) !== 0){
|
||||
return $this->getDropsForCompatibleTool($item);
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ use pocketmine\item\ItemFactory;
|
||||
class Leaves2 extends Leaves{
|
||||
|
||||
protected $id = self::LEAVES2;
|
||||
/** @var int */
|
||||
protected $woodType = self::WOOD2;
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -38,6 +38,7 @@ use function min;
|
||||
|
||||
abstract class Liquid extends Transparent{
|
||||
|
||||
/** @var int */
|
||||
public $adjacentSources = 0;
|
||||
|
||||
/** @var Vector3|null */
|
||||
@ -90,6 +91,9 @@ abstract class Liquid extends Transparent{
|
||||
|
||||
abstract public function getBucketEmptySound() : int;
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getFluidHeightPercent(){
|
||||
$d = $this->meta;
|
||||
if($d >= 8){
|
||||
@ -207,8 +211,6 @@ abstract class Liquid extends Transparent{
|
||||
|
||||
/**
|
||||
* Returns how many liquid levels are lost per block flowed horizontally. Affects how far the liquid can flow.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getFlowDecayPerBlock() : int{
|
||||
return 1;
|
||||
@ -430,6 +432,9 @@ abstract class Liquid extends Transparent{
|
||||
return ($decay >= 0 && $blockDecay >= $decay) ? $decay : $blockDecay;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function checkForHarden(){
|
||||
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class MossyCobblestone extends Cobblestone{
|
||||
|
||||
protected $id = self::MOSSY_COBBLESTONE;
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
use pocketmine\event\block\BlockGrowEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
|
@ -72,7 +72,7 @@ class Sapling extends Flowable{
|
||||
//TODO: change log type
|
||||
Tree::growTree($this->getLevel(), $this->x, $this->y, $this->z, new Random(mt_rand()), $this->getVariant());
|
||||
|
||||
$item->count--;
|
||||
$item->pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -57,7 +57,6 @@ class SignPost extends Transparent{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
if($face !== Vector3::SIDE_DOWN){
|
||||
|
||||
|
@ -42,7 +42,7 @@ class SnowLayer extends Flowable{
|
||||
}
|
||||
|
||||
public function canBeReplaced() : bool{
|
||||
return true;
|
||||
return $this->meta < 7; //8 snow layers
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
@ -57,9 +57,15 @@ class SnowLayer extends Flowable{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
private function canBeSupportedBy(Block $b) : bool{
|
||||
return $b->isSolid() or ($b->getId() === $this->getId() and $b->getDamage() === 7);
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
if($blockReplace->getSide(Vector3::SIDE_DOWN)->isSolid()){
|
||||
//TODO: fix placement
|
||||
if($blockReplace->getId() === $this->getId() and $blockReplace->getDamage() < 7){
|
||||
$this->setDamage($blockReplace->getDamage() + 1);
|
||||
}
|
||||
if($this->canBeSupportedBy($blockReplace->getSide(Vector3::SIDE_DOWN))){
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true);
|
||||
|
||||
return true;
|
||||
@ -69,7 +75,7 @@ class SnowLayer extends Flowable{
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if(!$this->getSide(Vector3::SIDE_DOWN)->isSolid()){
|
||||
if(!$this->canBeSupportedBy($this->getSide(Vector3::SIDE_DOWN))){
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false, false);
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class Sponge extends Solid{
|
||||
|
||||
protected $id = self::SPONGE;
|
||||
|
@ -62,7 +62,7 @@ class Sugarcane extends Flowable{
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
}
|
||||
|
||||
$item->count--;
|
||||
$item->pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -74,6 +74,9 @@ class TNT extends Solid{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function ignite(int $fuse = 80){
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use function count;
|
||||
|
||||
abstract class Thin extends Transparent{
|
||||
|
||||
@ -77,7 +78,7 @@ abstract class Thin extends Transparent{
|
||||
);
|
||||
}
|
||||
|
||||
if(empty($bbs)){
|
||||
if(count($bbs) === 0){
|
||||
//centre post AABB (only needed if not connected on any axis - other BBs overlapping will do this if any connections are made)
|
||||
return [
|
||||
new AxisAlignedBB(
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
abstract class Transparent extends Block{
|
||||
|
||||
public function isTransparent() : bool{
|
||||
|
@ -197,7 +197,7 @@ class Vine extends Flowable{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->getBlockToolType() & BlockToolType::TYPE_SHEARS){
|
||||
if(($item->getBlockToolType() & BlockToolType::TYPE_SHEARS) !== 0){
|
||||
return $this->getDropsForCompatibleTool($item);
|
||||
}
|
||||
|
||||
|
@ -70,8 +70,6 @@ class Water extends Liquid{
|
||||
if($entity->isOnFire()){
|
||||
$entity->extinguish();
|
||||
}
|
||||
|
||||
$entity->resetFallDistance();
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
|
@ -55,7 +55,6 @@ class WaterLily extends Flowable{
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
if($blockClicked instanceof Water){
|
||||
$up = $blockClicked->getSide(Vector3::SIDE_UP);
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class Wood2 extends Wood{
|
||||
|
||||
public const ACACIA = 0;
|
||||
|
@ -50,12 +50,10 @@ abstract class Command{
|
||||
/** @var string[] */
|
||||
private $aliases = [];
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
/** @var string[] */
|
||||
private $activeAliases = [];
|
||||
|
||||
/** @var CommandMap */
|
||||
/** @var CommandMap|null */
|
||||
private $commandMap = null;
|
||||
|
||||
/** @var string */
|
||||
@ -67,16 +65,13 @@ abstract class Command{
|
||||
/** @var string|null */
|
||||
private $permission = null;
|
||||
|
||||
/** @var string */
|
||||
/** @var string|null */
|
||||
private $permissionMessage = null;
|
||||
|
||||
/** @var TimingsHandler */
|
||||
public $timings;
|
||||
/** @var TimingsHandler|null */
|
||||
public $timings = null;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string $description
|
||||
* @param string $usageMessage
|
||||
* @param string[] $aliases
|
||||
*/
|
||||
public function __construct(string $name, string $description = "", string $usageMessage = null, array $aliases = []){
|
||||
@ -88,18 +83,13 @@ abstract class Command{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CommandSender $sender
|
||||
* @param string $commandLabel
|
||||
* @param string[] $args
|
||||
* @param string[] $args
|
||||
*
|
||||
* @return mixed
|
||||
* @throws CommandException
|
||||
*/
|
||||
abstract public function execute(CommandSender $sender, string $commandLabel, array $args);
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() : string{
|
||||
return $this->name;
|
||||
}
|
||||
@ -111,19 +101,13 @@ abstract class Command{
|
||||
return $this->permission;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string|null $permission
|
||||
* @return void
|
||||
*/
|
||||
public function setPermission(string $permission = null){
|
||||
$this->permission = $permission;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CommandSender $target
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function testPermission(CommandSender $target) : bool{
|
||||
if($this->testPermissionSilent($target)){
|
||||
return true;
|
||||
@ -138,11 +122,6 @@ abstract class Command{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CommandSender $target
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function testPermissionSilent(CommandSender $target) : bool{
|
||||
if($this->permission === null or $this->permission === ""){
|
||||
return true;
|
||||
@ -157,9 +136,6 @@ abstract class Command{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLabel() : string{
|
||||
return $this->label;
|
||||
}
|
||||
@ -181,10 +157,6 @@ abstract class Command{
|
||||
|
||||
/**
|
||||
* Registers the command into a Command map
|
||||
*
|
||||
* @param CommandMap $commandMap
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function register(CommandMap $commandMap) : bool{
|
||||
if($this->allowChangesFrom($commandMap)){
|
||||
@ -196,11 +168,6 @@ abstract class Command{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CommandMap $commandMap
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function unregister(CommandMap $commandMap) : bool{
|
||||
if($this->allowChangesFrom($commandMap)){
|
||||
$this->commandMap = null;
|
||||
@ -213,18 +180,10 @@ abstract class Command{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CommandMap $commandMap
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function allowChangesFrom(CommandMap $commandMap) : bool{
|
||||
return $this->commandMap === null or $this->commandMap === $commandMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isRegistered() : bool{
|
||||
return $this->commandMap !== null;
|
||||
}
|
||||
@ -236,29 +195,22 @@ abstract class Command{
|
||||
return $this->activeAliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPermissionMessage() : ?string{
|
||||
return $this->permissionMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription() : string{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getUsage() : string{
|
||||
return $this->usageMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $aliases
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setAliases(array $aliases){
|
||||
$this->aliases = $aliases;
|
||||
@ -268,30 +220,30 @@ abstract class Command{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $description
|
||||
* @return void
|
||||
*/
|
||||
public function setDescription(string $description){
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $permissionMessage
|
||||
* @return void
|
||||
*/
|
||||
public function setPermissionMessage(string $permissionMessage){
|
||||
$this->permissionMessage = $permissionMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $usage
|
||||
* @return void
|
||||
*/
|
||||
public function setUsage(string $usage){
|
||||
$this->usageMessage = $usage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CommandSender $source
|
||||
* @param TextContainer|string $message
|
||||
* @param bool $sendToSource
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function broadcastCommandMessage(CommandSender $source, $message, bool $sendToSource = true){
|
||||
if($message instanceof TextContainer){
|
||||
@ -326,9 +278,6 @@ abstract class Command{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString() : string{
|
||||
return $this->name;
|
||||
}
|
||||
|
@ -23,16 +23,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command;
|
||||
|
||||
|
||||
interface CommandExecutor{
|
||||
|
||||
/**
|
||||
* @param CommandSender $sender
|
||||
* @param Command $command
|
||||
* @param string $label
|
||||
* @param string[] $args
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function onCommand(CommandSender $sender, Command $command, string $label, array $args) : bool;
|
||||
|
||||
|
@ -23,30 +23,17 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\command;
|
||||
|
||||
|
||||
interface CommandMap{
|
||||
|
||||
/**
|
||||
* @param string $fallbackPrefix
|
||||
* @param Command[] $commands
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function registerAll(string $fallbackPrefix, array $commands);
|
||||
|
||||
/**
|
||||
* @param string $fallbackPrefix
|
||||
* @param Command $command
|
||||
* @param string|null $label
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function register(string $fallbackPrefix, Command $command, string $label = null) : bool;
|
||||
|
||||
/**
|
||||
* @param CommandSender $sender
|
||||
* @param string $cmdLine
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function dispatch(CommandSender $sender, string $cmdLine) : bool;
|
||||
|
||||
/**
|
||||
@ -55,11 +42,8 @@ interface CommandMap{
|
||||
public function clearCommands();
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return Command|null
|
||||
*/
|
||||
public function getCommand(string $name);
|
||||
|
||||
|
||||
}
|
||||
|
@ -54,7 +54,9 @@ class CommandReader extends Thread{
|
||||
|
||||
/** @var \Threaded */
|
||||
protected $buffer;
|
||||
/** @var bool */
|
||||
private $shutdown = false;
|
||||
/** @var int */
|
||||
private $type = self::TYPE_STREAM;
|
||||
|
||||
/** @var SleeperNotifier|null */
|
||||
@ -71,6 +73,9 @@ class CommandReader extends Thread{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function shutdown(){
|
||||
$this->shutdown = true;
|
||||
}
|
||||
@ -94,7 +99,7 @@ class CommandReader extends Thread{
|
||||
throw new \ThreadException($message);
|
||||
}
|
||||
|
||||
private function initStdin(){
|
||||
private function initStdin() : void{
|
||||
if(is_resource(self::$stdin)){
|
||||
fclose(self::$stdin);
|
||||
}
|
||||
@ -111,8 +116,6 @@ class CommandReader extends Thread{
|
||||
* Checks if the specified stream is a FIFO pipe.
|
||||
*
|
||||
* @param resource $stream
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isPipe($stream) : bool{
|
||||
return is_resource($stream) and (!stream_isatty($stream) or ((fstat($stream)["mode"] & 0170000) === 0010000));
|
||||
@ -141,6 +144,7 @@ class CommandReader extends Thread{
|
||||
case self::TYPE_STREAM:
|
||||
//stream_select doesn't work on piped streams for some reason
|
||||
$r = [self::$stdin];
|
||||
$w = $e = null;
|
||||
if(($count = stream_select($r, $w, $e, 0, 200000)) === 0){ //nothing changed in 200000 microseconds
|
||||
return true;
|
||||
}elseif($count === false){ //stream error
|
||||
@ -150,7 +154,7 @@ class CommandReader extends Thread{
|
||||
case self::TYPE_PIPED:
|
||||
if(($raw = fgets(self::$stdin)) === false){ //broken pipe or EOF
|
||||
$this->initStdin();
|
||||
$this->synchronized(function(){
|
||||
$this->synchronized(function() : void{
|
||||
$this->wait(200000);
|
||||
}); //prevent CPU waste if it's end of pipe
|
||||
return true; //loop back round
|
||||
@ -184,6 +188,9 @@ class CommandReader extends Thread{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function run(){
|
||||
$this->registerClassLoader();
|
||||
|
||||
|
@ -31,6 +31,8 @@ interface CommandSender extends Permissible{
|
||||
|
||||
/**
|
||||
* @param TextContainer|string $message
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendMessage($message);
|
||||
|
||||
@ -39,23 +41,18 @@ interface CommandSender extends Permissible{
|
||||
*/
|
||||
public function getServer();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() : string;
|
||||
|
||||
/**
|
||||
* Returns the line height of the command-sender's screen. Used for determining sizes for command output pagination
|
||||
* such as in the /help command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getScreenLineHeight() : int;
|
||||
|
||||
/**
|
||||
* Sets the line height used for command output pagination for this command sender. `null` will reset it to default.
|
||||
*
|
||||
* @param int|null $height
|
||||
* @return void
|
||||
*/
|
||||
public function setScreenLineHeight(int $height = null);
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ use const PHP_INT_MAX;
|
||||
|
||||
class ConsoleCommandSender implements CommandSender{
|
||||
|
||||
/** @var PermissibleBase */
|
||||
private $perm;
|
||||
|
||||
/** @var int|null */
|
||||
@ -48,8 +49,6 @@ class ConsoleCommandSender implements CommandSender{
|
||||
|
||||
/**
|
||||
* @param Permission|string $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isPermissionSet($name) : bool{
|
||||
return $this->perm->isPermissionSet($name);
|
||||
@ -57,27 +56,16 @@ class ConsoleCommandSender implements CommandSender{
|
||||
|
||||
/**
|
||||
* @param Permission|string $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasPermission($name) : bool{
|
||||
return $this->perm->hasPermission($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Plugin $plugin
|
||||
* @param string $name
|
||||
* @param bool $value
|
||||
*
|
||||
* @return PermissionAttachment
|
||||
*/
|
||||
public function addAttachment(Plugin $plugin, string $name = null, bool $value = null) : PermissionAttachment{
|
||||
return $this->perm->addAttachment($plugin, $name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PermissionAttachment $attachment
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeAttachment(PermissionAttachment $attachment){
|
||||
@ -104,6 +92,8 @@ class ConsoleCommandSender implements CommandSender{
|
||||
|
||||
/**
|
||||
* @param TextContainer|string $message
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendMessage($message){
|
||||
if($message instanceof TextContainer){
|
||||
@ -117,22 +107,16 @@ class ConsoleCommandSender implements CommandSender{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() : string{
|
||||
return "CONSOLE";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isOp() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
* @return void
|
||||
*/
|
||||
public function setOp(bool $value){
|
||||
|
||||
|
@ -32,10 +32,10 @@ use function strpos;
|
||||
use function substr;
|
||||
|
||||
class FormattedCommandAlias extends Command{
|
||||
/** @var string[] */
|
||||
private $formatStrings = [];
|
||||
|
||||
/**
|
||||
* @param string $alias
|
||||
* @param string[] $formatStrings
|
||||
*/
|
||||
public function __construct(string $alias, array $formatStrings){
|
||||
@ -65,10 +65,7 @@ class FormattedCommandAlias extends Command{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $formatString
|
||||
* @param array $args
|
||||
*
|
||||
* @return string
|
||||
* @param string[] $args
|
||||
*/
|
||||
private function buildCommand(string $formatString, array $args) : string{
|
||||
$index = strpos($formatString, '$');
|
||||
@ -143,13 +140,6 @@ class FormattedCommandAlias extends Command{
|
||||
return $formatString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $i
|
||||
* @param int $j
|
||||
* @param int $k
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function inRange(int $i, int $j, int $k) : bool{
|
||||
return $i >= $j and $i <= $k;
|
||||
}
|
||||
|
@ -34,10 +34,6 @@ class PluginCommand extends Command implements PluginIdentifiableCommand{
|
||||
/** @var CommandExecutor */
|
||||
private $executor;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param Plugin $owner
|
||||
*/
|
||||
public function __construct(string $name, Plugin $owner){
|
||||
parent::__construct($name);
|
||||
$this->owningPlugin = $owner;
|
||||
@ -69,15 +65,12 @@ class PluginCommand extends Command implements PluginIdentifiableCommand{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CommandExecutor $executor
|
||||
* @return void
|
||||
*/
|
||||
public function setExecutor(CommandExecutor $executor){
|
||||
$this->executor = $executor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Plugin
|
||||
*/
|
||||
public function getPlugin() : Plugin{
|
||||
return $this->owningPlugin;
|
||||
}
|
||||
|
@ -27,8 +27,5 @@ use pocketmine\plugin\Plugin;
|
||||
|
||||
interface PluginIdentifiableCommand{
|
||||
|
||||
/**
|
||||
* @return Plugin
|
||||
*/
|
||||
public function getPlugin() : Plugin;
|
||||
}
|
||||
|
@ -41,6 +41,9 @@ class RemoteConsoleCommandSender extends ConsoleCommandSender{
|
||||
$this->messages .= trim($message, "\r\n") . "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMessage(){
|
||||
return $this->messages;
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ use function explode;
|
||||
use function implode;
|
||||
use function min;
|
||||
use function preg_match_all;
|
||||
use function strcasecmp;
|
||||
use function stripslashes;
|
||||
use function strpos;
|
||||
use function strtolower;
|
||||
@ -79,9 +80,7 @@ use function trim;
|
||||
|
||||
class SimpleCommandMap implements CommandMap{
|
||||
|
||||
/**
|
||||
* @var Command[]
|
||||
*/
|
||||
/** @var Command[] */
|
||||
protected $knownCommands = [];
|
||||
|
||||
/** @var Server */
|
||||
@ -92,7 +91,7 @@ class SimpleCommandMap implements CommandMap{
|
||||
$this->setDefaultCommands();
|
||||
}
|
||||
|
||||
private function setDefaultCommands(){
|
||||
private function setDefaultCommands() : void{
|
||||
$this->registerAll("pocketmine", [
|
||||
new BanCommand("ban"),
|
||||
new BanIpCommand("ban-ip"),
|
||||
@ -137,20 +136,12 @@ class SimpleCommandMap implements CommandMap{
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function registerAll(string $fallbackPrefix, array $commands){
|
||||
foreach($commands as $command){
|
||||
$this->register($fallbackPrefix, $command);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fallbackPrefix
|
||||
* @param Command $command
|
||||
* @param string|null $label
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function register(string $fallbackPrefix, Command $command, string $label = null) : bool{
|
||||
if($label === null){
|
||||
$label = $command->getName();
|
||||
@ -177,11 +168,6 @@ class SimpleCommandMap implements CommandMap{
|
||||
return $registered;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Command $command
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function unregister(Command $command) : bool{
|
||||
foreach($this->knownCommands as $lbl => $cmd){
|
||||
if($cmd === $command){
|
||||
@ -194,21 +180,13 @@ class SimpleCommandMap implements CommandMap{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Command $command
|
||||
* @param bool $isAlias
|
||||
* @param string $fallbackPrefix
|
||||
* @param string $label
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function registerAlias(Command $command, bool $isAlias, string $fallbackPrefix, string $label) : bool{
|
||||
$this->knownCommands[$fallbackPrefix . ":" . $label] = $command;
|
||||
if(($command instanceof VanillaCommand or $isAlias) and isset($this->knownCommands[$label])){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(isset($this->knownCommands[$label]) and $this->knownCommands[$label]->getLabel() !== null and $this->knownCommands[$label]->getLabel() === $label){
|
||||
if(isset($this->knownCommands[$label]) and $this->knownCommands[$label]->getLabel() === $label){
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -226,8 +204,8 @@ class SimpleCommandMap implements CommandMap{
|
||||
* This method is intended to provide capability for handling commands with spaces in their name.
|
||||
* The referenced parameters will be modified accordingly depending on the resulting matched command.
|
||||
*
|
||||
* @param string &$commandName
|
||||
* @param string[] &$args
|
||||
* @param string $commandName reference parameter
|
||||
* @param string[] $args reference parameter
|
||||
*
|
||||
* @return Command|null
|
||||
*/
|
||||
@ -296,7 +274,6 @@ class SimpleCommandMap implements CommandMap{
|
||||
return $this->knownCommands;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
@ -318,22 +295,21 @@ class SimpleCommandMap implements CommandMap{
|
||||
$commandName = "";
|
||||
$command = $this->matchCommand($commandName, $args);
|
||||
|
||||
|
||||
if($command === null){
|
||||
$bad[] = $commandString;
|
||||
}elseif($commandName === $alias){
|
||||
}elseif(strcasecmp($commandName, $alias) === 0){
|
||||
$recursive[] = $commandString;
|
||||
}else{
|
||||
$targets[] = $commandString;
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($recursive)){
|
||||
if(count($recursive) > 0){
|
||||
$this->server->getLogger()->warning($this->server->getLanguage()->translateString("pocketmine.command.alias.recursive", [$alias, implode(", ", $recursive)]));
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!empty($bad)){
|
||||
if(count($bad) > 0){
|
||||
$this->server->getLogger()->warning($this->server->getLanguage()->translateString("pocketmine.command.alias.notFound", [$alias, implode(", ", $bad)]));
|
||||
continue;
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ class BanIpCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
private function processIPBan(string $ip, CommandSender $sender, string $reason){
|
||||
private function processIPBan(string $ip, CommandSender $sender, string $reason) : void{
|
||||
$sender->getServer()->getIPBans()->addBan($ip, $reason, null, $sender->getName());
|
||||
|
||||
foreach($sender->getServer()->getOnlinePlayers() as $player){
|
||||
|
@ -63,7 +63,7 @@ class BanListCommand extends VanillaCommand{
|
||||
}
|
||||
|
||||
$list = $list->getEntries();
|
||||
$message = implode(", ", array_map(function(BanEntry $entry){
|
||||
$message = implode(", ", array_map(function(BanEntry $entry) : string{
|
||||
return $entry->getName();
|
||||
}, $list));
|
||||
|
||||
|
@ -76,7 +76,7 @@ class EffectCommand extends VanillaCommand{
|
||||
}
|
||||
|
||||
if($effect === null){
|
||||
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.effect.notFound", [(string) $args[1]]));
|
||||
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.effect.notFound", [$args[1]]));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -124,7 +124,6 @@ class EffectCommand extends VanillaCommand{
|
||||
self::broadcastCommandMessage($sender, new TranslationContainer("%commands.effect.success", [$effect->getName(), $instance->getAmplifier(), $player->getDisplayName(), $instance->getDuration() / 20, $effect->getId()]));
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,6 @@ class EnchantCommand extends VanillaCommand{
|
||||
$item->addEnchantment(new EnchantmentInstance($enchantment, $level));
|
||||
$player->getInventory()->setItemInHand($item);
|
||||
|
||||
|
||||
self::broadcastCommandMessage($sender, new TranslationContainer("%commands.enchant.success", [$player->getName()]));
|
||||
return true;
|
||||
}
|
||||
|
@ -60,7 +60,6 @@ class GamemodeCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
$target = $sender;
|
||||
if(isset($args[1])){
|
||||
$target = $sender->getServer()->getPlayer($args[1]);
|
||||
if($target === null){
|
||||
@ -68,7 +67,9 @@ class GamemodeCommand extends VanillaCommand{
|
||||
|
||||
return true;
|
||||
}
|
||||
}elseif(!($sender instanceof Player)){
|
||||
}elseif($sender instanceof Player){
|
||||
$target = $sender;
|
||||
}else{
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
|
@ -57,22 +57,22 @@ class HelpCommand extends VanillaCommand{
|
||||
}
|
||||
|
||||
if(count($args) === 0){
|
||||
$command = "";
|
||||
$commandName = "";
|
||||
$pageNumber = 1;
|
||||
}elseif(is_numeric($args[count($args) - 1])){
|
||||
$pageNumber = (int) array_pop($args);
|
||||
if($pageNumber <= 0){
|
||||
$pageNumber = 1;
|
||||
}
|
||||
$command = implode(" ", $args);
|
||||
$commandName = implode(" ", $args);
|
||||
}else{
|
||||
$command = implode(" ", $args);
|
||||
$commandName = implode(" ", $args);
|
||||
$pageNumber = 1;
|
||||
}
|
||||
|
||||
$pageHeight = $sender->getScreenLineHeight();
|
||||
|
||||
if($command === ""){
|
||||
if($commandName === ""){
|
||||
/** @var Command[][] $commands */
|
||||
$commands = [];
|
||||
foreach($sender->getServer()->getCommandMap()->getCommands() as $command){
|
||||
@ -82,7 +82,7 @@ class HelpCommand extends VanillaCommand{
|
||||
}
|
||||
ksort($commands, SORT_NATURAL | SORT_FLAG_CASE);
|
||||
$commands = array_chunk($commands, $pageHeight);
|
||||
$pageNumber = (int) min(count($commands), $pageNumber);
|
||||
$pageNumber = min(count($commands), $pageNumber);
|
||||
if($pageNumber < 1){
|
||||
$pageNumber = 1;
|
||||
}
|
||||
@ -95,7 +95,7 @@ class HelpCommand extends VanillaCommand{
|
||||
|
||||
return true;
|
||||
}else{
|
||||
if(($cmd = $sender->getServer()->getCommandMap()->getCommand(strtolower($command))) instanceof Command){
|
||||
if(($cmd = $sender->getServer()->getCommandMap()->getCommand(strtolower($commandName))) instanceof Command){
|
||||
if($cmd->testPermissionSilent($sender)){
|
||||
$message = TextFormat::YELLOW . "--------- " . TextFormat::WHITE . " Help: /" . $cmd->getName() . TextFormat::YELLOW . " ---------\n";
|
||||
$message .= TextFormat::GOLD . "Description: " . TextFormat::WHITE . $cmd->getDescription() . "\n";
|
||||
@ -105,7 +105,7 @@ class HelpCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
$sender->sendMessage(TextFormat::RED . "No help for " . strtolower($command));
|
||||
$sender->sendMessage(TextFormat::RED . "No help for " . strtolower($commandName));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -68,7 +68,6 @@ class KickCommand extends VanillaCommand{
|
||||
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.player.notFound"));
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -47,9 +47,9 @@ class ListCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
$playerNames = array_map(function(Player $player){
|
||||
$playerNames = array_map(function(Player $player) : string{
|
||||
return $player->getName();
|
||||
}, array_filter($sender->getServer()->getOnlinePlayers(), function(Player $player) use ($sender){
|
||||
}, array_filter($sender->getServer()->getOnlinePlayers(), function(Player $player) use ($sender) : bool{
|
||||
return $player->isOnline() and (!($sender instanceof Player) or $sender->canSee($player));
|
||||
}));
|
||||
|
||||
|
@ -37,6 +37,7 @@ use pocketmine\level\particle\CriticalParticle;
|
||||
use pocketmine\level\particle\DustParticle;
|
||||
use pocketmine\level\particle\EnchantmentTableParticle;
|
||||
use pocketmine\level\particle\EnchantParticle;
|
||||
use pocketmine\level\particle\EntityFlameParticle;
|
||||
use pocketmine\level\particle\ExplodeParticle;
|
||||
use pocketmine\level\particle\FlameParticle;
|
||||
use pocketmine\level\particle\HappyVillagerParticle;
|
||||
@ -119,7 +120,6 @@ class ParticleCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
$sender->sendMessage(new TranslationContainer("commands.particle.success", [$name, $count]));
|
||||
|
||||
$random = new Random((int) (microtime(true) * 1000) + mt_rand());
|
||||
@ -137,13 +137,6 @@ class ParticleCommand extends VanillaCommand{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param Vector3 $pos
|
||||
* @param float $xd
|
||||
* @param float $yd
|
||||
* @param float $zd
|
||||
* @param int|null $data
|
||||
*
|
||||
* @return Particle|null
|
||||
*/
|
||||
private function getParticle(string $name, Vector3 $pos, float $xd, float $yd, float $zd, int $data = null){
|
||||
@ -212,7 +205,8 @@ class ParticleCommand extends VanillaCommand{
|
||||
return new AngryVillagerParticle($pos);
|
||||
case "forcefield":
|
||||
return new BlockForceFieldParticle($pos, $data ?? 0);
|
||||
|
||||
case "mobflame":
|
||||
return new EntityFlameParticle($pos);
|
||||
}
|
||||
|
||||
if(strpos($name, "iconcrack_") === 0){
|
||||
|
@ -52,7 +52,7 @@ class TeleportCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
$args = array_values(array_filter($args, function($arg){
|
||||
$args = array_values(array_filter($args, function(string $arg) : bool{
|
||||
return $arg !== "";
|
||||
}));
|
||||
if(count($args) < 1 or count($args) > 6){
|
||||
|
@ -85,7 +85,6 @@ class TimeCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if(count($args) < 2){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
@ -126,18 +126,25 @@ class TimingsCommand extends VanillaCommand{
|
||||
/** @var string */
|
||||
private $host;
|
||||
|
||||
/**
|
||||
* @param string[] $data
|
||||
* @phpstan-param array<string, string> $data
|
||||
*/
|
||||
public function __construct(CommandSender $sender, string $host, string $agent, array $data){
|
||||
parent::__construct([
|
||||
["page" => "https://$host?upload=true", "extraOpts" => [
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"User-Agent: $agent",
|
||||
"Content-Type: application/x-www-form-urlencoded"
|
||||
],
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => http_build_query($data),
|
||||
CURLOPT_AUTOREFERER => false,
|
||||
CURLOPT_FOLLOWLOCATION => false
|
||||
]]
|
||||
[
|
||||
"page" => "https://$host?upload=true",
|
||||
"extraOpts" => [
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"User-Agent: $agent",
|
||||
"Content-Type: application/x-www-form-urlencoded"
|
||||
],
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => http_build_query($data),
|
||||
CURLOPT_AUTOREFERER => false,
|
||||
CURLOPT_FOLLOWLOCATION => false
|
||||
]
|
||||
]
|
||||
], $sender);
|
||||
$this->host = $host;
|
||||
}
|
||||
|
@ -21,10 +21,8 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\Player;
|
||||
@ -42,6 +40,10 @@ class TransferServerCommand extends VanillaCommand{
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(!$this->testPermission($sender)){
|
||||
return true;
|
||||
}
|
||||
|
||||
if(count($args) < 1){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}elseif(!($sender instanceof Player)){
|
||||
|
@ -36,12 +36,7 @@ abstract class VanillaCommand extends Command{
|
||||
public const MIN_COORD = -30000000;
|
||||
|
||||
/**
|
||||
* @param CommandSender $sender
|
||||
* @param mixed $value
|
||||
* @param int $min
|
||||
* @param int $max
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getInteger(CommandSender $sender, $value, int $min = self::MIN_COORD, int $max = self::MAX_COORD) : int{
|
||||
$i = (int) $value;
|
||||
@ -55,15 +50,6 @@ abstract class VanillaCommand extends Command{
|
||||
return $i;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $original
|
||||
* @param CommandSender $sender
|
||||
* @param string $input
|
||||
* @param float $min
|
||||
* @param float $max
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected function getRelativeDouble(float $original, CommandSender $sender, string $input, float $min = self::MIN_COORD, float $max = self::MAX_COORD) : float{
|
||||
if($input[0] === "~"){
|
||||
$value = $this->getDouble($sender, substr($input, 1));
|
||||
@ -75,12 +61,7 @@ abstract class VanillaCommand extends Command{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CommandSender $sender
|
||||
* @param mixed $value
|
||||
* @param float $min
|
||||
* @param float $max
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected function getDouble(CommandSender $sender, $value, float $min = self::MIN_COORD, float $max = self::MAX_COORD) : float{
|
||||
$i = (double) $value;
|
||||
|
@ -84,7 +84,7 @@ class VersionCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
private function describeToSender(Plugin $plugin, CommandSender $sender){
|
||||
private function describeToSender(Plugin $plugin, CommandSender $sender) : void{
|
||||
$desc = $plugin->getDescription();
|
||||
$sender->sendMessage(TextFormat::DARK_GREEN . $desc->getName() . TextFormat::WHITE . " version " . TextFormat::DARK_GREEN . $desc->getVersion());
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user