mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-12 20:35:11 +00:00
Compare commits
1177 Commits
4.0.0-BETA
...
4.5.0
Author | SHA1 | Date | |
---|---|---|---|
64a8c462f9 | |||
4ec97d0f7a | |||
016a80bb70 | |||
ce66a400a7 | |||
50776875bb | |||
bcb0e2ff1f | |||
1584768c80 | |||
5fd685e07d | |||
6ecfbd1bde | |||
b661097c51 | |||
0771295899 | |||
702816458c | |||
e040c2b281 | |||
e12e4e8fb8 | |||
d15a90899e | |||
237c2866e0 | |||
38d6284671 | |||
7355798e77 | |||
4b662d65b3 | |||
c87a3b054c | |||
8b86e43d51 | |||
eade2d2af0 | |||
f2299a562f | |||
3fcf6372e0 | |||
533cb77c50 | |||
681a9bb0e1 | |||
6c080dae55 | |||
670fb4de74 | |||
6d7318af43 | |||
97c0d72e28 | |||
4ccae2d1de | |||
b36c6ea13b | |||
39b8daeeec | |||
c492352d50 | |||
8f1452acd1 | |||
8a2ba584ab | |||
227f28a6d2 | |||
812d5c3f58 | |||
9a5a03ef83 | |||
38d75f3aab | |||
179cac45f5 | |||
1591881bf2 | |||
7bbb2617c8 | |||
2ec65ba799 | |||
3dd7c09351 | |||
afc6e8878d | |||
7eaf1246a0 | |||
645c44ae9c | |||
331b05c681 | |||
3abe80184a | |||
7618b13c6e | |||
351cd4bfd7 | |||
1154c7c1ab | |||
4a3e42f82e | |||
8ecf9717d6 | |||
3ca80b353b | |||
7d172e2211 | |||
e934e2bd26 | |||
3177d19730 | |||
82104a8251 | |||
e9a17374d1 | |||
a31bd19b5a | |||
c82dfef9b0 | |||
1181b13b5d | |||
688be0a404 | |||
33e6b63fe5 | |||
5d92eddc82 | |||
0324392cd8 | |||
01b0742bd4 | |||
02cf6ae46c | |||
fcb2ccab99 | |||
a38a5c67f1 | |||
a45a96b3ee | |||
86efa0aae6 | |||
2b84cb7be4 | |||
26df37e6ef | |||
554f96bc24 | |||
6482aa7c64 | |||
6d941640a9 | |||
0ea3861d43 | |||
a323a5e56d | |||
79caba22a7 | |||
30815bc8a2 | |||
df3a69dcb7 | |||
d4b7f66e15 | |||
8e767da29e | |||
c0b15de504 | |||
1d5430937f | |||
9de88aa734 | |||
9e59819f06 | |||
c60311617d | |||
7bc3dcdefd | |||
22edca610c | |||
6eac2ea7a5 | |||
cd016bedce | |||
95ad3f16e1 | |||
fb4d332d1a | |||
a06b9294df | |||
221c6b8570 | |||
eb95e2a97e | |||
ec6769a6fc | |||
343a12626e | |||
d11d77d328 | |||
20eb80fc9a | |||
071067effb | |||
89cc449808 | |||
1e59679ec2 | |||
8b8560a701 | |||
161ab5af16 | |||
ab41594da2 | |||
80d4c11061 | |||
e767796986 | |||
dea7031b86 | |||
7e3d099d5b | |||
8b1bd5b7ff | |||
4dbac79e86 | |||
5abc7f866a | |||
9dc2a01c2e | |||
6f0aa360d1 | |||
7c3b78b0a0 | |||
12e4724b19 | |||
52e74296de | |||
3b7e274c34 | |||
db6abfb227 | |||
2adaca2521 | |||
b6f39035f8 | |||
cfd550451f | |||
9ff1bf6deb | |||
212c94ce98 | |||
77530b0c24 | |||
3e1246acff | |||
4c29f98292 | |||
5cc0d92eff | |||
b875b68fc7 | |||
a5ebbf8adb | |||
217385efb9 | |||
f70c36baf9 | |||
eda4ae9181 | |||
d2e421c424 | |||
6da53536ca | |||
1da6aa40f8 | |||
a913736235 | |||
124edeacaf | |||
a216f4d089 | |||
17b0e0be84 | |||
81d8aed2e2 | |||
69418084bc | |||
593a4b65ea | |||
869d340f10 | |||
5d64d4a1e3 | |||
cc3c5bdb8d | |||
e1c4150dff | |||
755ca1af9b | |||
7d78b9cb2c | |||
91f802ac7a | |||
72cfea3a63 | |||
a353872327 | |||
f4d71d0b48 | |||
a6299b0927 | |||
6e372d9e36 | |||
ad8132ae11 | |||
5d39d7a1c8 | |||
937bb4c6ce | |||
cf15a0913d | |||
33cf085692 | |||
3752225ed5 | |||
5cf572892f | |||
20ff5d5a3d | |||
b88a47929f | |||
159392e738 | |||
2f03af51dd | |||
cb76c149e1 | |||
6d7bf1c5d8 | |||
ed2a239334 | |||
46c504e529 | |||
0e7e776862 | |||
de12b701ac | |||
b402df8b91 | |||
dca457b1e0 | |||
72cff0ee11 | |||
09778e3f1b | |||
9f5d4180c9 | |||
c8a7a53d70 | |||
223893fd5c | |||
a58551af5b | |||
f7dce4af88 | |||
dff5c30172 | |||
e8994dbc17 | |||
aaba8a2a9a | |||
27056b6c37 | |||
9930de01b9 | |||
cd021f49cd | |||
e4ce467c0b | |||
6b4687a36b | |||
c085bf0db4 | |||
e0d4bd985e | |||
3339225fe8 | |||
df33e179e5 | |||
624a7dff16 | |||
1d314ad4ce | |||
5a98b08ee8 | |||
ded7e24f67 | |||
e73bb07da0 | |||
d9d02d526a | |||
f272986903 | |||
988da8eaab | |||
ea7f706aed | |||
52e3f1e269 | |||
4c9d2a989e | |||
022db5cbe3 | |||
3bbf558883 | |||
1d68d9f71a | |||
f2e8824242 | |||
a0e47b5a64 | |||
f7465f55e7 | |||
453bf6d73b | |||
3353a00641 | |||
e388cb1643 | |||
741182c55f | |||
2efce35331 | |||
d1dfbd95e2 | |||
4fc712119f | |||
1aee5b1ed8 | |||
fefd3e6b29 | |||
9b43be9d9c | |||
ea677154cb | |||
7f2802e75f | |||
f924208881 | |||
6bea2961d9 | |||
ac3a6033b9 | |||
d7e6b01216 | |||
26aee7ff73 | |||
319c8fe32c | |||
ce121ccea9 | |||
7f1a4185b5 | |||
7d1464f0a1 | |||
8cc7fb9dd9 | |||
194cb1fb84 | |||
8ea106c091 | |||
a6cb3313b0 | |||
c6374b79b0 | |||
f25beab6cb | |||
901449b0b1 | |||
a9f2766a8b | |||
4e777572c9 | |||
90a8595a40 | |||
bf71eb448a | |||
2c29d272ad | |||
98aa2b9ff9 | |||
ea33a04d00 | |||
9963fcf849 | |||
ab93135b84 | |||
4a94cb85a2 | |||
b7e6854189 | |||
2b8a54f8ff | |||
a5dab0f61e | |||
824f1f24ff | |||
f4f5c3128f | |||
fdd42fd15f | |||
05a5e5eac1 | |||
c8e1cfcbee | |||
869dda9a45 | |||
e2c647ef91 | |||
05fdd94754 | |||
4a599b58ff | |||
05792826bc | |||
fbf7ad4295 | |||
6c1c0c867e | |||
5c0eb92d81 | |||
1e88412a8f | |||
f97ce6afef | |||
879476d8e0 | |||
6d584cf008 | |||
8efa299c65 | |||
b6e7ad187a | |||
5ef73ca9aa | |||
c50518a4ca | |||
4c98780bdb | |||
856fd2a33b | |||
581bbfe255 | |||
b4e1edaa64 | |||
025f6407e2 | |||
10c0d83fa5 | |||
9a6ec14cbf | |||
f77fec0c3c | |||
5d970cf5bd | |||
58e186440b | |||
6a39caa204 | |||
91f81d4c8e | |||
2b81b53dfa | |||
dfd8c4e4b8 | |||
c9c50e16ec | |||
eff856d8e5 | |||
90a369f0b6 | |||
ba05b4f024 | |||
3e90c3072a | |||
12946fbe46 | |||
70f923714c | |||
7cd394b0fb | |||
0bca098707 | |||
d47a7f48bd | |||
f181c60209 | |||
784c34f784 | |||
03fa5387ac | |||
1ea0b8a9df | |||
566e4a4196 | |||
61265604fb | |||
29909e7f44 | |||
3232a83965 | |||
c816bbdb6e | |||
4f25ab10e9 | |||
f04099c5de | |||
fdb82f5fb8 | |||
75d4c47384 | |||
bd4c2b5245 | |||
d60dba2de0 | |||
51a3043dfd | |||
7098bcec8c | |||
6d65512531 | |||
3ed336fa0e | |||
b26b1cd32f | |||
54db842d16 | |||
31a0085efb | |||
715355e148 | |||
55dfacea8d | |||
55c744cc00 | |||
7e903fde5b | |||
d702113fb5 | |||
4f44a067b0 | |||
44818e6d14 | |||
325131dd30 | |||
38eeda6e8b | |||
1eb59fb9b5 | |||
1c60aa9769 | |||
735e4cc3bc | |||
e9dd9df0a0 | |||
032b15efe0 | |||
256826d9c7 | |||
c273b29dec | |||
c19a038d47 | |||
95bc013e97 | |||
7ddd547190 | |||
38e34093cf | |||
dd1ebb5915 | |||
df1cdbe921 | |||
7846ea8acc | |||
1dc0d5f96a | |||
712ffb3e31 | |||
2a4111868c | |||
123701ed76 | |||
28dce8783f | |||
3781b62d35 | |||
859f062267 | |||
15425d01bc | |||
0642364a44 | |||
cfdbfa3d58 | |||
e9a6c0ba58 | |||
466b018319 | |||
d16b6fe61e | |||
7a75fcda44 | |||
8d289ab01d | |||
363a9689b4 | |||
40c7497efe | |||
6ccb1ff114 | |||
1d2593208a | |||
a7bdef69e2 | |||
d9ea647925 | |||
6673289c33 | |||
822af4f7f5 | |||
3155c90396 | |||
1dbfedce4c | |||
3ab5b5a79d | |||
8a4bc72b34 | |||
6cbc14f2b2 | |||
75d0fc4749 | |||
ea161af4e5 | |||
0bf5f97fe9 | |||
b9f1bcf0e4 | |||
32b07e0940 | |||
99f087e5e1 | |||
22a4117109 | |||
aaf7a88de7 | |||
e0da99a973 | |||
b2630a0920 | |||
67a0ae0246 | |||
5ae20459dd | |||
587da478a6 | |||
419bb9eba6 | |||
82f1c2766c | |||
b3fec3d86f | |||
60ef2db892 | |||
e21446e583 | |||
7bf0bc2ca7 | |||
e5a9123522 | |||
09201ac14b | |||
0697c7d316 | |||
1eae133118 | |||
d28be4eaf2 | |||
b33a75a6d1 | |||
f9c8c0e34d | |||
58ba4f680f | |||
8c5cc67e07 | |||
ab8b24bcd2 | |||
94c4f58667 | |||
c10eda5eae | |||
ed312863a7 | |||
387c13beff | |||
56fe71d939 | |||
73d8c87b76 | |||
fc53f3721a | |||
345ac75aac | |||
32db27af78 | |||
4e956d5d1d | |||
61f8144280 | |||
ae03c70dfc | |||
e986a0a4f2 | |||
b85fe0e72a | |||
03f47d0a78 | |||
3f8f5cd200 | |||
aa6bd4438a | |||
22fb02c4e6 | |||
373880e582 | |||
8f525ab399 | |||
be1996752a | |||
2bcb629d78 | |||
aae5962f6a | |||
282b430b1f | |||
c47dfa1fb8 | |||
8db137882c | |||
79d1feff9c | |||
2f32bd877a | |||
22bc3bc3f9 | |||
6846f1e78a | |||
4d55935bd8 | |||
9c328690f8 | |||
b60dd1e9b4 | |||
86bcc49972 | |||
061d851fbd | |||
a67aef0477 | |||
088745cf3b | |||
8cdfef7861 | |||
a0bb7059c1 | |||
858024afb7 | |||
eaaf00ca2b | |||
f1723acfd3 | |||
8da27ea0aa | |||
388622d55d | |||
bac6a2a1eb | |||
b9b76eaed2 | |||
9f4fcfafdb | |||
853ecd2408 | |||
33421258b6 | |||
c221484fc3 | |||
d9deb571ed | |||
42d07c74d7 | |||
1366c49f1f | |||
6679c53e56 | |||
ee6548aa50 | |||
9d061e86af | |||
f7d25f251e | |||
0ccb47fb07 | |||
0973472842 | |||
f126479c37 | |||
d34f4b28b3 | |||
8a65fd273a | |||
248cc0ef49 | |||
d1726aa20c | |||
58e1e7bd6f | |||
a5c0958adf | |||
fd880d8465 | |||
a323fb7bb5 | |||
0a5b146189 | |||
1948b00008 | |||
b4e1871899 | |||
78eaa0993d | |||
bee2aba813 | |||
af81f80cf3 | |||
dbbbc4f9c9 | |||
51f2a78dcf | |||
5128bc02bb | |||
4f4aa62479 | |||
c267e7b3c2 | |||
3faeb5a556 | |||
0bc578b8fc | |||
661848c5e7 | |||
75fc7a2d1f | |||
43c5d08042 | |||
6d249026cc | |||
ed2145b6a4 | |||
3e6c157217 | |||
4f8a0bad25 | |||
fb29653ed7 | |||
ffa8cf3ec3 | |||
86beeb8255 | |||
230a3c9839 | |||
35f205b476 | |||
e7d17eb4d3 | |||
73168a0e39 | |||
e8893dd91f | |||
a4af1609ea | |||
8c4b8a9042 | |||
6492cac5c1 | |||
958a9dbf0f | |||
3ed57ce49a | |||
68f3399cfd | |||
aeab19a616 | |||
8532e9c8e0 | |||
7bee72ef2d | |||
0d595e4324 | |||
e43e0189df | |||
decd1da2d0 | |||
bcc0f1e733 | |||
e04dfe96af | |||
f62cfe8ae3 | |||
b903e90dc2 | |||
c8247786d7 | |||
f486b5f4a7 | |||
54d6b83fc2 | |||
eedea38669 | |||
3c6146b5e0 | |||
72f2c794ab | |||
193a1b3f4e | |||
62afa2f28d | |||
207f7ec309 | |||
e0a6bc1d4a | |||
5c994e4a24 | |||
d94578a420 | |||
0a0de018a5 | |||
a1d217e12b | |||
e102339637 | |||
7124d44b92 | |||
38b6b39cb3 | |||
767dfd9947 | |||
fcc4757209 | |||
d9c70cb176 | |||
4aab0565c0 | |||
87170ab067 | |||
74ac0f5862 | |||
f5144d49b1 | |||
8943d8a2a7 | |||
0da29beb1d | |||
157048264c | |||
95b6cb21f2 | |||
c858c0dc79 | |||
b55aa78aec | |||
091673d8f1 | |||
18e26d975b | |||
d41f933e7b | |||
65dabefa3b | |||
44e8603a6d | |||
e3614d1a82 | |||
16fd5456aa | |||
93caf72f34 | |||
089f22d903 | |||
fc3a6c6984 | |||
1ab285f573 | |||
aa56c66a3c | |||
920462bdcc | |||
e6e1bca676 | |||
795ebd1824 | |||
5f03887b47 | |||
9979a64ad2 | |||
75a72786f9 | |||
3d205c6e5f | |||
2955a92837 | |||
e70f81a111 | |||
482bc462d3 | |||
de82424fb2 | |||
d487e43766 | |||
57e1509c3a | |||
6494375a53 | |||
4466166f8b | |||
0da1810aaa | |||
3aa34b59a5 | |||
c04b00d09d | |||
6e67c7532a | |||
5f8ebd81d7 | |||
79b5109953 | |||
4d37b79ff7 | |||
60938c8c9d | |||
49a8afd126 | |||
dbad5dd611 | |||
ea1fceece2 | |||
7fb1669c6d | |||
a41404bd8a | |||
4b06fe73f2 | |||
929abb04be | |||
a09817864b | |||
45c4a9673d | |||
4ad8cb02a5 | |||
1c6907c636 | |||
7e6bbcc393 | |||
7184c02bb6 | |||
8a94aa10a4 | |||
c334e6dec7 | |||
89a766b799 | |||
7e99e5167c | |||
f5bbd30dbb | |||
3be8472ae2 | |||
22bb1ce8e0 | |||
178dcb71a9 | |||
0a58fd5472 | |||
e06eefeab0 | |||
ede07c4314 | |||
cba00bf1e2 | |||
e81bee3866 | |||
e6b85988b2 | |||
b50591303b | |||
9e75c1463a | |||
a94b88424e | |||
448f26cefc | |||
fa48100da5 | |||
bcf8a3424c | |||
69d5bfa0d4 | |||
549fb923bf | |||
6d5c463bdd | |||
911ad344c9 | |||
3b77462935 | |||
6b40ed7bf8 | |||
1ed9302f5a | |||
b3dab0beef | |||
7ad1afee89 | |||
292827a311 | |||
f8ed23cc1e | |||
6ddaed97fa | |||
036b90d247 | |||
d909cd8a91 | |||
06eaf9f273 | |||
1e56ed2ea3 | |||
dccb8a3595 | |||
0ace807756 | |||
40895a86e5 | |||
b081394125 | |||
f48cf68cac | |||
264cff70ec | |||
3aabfa4ab0 | |||
922ce2e312 | |||
0793e7e094 | |||
7a385ddc8b | |||
2254f31bec | |||
77a74d84e2 | |||
5b868e6d5e | |||
889d048ca3 | |||
8b73549355 | |||
c6466a6da9 | |||
3d9e19546f | |||
45b4fa0e96 | |||
bf29409a45 | |||
503c888838 | |||
e0eeb87ea0 | |||
78ffad5ffc | |||
1d14c8cb6b | |||
49d0d01f9f | |||
ed4978c31b | |||
3728ddbf24 | |||
5a351d3b17 | |||
0c012ca5d9 | |||
0530cb72df | |||
8f2ca92f02 | |||
ce54d268f2 | |||
cd850b111d | |||
ee060f3e02 | |||
e7deffa9af | |||
6e4b73c183 | |||
62f150586f | |||
8ed9551ac9 | |||
2486dabd8a | |||
4d2d0f1d35 | |||
4f3a60ac90 | |||
98c31cf07b | |||
9256afd439 | |||
cac9db9bcc | |||
300d194185 | |||
13340a21d3 | |||
27f599793a | |||
527e975fa9 | |||
8e37f86480 | |||
8e8cee45b8 | |||
1a046c6cd5 | |||
e61aaaccca | |||
1b86355c40 | |||
1669d33f7e | |||
2da65c5a6e | |||
468faa464b | |||
59de045ecb | |||
bd8308cc6f | |||
edc3bae172 | |||
06e7030817 | |||
cb0af44ccb | |||
d535f02096 | |||
7665f4f443 | |||
20d6b69813 | |||
6b7d0307af | |||
baeac2eb07 | |||
2850ea1e89 | |||
d560cf17fc | |||
3f6efd0018 | |||
aea124af74 | |||
8620e67d88 | |||
d5f81fe261 | |||
0aeac3af7d | |||
9931c1d50a | |||
d21a3d8750 | |||
6d62b06ce6 | |||
8be92d16fe | |||
8079ae341a | |||
ba295dc7dc | |||
38325c8573 | |||
f239b077b9 | |||
6f8f460a6c | |||
882df94bcb | |||
4a8ca603a1 | |||
52f0c4f3ed | |||
e2815eed60 | |||
932a88764c | |||
9540193766 | |||
cc23e0b7a1 | |||
1f9400f901 | |||
e5149756a8 | |||
bc18969a09 | |||
c19174a174 | |||
f95142f6b6 | |||
7ace24caab | |||
32f619ac49 | |||
1bb6ac4fb6 | |||
533d3aae8b | |||
52a891ba73 | |||
71b813d4f9 | |||
f2540a72ad | |||
03f13495b7 | |||
7e0f6c02a1 | |||
1bc7869f6e | |||
5556861000 | |||
7dd5d0b593 | |||
9338d42742 | |||
9346ecdc39 | |||
c023c02b6c | |||
bb7683158f | |||
fad96b77ce | |||
40575a6dcf | |||
40f8f042da | |||
0fe6038c41 | |||
adff561483 | |||
ad56392d95 | |||
472ffb28ff | |||
726c5652f7 | |||
b784a04e08 | |||
5c7125f190 | |||
eb0cf52d81 | |||
d8f0fd0a7e | |||
fb0eebc0dc | |||
020cd7b966 | |||
c37c261c0f | |||
2bb97d8904 | |||
d3878b2d57 | |||
cbe0f44c4f | |||
37622e02b8 | |||
ed8b4950a3 | |||
fc7d297f60 | |||
7b4ef293bd | |||
c72d66f370 | |||
3683884b9c | |||
37e8b1ee8c | |||
046dafc34f | |||
db135788b9 | |||
b34e6f53eb | |||
b4b954cc5f | |||
7210db25b0 | |||
4599913034 | |||
c48aa274e7 | |||
269231c228 | |||
4cad552909 | |||
f2d5455c5e | |||
65247b7248 | |||
2f408708f0 | |||
3dd03075cb | |||
82b5bca83e | |||
639867a640 | |||
d4a382d568 | |||
399824c31c | |||
ada469bc45 | |||
dc8243f88b | |||
7668171c56 | |||
e4754ab029 | |||
3276047497 | |||
49a8eff11e | |||
73592349cd | |||
635a9143de | |||
c3ec9c0948 | |||
09a2e006a8 | |||
fed59d3ebe | |||
c7beb0a702 | |||
5be429a8c4 | |||
ab002ca06d | |||
6efb1db107 | |||
6fdcfb01c8 | |||
1beec348f9 | |||
7306a2d939 | |||
4bf338f783 | |||
255ff63fda | |||
d72f6a3ac6 | |||
93a1e84ad9 | |||
c33f97ae41 | |||
cc4bb91fcb | |||
eb9012401b | |||
3b34268ed6 | |||
4c07078586 | |||
19a3efe893 | |||
a1ecdc27e5 | |||
f93b5be789 | |||
1fb60b5b3a | |||
08420c2556 | |||
18f5fb66bb | |||
a6f6b60bed | |||
c6c992a1f0 | |||
df39a1ca07 | |||
be6d1843de | |||
2b0b9bd8ed | |||
76dad46e13 | |||
eb3530b6e6 | |||
4131bcef08 | |||
b84f7c18ec | |||
45edb94607 | |||
6b316dc29a | |||
d9d37f7fa6 | |||
4cb6c7dc1e | |||
b392651354 | |||
f81c55ce6c | |||
002feacf8e | |||
b8523f7a18 | |||
640e88009b | |||
6cd272c9e1 | |||
566c57bcd3 | |||
3c754b079c | |||
dbf9a33160 | |||
07b1cff306 | |||
0989c77037 | |||
5107d0df4e | |||
579ef63663 | |||
8abc952c74 | |||
4c3a5fdd73 | |||
54f287feb6 | |||
84f8b3eb2d | |||
15fca84f3b | |||
c60144210f | |||
8ac999cbd4 | |||
4f8501ff34 | |||
2405e45b35 | |||
e0b07ff308 | |||
729f831b8f | |||
0356716e8e | |||
5c81b04813 | |||
1ebb206762 | |||
29e2d92098 | |||
ef82a2cd79 | |||
87031627bf | |||
f066199971 | |||
a0e9eec652 | |||
fa6a432d58 | |||
102277c636 | |||
f50f26d52e | |||
4ca7c29cde | |||
9f64bc8180 | |||
f75a05d7fa | |||
3dae873731 | |||
aa0dc60c32 | |||
d184838ba0 | |||
ead8ccf08d | |||
38f97bed52 | |||
275f145418 | |||
6b07f7a5ec | |||
e131c2cefa | |||
e34364412b | |||
4eef458d29 | |||
8b3565b75d | |||
facfd7c04a | |||
65ef9f786a | |||
4dc13ab3da | |||
ede4157814 | |||
34ea199fb0 | |||
1775699f05 | |||
32a857b8b4 | |||
7e4be29fc4 | |||
c17587d436 | |||
0f6b7e48cb | |||
f2912fcdd8 | |||
f6cb4f9597 | |||
54442f7e4b | |||
5257755dc5 | |||
8c16ecaa5b | |||
3214da8642 | |||
f827a555d5 | |||
61145baded | |||
4d54d6c552 | |||
485bc2c565 | |||
07b4f844a9 | |||
19e5775f6b | |||
804fb3f603 | |||
6175b03433 | |||
a78248a19c | |||
414ccb9f10 | |||
794142fe49 | |||
ff27c5f7db | |||
4d4362801f | |||
0babe0a1ab | |||
d696ebcda3 | |||
c3768b997a | |||
f6480017ce | |||
9f5c16bc46 | |||
8865bb73ba | |||
2dee1dbc28 | |||
0f0b6f0efa | |||
d5f13d8be2 | |||
27ae959e89 | |||
f8f39687e2 | |||
94737934de | |||
debb469de1 | |||
616eb0050d | |||
9d30bc8b95 | |||
46b7d35cd3 | |||
c781efcf90 | |||
e4a54f5b6a | |||
afb54f1ae4 | |||
8f803df511 | |||
f4a3c40b5c | |||
9dec82cdbc | |||
74031d2fbe | |||
bd60e41268 | |||
96cfdc79b8 | |||
2fa0a914ff | |||
08636d079d | |||
3265d3f6b4 | |||
0f78a2b5ef | |||
f1a791ef75 | |||
866020dfdb | |||
c580bb2434 | |||
4fe3f69702 | |||
018006541e | |||
fbb91d123d | |||
3dc75644d9 | |||
1cabe4baf3 | |||
73dc0598e4 | |||
faad2365e2 | |||
4f816d03a7 | |||
1d22761d27 | |||
5b8ce7e3e2 | |||
08f3c18de9 | |||
141fbde660 | |||
465a509858 | |||
69952ae2af | |||
71f2a34616 | |||
63dfcc60c3 | |||
428bd5ae91 | |||
d17cd65803 | |||
a8d5e8c5f6 | |||
19f448d074 | |||
1c18c731ef | |||
8a2ecfe1d4 | |||
089e62b44e | |||
32a34d2494 | |||
ee9f5e0044 | |||
88b7389080 | |||
f1cc168d26 | |||
fb5543a2ad | |||
a4eda9a8f5 | |||
eb75df6f8e | |||
c66790b6a6 | |||
d78801b9d5 | |||
d410db4302 | |||
a62ce64fdd | |||
5db3915aad | |||
eb40b741ae | |||
b3720b3f17 | |||
7effa03ba4 | |||
d0474ccd92 | |||
2b0768f720 | |||
dba148cfaa | |||
48f77abe7e | |||
bb05af103d | |||
0ef5c67b9b | |||
6d89265510 | |||
a7d8a598e1 | |||
51fbff204b | |||
1873457840 | |||
fca70efbb1 | |||
8f88393184 | |||
b9d9b69bbe | |||
1d99cd329a | |||
bd8cba1a7f | |||
24d4daec90 | |||
4178c81209 | |||
94f4ef5862 | |||
2e2515354c | |||
359d0835f3 | |||
d4cbde6f10 | |||
a5418a019d | |||
baba25953f | |||
d53347454b | |||
401e8d117b | |||
9835d75f65 | |||
b8519d1af4 | |||
f6e53f826b | |||
42ede30e77 | |||
04aedc6494 | |||
701a71a4ee | |||
e50072dc27 | |||
c77829f4ad | |||
c773e43eda | |||
c262c2e726 | |||
a4b65d6a3f | |||
986b4e0651 | |||
2971bf30a5 | |||
4f2bcb61d6 | |||
e2275cc8ec | |||
620874d902 | |||
44508a138f | |||
aa408c9a97 | |||
6d78a0b435 | |||
76b4b23d98 | |||
03fcd844eb | |||
fecc13f362 | |||
9646128d01 | |||
a788954551 | |||
dc07ac33d3 | |||
ec3986827c | |||
09c840b66a | |||
80b402e529 | |||
a3f8546ac4 | |||
46920818b5 | |||
69cb575789 | |||
fee6478cbe | |||
9c5cec77b1 | |||
f48b703533 | |||
70636f6eb4 | |||
c70b80c273 | |||
a794d24c81 | |||
8db5732b44 | |||
48f809d3fa | |||
0348236860 | |||
8c07748100 | |||
06e7338ff9 | |||
bdbfa70558 | |||
7a4af7a0bc | |||
34b1392598 | |||
321345fcc8 | |||
0ac9f4fe61 | |||
2db53775e0 | |||
8523f0fb0b | |||
b570324288 | |||
6284cd14c7 | |||
ce8af4e3bc | |||
b65e89b605 | |||
d3f74d6ce1 | |||
bbd925abc4 | |||
4bf6205a6c | |||
b5699679ef | |||
824a89edfe | |||
ead9aae23c | |||
aefa0afd7c | |||
ec2699ffee | |||
49c1e4c06e | |||
9b94a4661b | |||
62f11360ee | |||
a5833327f0 | |||
d73ea8efe4 | |||
835e18ce6e | |||
01c0602043 | |||
8fd475f87b | |||
34f54750c8 | |||
092aabeb97 | |||
89d7b7198f | |||
70deea0ef9 | |||
859cdfa5d2 | |||
fa93a8d78f | |||
7b6632941d | |||
e62794e4cf | |||
500c298aaf | |||
8ac16345a3 | |||
19a66a8d03 | |||
6d728e8d98 | |||
e1ee320c8d | |||
965a16d19d | |||
5bae458a91 | |||
2696698926 | |||
912e612743 | |||
fd2df637b6 | |||
aa53dc6709 | |||
c1f843a42c | |||
09715906c8 | |||
13068ba3a7 | |||
b54854529f | |||
974d08efd6 | |||
289553fa46 | |||
e38866c4ba | |||
58a95f8836 | |||
ccc881ee58 | |||
308d7c126a | |||
4910250a81 | |||
e0d2e24698 | |||
d5f02a0bf8 | |||
2a3a57c519 | |||
5115387feb | |||
dd0aaf59b5 | |||
a555f21b18 | |||
1be9b2f037 | |||
32fd9879e5 | |||
dc2e8e7e8f | |||
847e24fc41 | |||
9e6d740570 | |||
8e3772ceef | |||
e032b8fe20 | |||
90800a4124 | |||
4b00465e24 | |||
10b3596eef | |||
258c38f9cd | |||
d07517fe8b | |||
31a176286d | |||
1fafce6d6f | |||
5061bbbc25 | |||
a101d1cdf9 | |||
fec48003d9 | |||
e25c03eec1 | |||
7245d15abe | |||
13178a47a5 | |||
817ab88c70 | |||
fef8297907 | |||
dbeaf27cb7 | |||
2db79cf58d | |||
7d06b76aaf | |||
0ad663ff50 | |||
a27c14c00c | |||
5b26abcb0e | |||
f2d6059613 | |||
bb6ea8cbdc | |||
356a49d225 | |||
6332af3e59 | |||
fb570970a8 | |||
30e10c38b6 | |||
05dc675d5b | |||
d63b9d1648 | |||
f9e6fd44bc | |||
0108888450 | |||
dd0c2fed82 | |||
2566123e49 | |||
54174eefa0 | |||
f5266ec816 | |||
c6b2c63a9b | |||
f26f063164 | |||
81d5598e96 | |||
c7e9138994 | |||
88f799da2c | |||
8de30e8162 | |||
e6f6a036ef | |||
32f8b8163e | |||
5b818827db | |||
42bf9578ce | |||
aee4a00a50 | |||
2fdd8d039e | |||
349f37b15f | |||
afa3349c04 | |||
6a8280b1ba | |||
003c002208 | |||
d417b1e2f5 | |||
65e468e3c2 | |||
a11cf8c296 | |||
c931c52617 | |||
b3e8314b9f | |||
f138004913 | |||
8e2d06a880 | |||
eb80515e99 | |||
1cb540387c | |||
d455188d03 | |||
14fba36636 | |||
43ac3fbf3e | |||
352162a6e6 | |||
b3601c9390 | |||
817fec9e3d |
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -4,6 +4,7 @@
|
|||||||
*.sh text eol=lf
|
*.sh text eol=lf
|
||||||
*.txt text eol=lf
|
*.txt text eol=lf
|
||||||
*.properties text eol=lf
|
*.properties text eol=lf
|
||||||
|
*.neon text eol=lf
|
||||||
*.bat text eol=crlf
|
*.bat text eol=crlf
|
||||||
*.cmd text eol=crlf
|
*.cmd text eol=crlf
|
||||||
*.ps1 text eol=crlf
|
*.ps1 text eol=crlf
|
||||||
|
10
.github/dependabot.yml
vendored
10
.github/dependabot.yml
vendored
@ -6,3 +6,13 @@ updates:
|
|||||||
interval: daily
|
interval: daily
|
||||||
time: "10:00"
|
time: "10:00"
|
||||||
open-pull-requests-limit: 10
|
open-pull-requests-limit: 10
|
||||||
|
|
||||||
|
- package-ecosystem: gitsubmodule
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: daily
|
||||||
|
|
||||||
|
- package-ecosystem: github-actions
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: daily
|
||||||
|
BIN
.github/readme/pocketmine-dark.png
vendored
Normal file
BIN
.github/readme/pocketmine-dark.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
BIN
.github/readme/pocketmine.png
vendored
Normal file
BIN
.github/readme/pocketmine.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
97
.github/workflows/build-docker-image.yml
vendored
Normal file
97
.github/workflows/build-docker-image.yml
vendored
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
name: Update Docker Hub images
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Update Docker Hub images
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Clone pmmp/PocketMine-Docker repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
repository: pmmp/PocketMine-Docker
|
||||||
|
fetch-depth: 1
|
||||||
|
|
||||||
|
- name: Get tag names
|
||||||
|
id: tag-name
|
||||||
|
run: |
|
||||||
|
VERSION=$(echo "${{ github.ref }}" | sed 's{^refs/tags/{{')
|
||||||
|
echo ::set-output name=TAG_NAME::$VERSION
|
||||||
|
echo ::set-output name=MAJOR::$(echo $VERSION | cut -d. -f1)
|
||||||
|
echo ::set-output name=MINOR::$(echo $VERSION | cut -d. -f1-2)
|
||||||
|
|
||||||
|
- name: Download new release information
|
||||||
|
run: curl -f -L ${{ github.server_url }}/${{ github.repository }}/releases/download/${{ steps.tag-name.outputs.TAG_NAME }}/build_info.json -o new_build_info.json
|
||||||
|
|
||||||
|
- name: Detect channel
|
||||||
|
id: channel
|
||||||
|
run: echo ::set-output name=CHANNEL::$(jq -r '.channel' new_build_info.json)
|
||||||
|
|
||||||
|
- name: Get name of Docker repository name
|
||||||
|
id: docker-repo-name
|
||||||
|
run: echo ::set-output name=NAME::$(echo "${GITHUB_REPOSITORY,,}")
|
||||||
|
|
||||||
|
- name: Build image for tag
|
||||||
|
uses: docker/build-push-action@v3.0.0
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
context: ./pocketmine-mp
|
||||||
|
tags: |
|
||||||
|
${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.TAG_NAME }}
|
||||||
|
# ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.TAG_NAME }}
|
||||||
|
build-args: |
|
||||||
|
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||||
|
PMMP_REPO=${{ github.repository }}
|
||||||
|
|
||||||
|
- name: Build image for major tag
|
||||||
|
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||||
|
uses: docker/build-push-action@v3.0.0
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
context: ./pocketmine-mp
|
||||||
|
tags: |
|
||||||
|
${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MAJOR }}
|
||||||
|
# ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MAJOR }}
|
||||||
|
build-args: |
|
||||||
|
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||||
|
PMMP_REPO=${{ github.repository }}
|
||||||
|
|
||||||
|
- name: Build image for minor tag
|
||||||
|
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||||
|
uses: docker/build-push-action@v3.0.0
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
context: ./pocketmine-mp
|
||||||
|
tags: |
|
||||||
|
${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MINOR }}
|
||||||
|
# ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MINOR }}
|
||||||
|
build-args: |
|
||||||
|
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||||
|
PMMP_REPO=${{ github.repository }}
|
||||||
|
|
||||||
|
- name: Build image for latest tag
|
||||||
|
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||||
|
uses: docker/build-push-action@v3.0.0
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
context: ./pocketmine-mp
|
||||||
|
tags: |
|
||||||
|
${{ steps.docker-repo-name.outputs.NAME }}:latest
|
||||||
|
# ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:latest
|
||||||
|
build-args: |
|
||||||
|
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||||
|
PMMP_REPO=${{ github.repository }}
|
23
.github/workflows/draft-release.yml
vendored
23
.github/workflows/draft-release.yml
vendored
@ -13,17 +13,17 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@2.12.0
|
uses: shivammathur/setup-php@2.19.0
|
||||||
with:
|
with:
|
||||||
php-version: 8.0
|
php-version: 8.0
|
||||||
|
|
||||||
- name: Restore Composer package cache
|
- name: Restore Composer package cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/composer/files
|
~/.cache/composer/files
|
||||||
@ -35,17 +35,18 @@ jobs:
|
|||||||
- name: Install Composer dependencies
|
- name: Install Composer dependencies
|
||||||
run: composer install --no-dev --prefer-dist --no-interaction --ignore-platform-reqs
|
run: composer install --no-dev --prefer-dist --no-interaction --ignore-platform-reqs
|
||||||
|
|
||||||
- name: Patch VersionInfo
|
- name: Calculate build number
|
||||||
|
id: build-number
|
||||||
run: |
|
run: |
|
||||||
BUILD_NUMBER=2000+$GITHUB_RUN_NUMBER #to stay above jenkins
|
BUILD_NUMBER=$((2000+$GITHUB_RUN_NUMBER)) #to stay above jenkins
|
||||||
echo "Build number: $BUILD_NUMBER"
|
echo "Build number: $BUILD_NUMBER"
|
||||||
sed -i "s/const BUILD_NUMBER = 0/const BUILD_NUMBER = ${BUILD_NUMBER}/" src/VersionInfo.php
|
echo ::set-output name=BUILD_NUMBER::$BUILD_NUMBER
|
||||||
|
|
||||||
- name: Minify BedrockData JSON files
|
- name: Minify BedrockData JSON files
|
||||||
run: php resources/vanilla/.minify_json.php
|
run: php vendor/pocketmine/bedrock-data/.minify_json.php
|
||||||
|
|
||||||
- name: Build PocketMine-MP.phar
|
- name: Build PocketMine-MP.phar
|
||||||
run: php -dphar.readonly=0 build/server-phar.php --git ${{ github.sha }}
|
run: php -dphar.readonly=0 build/server-phar.php --git ${{ github.sha }} --build ${{ steps.build-number.outputs.BUILD_NUMBER }}
|
||||||
|
|
||||||
- name: Get PocketMine-MP release version
|
- name: Get PocketMine-MP release version
|
||||||
id: get-pm-version
|
id: get-pm-version
|
||||||
@ -56,10 +57,10 @@ jobs:
|
|||||||
echo ::set-output name=PM_VERSION_MD::$(php -r 'require "vendor/autoload.php"; echo str_replace(".", "", \pocketmine\VersionInfo::BASE_VERSION);')
|
echo ::set-output name=PM_VERSION_MD::$(php -r 'require "vendor/autoload.php"; echo str_replace(".", "", \pocketmine\VersionInfo::BASE_VERSION);')
|
||||||
|
|
||||||
- name: Generate build info
|
- name: Generate build info
|
||||||
run: php build/generate-build-info-json.php ${{ github.sha }} ${{ steps.get-pm-version.outputs.PM_VERSION }} ${{ github.repository }} > build_info.json
|
run: php build/generate-build-info-json.php ${{ github.sha }} ${{ steps.get-pm-version.outputs.PM_VERSION }} ${{ github.repository }} ${{ steps.build-number.outputs.BUILD_NUMBER }} > build_info.json
|
||||||
|
|
||||||
- name: Upload release artifacts
|
- name: Upload release artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: release_artifacts
|
name: release_artifacts
|
||||||
path: |
|
path: |
|
||||||
@ -68,7 +69,7 @@ jobs:
|
|||||||
${{ github.workspace }}/build_info.json
|
${{ github.workspace }}/build_info.json
|
||||||
|
|
||||||
- name: Create draft release
|
- name: Create draft release
|
||||||
uses: ncipollo/release-action@v1.8.6
|
uses: ncipollo/release-action@v1.10.0
|
||||||
with:
|
with:
|
||||||
artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json
|
artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json
|
||||||
commit: ${{ github.sha }}
|
commit: ${{ github.sha }}
|
||||||
|
145
.github/workflows/main.yml
vendored
145
.github/workflows/main.yml
vendored
@ -13,20 +13,14 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
image: [ubuntu-20.04]
|
image: [ubuntu-20.04]
|
||||||
php: [8.0.9]
|
php: [8.0.18]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2 #needed for build.sh
|
- name: Build and prepare PHP cache
|
||||||
- name: Check for PHP build cache
|
uses: pmmp/setup-php-action@aa636a4fe0c1c035fd9a3f05e360eadd86e06440
|
||||||
id: php-build-cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
with:
|
||||||
path: "./bin"
|
php-version: ${{ matrix.php }}
|
||||||
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
|
install-path: "./bin"
|
||||||
|
|
||||||
- name: Compile PHP
|
|
||||||
if: steps.php-build-cache.outputs.cache-hit != 'true'
|
|
||||||
run: ./tests/gh-actions/build.sh "${{ matrix.php }}"
|
|
||||||
|
|
||||||
phpstan:
|
phpstan:
|
||||||
name: PHPStan analysis
|
name: PHPStan analysis
|
||||||
@ -37,34 +31,22 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
image: [ubuntu-20.04]
|
image: [ubuntu-20.04]
|
||||||
php: [8.0.9]
|
php: [8.0.18]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Restore PHP build cache
|
- name: Setup PHP
|
||||||
id: php-build-cache
|
uses: pmmp/setup-php-action@aa636a4fe0c1c035fd9a3f05e360eadd86e06440
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
with:
|
||||||
path: "./bin"
|
php-version: ${{ matrix.php }}
|
||||||
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
|
install-path: "./bin"
|
||||||
|
|
||||||
- name: Kill build on PHP build cache miss (should never happen)
|
|
||||||
if: steps.php-build-cache.outputs.cache-hit != 'true'
|
|
||||||
run: exit 1
|
|
||||||
|
|
||||||
- name: Install cached PHP's dependencies
|
|
||||||
if: steps.php-build-cache.outputs.cache-hit == 'true'
|
|
||||||
run: ./tests/gh-actions/install-dependencies.sh
|
|
||||||
|
|
||||||
- name: Prefix PHP to PATH
|
|
||||||
run: echo "$(pwd)/bin/php7/bin" >> $GITHUB_PATH
|
|
||||||
|
|
||||||
- name: Install Composer
|
- name: Install Composer
|
||||||
run: curl -sS https://getcomposer.org/installer | php
|
run: curl -sS https://getcomposer.org/installer | php
|
||||||
|
|
||||||
- name: Restore Composer package cache
|
- name: Restore Composer package cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/composer/files
|
~/.cache/composer/files
|
||||||
@ -87,36 +69,22 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
image: [ubuntu-20.04]
|
image: [ubuntu-20.04]
|
||||||
php: [8.0.9]
|
php: [8.0.18]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup PHP
|
||||||
|
uses: pmmp/setup-php-action@aa636a4fe0c1c035fd9a3f05e360eadd86e06440
|
||||||
with:
|
with:
|
||||||
submodules: true
|
php-version: ${{ matrix.php }}
|
||||||
|
install-path: "./bin"
|
||||||
- name: Restore PHP build cache
|
|
||||||
id: php-build-cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: "./bin"
|
|
||||||
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
|
|
||||||
|
|
||||||
- name: Kill build on PHP build cache miss (should never happen)
|
|
||||||
if: steps.php-build-cache.outputs.cache-hit != 'true'
|
|
||||||
run: exit 1
|
|
||||||
|
|
||||||
- name: Install cached PHP's dependencies
|
|
||||||
if: steps.php-build-cache.outputs.cache-hit == 'true'
|
|
||||||
run: ./tests/gh-actions/install-dependencies.sh
|
|
||||||
|
|
||||||
- name: Prefix PHP to PATH
|
|
||||||
run: echo "$(pwd)/bin/php7/bin" >> $GITHUB_PATH
|
|
||||||
|
|
||||||
- name: Install Composer
|
- name: Install Composer
|
||||||
run: curl -sS https://getcomposer.org/installer | php
|
run: curl -sS https://getcomposer.org/installer | php
|
||||||
|
|
||||||
- name: Restore Composer package cache
|
- name: Restore Composer package cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/composer/files
|
~/.cache/composer/files
|
||||||
@ -139,36 +107,24 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
image: [ubuntu-20.04]
|
image: [ubuntu-20.04]
|
||||||
php: [8.0.9]
|
php: [8.0.18]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Restore PHP build cache
|
- name: Setup PHP
|
||||||
id: php-build-cache
|
uses: pmmp/setup-php-action@aa636a4fe0c1c035fd9a3f05e360eadd86e06440
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
with:
|
||||||
path: "./bin"
|
php-version: ${{ matrix.php }}
|
||||||
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
|
install-path: "./bin"
|
||||||
|
|
||||||
- name: Kill build on PHP build cache miss (should never happen)
|
|
||||||
if: steps.php-build-cache.outputs.cache-hit != 'true'
|
|
||||||
run: exit 1
|
|
||||||
|
|
||||||
- name: Install cached PHP's dependencies
|
|
||||||
if: steps.php-build-cache.outputs.cache-hit == 'true'
|
|
||||||
run: ./tests/gh-actions/install-dependencies.sh
|
|
||||||
|
|
||||||
- name: Prefix PHP to PATH
|
|
||||||
run: echo "$(pwd)/bin/php7/bin" >> $GITHUB_PATH
|
|
||||||
|
|
||||||
- name: Install Composer
|
- name: Install Composer
|
||||||
run: curl -sS https://getcomposer.org/installer | php
|
run: curl -sS https://getcomposer.org/installer | php
|
||||||
|
|
||||||
- name: Restore Composer package cache
|
- name: Restore Composer package cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/composer/files
|
~/.cache/composer/files
|
||||||
@ -191,36 +147,22 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
image: [ubuntu-20.04]
|
image: [ubuntu-20.04]
|
||||||
php: [8.0.9]
|
php: [8.0.18]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup PHP
|
||||||
|
uses: pmmp/setup-php-action@aa636a4fe0c1c035fd9a3f05e360eadd86e06440
|
||||||
with:
|
with:
|
||||||
submodules: true
|
php-version: ${{ matrix.php }}
|
||||||
|
install-path: "./bin"
|
||||||
- name: Restore PHP build cache
|
|
||||||
id: php-build-cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: "./bin"
|
|
||||||
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
|
|
||||||
|
|
||||||
- name: Kill build on PHP build cache miss (should never happen)
|
|
||||||
if: steps.php-build-cache.outputs.cache-hit != 'true'
|
|
||||||
run: exit 1
|
|
||||||
|
|
||||||
- name: Install cached PHP's dependencies
|
|
||||||
if: steps.php-build-cache.outputs.cache-hit == 'true'
|
|
||||||
run: ./tests/gh-actions/install-dependencies.sh
|
|
||||||
|
|
||||||
- name: Prefix PHP to PATH
|
|
||||||
run: echo "$(pwd)/bin/php7/bin" >> $GITHUB_PATH
|
|
||||||
|
|
||||||
- name: Install Composer
|
- name: Install Composer
|
||||||
run: curl -sS https://getcomposer.org/installer | php
|
run: curl -sS https://getcomposer.org/installer | php
|
||||||
|
|
||||||
- name: Restore Composer package cache
|
- name: Restore Composer package cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/composer/files
|
~/.cache/composer/files
|
||||||
@ -238,11 +180,10 @@ jobs:
|
|||||||
- name: Regenerate KnownTranslation APIs
|
- name: Regenerate KnownTranslation APIs
|
||||||
run: php build/generate-known-translation-apis.php
|
run: php build/generate-known-translation-apis.php
|
||||||
|
|
||||||
- name: Run git diff
|
- name: Verify code is unchanged
|
||||||
run: git diff
|
run: |
|
||||||
|
git diff
|
||||||
- name: Fail job if changes were made
|
git diff --quiet
|
||||||
run: git diff --quiet
|
|
||||||
|
|
||||||
codestyle:
|
codestyle:
|
||||||
name: Code Style checks
|
name: Code Style checks
|
||||||
@ -251,13 +192,13 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Setup PHP and tools
|
- name: Setup PHP and tools
|
||||||
uses: shivammathur/setup-php@2.9.0
|
uses: shivammathur/setup-php@2.19.0
|
||||||
with:
|
with:
|
||||||
php-version: 8.0
|
php-version: 8.0
|
||||||
tools: php-cs-fixer
|
tools: php-cs-fixer:3.2
|
||||||
|
|
||||||
- name: Run PHP-CS-Fixer
|
- name: Run PHP-CS-Fixer
|
||||||
run: php-cs-fixer fix --dry-run --diff
|
run: php-cs-fixer fix --dry-run --diff --ansi
|
||||||
|
8
.github/workflows/support.yml
vendored
8
.github/workflows/support.yml
vendored
@ -13,7 +13,13 @@ jobs:
|
|||||||
github-token: ${{ github.token }}
|
github-token: ${{ github.token }}
|
||||||
support-label: "Support request"
|
support-label: "Support request"
|
||||||
issue-comment: >
|
issue-comment: >
|
||||||
Thanks, but this issue tracker is not intended for support requests. Please read the guidelines on [submitting an issue](https://github.com/pmmp/PocketMine-MP/blob/master/CONTRIBUTING.md#creating-an-issue).
|
Hi, we only accept **bug reports** on this issue tracker, but this issue looks like a support request.
|
||||||
|
|
||||||
|
|
||||||
|
Instead of creating a bug report, try the following:
|
||||||
|
|
||||||
|
- Check our [Documentation](https://doc.pmmp.io) to see if you can find answers there
|
||||||
|
- Ask the community on our [Discord server](https://discord.gg/bmSAZBG) or our [Forums](https://forums.pmmp.io)
|
||||||
|
|
||||||
|
|
||||||
[Docs](https://pmmp.rtfd.io) | [Discord](https://discord.gg/bmSAZBG) | [Forums](https://forums.pmmp.io)
|
[Docs](https://pmmp.rtfd.io) | [Discord](https://discord.gg/bmSAZBG) | [Forums](https://forums.pmmp.io)
|
||||||
|
2
.github/workflows/update-php-versions.php
vendored
2
.github/workflows/update-php-versions.php
vendored
@ -22,8 +22,6 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const VERSIONS = [
|
const VERSIONS = [
|
||||||
"7.3",
|
|
||||||
"7.4",
|
|
||||||
"8.0"
|
"8.0"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
2
.github/workflows/update-updater-api.yml
vendored
2
.github/workflows/update-updater-api.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
|||||||
- name: Install jq
|
- name: Install jq
|
||||||
run: sudo apt update && sudo apt install jq -y
|
run: sudo apt update && sudo apt install jq -y
|
||||||
|
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
repository: pmmp/update.pmmp.io
|
repository: pmmp/update.pmmp.io
|
||||||
ssh-key: ${{ secrets.UPDATE_PMMP_IO_DEPLOY_KEY }}
|
ssh-key: ${{ secrets.UPDATE_PMMP_IO_DEPLOY_KEY }}
|
||||||
|
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -1,12 +1,6 @@
|
|||||||
[submodule "resources/locale"]
|
|
||||||
path = resources/locale
|
|
||||||
url = https://github.com/pmmp/Language.git
|
|
||||||
[submodule "tests/plugins/DevTools"]
|
[submodule "tests/plugins/DevTools"]
|
||||||
path = tests/plugins/DevTools
|
path = tests/plugins/DevTools
|
||||||
url = https://github.com/pmmp/DevTools.git
|
url = https://github.com/pmmp/DevTools.git
|
||||||
[submodule "build/php"]
|
[submodule "build/php"]
|
||||||
path = build/php
|
path = build/php
|
||||||
url = https://github.com/pmmp/php-build-scripts.git
|
url = https://github.com/pmmp/php-build-scripts.git
|
||||||
[submodule "resources/vanilla"]
|
|
||||||
path = resources/vanilla
|
|
||||||
url = https://github.com/pmmp/BedrockData.git
|
|
||||||
|
2
.idea/fileTemplates/includes/PHP File Header.php
generated
2
.idea/fileTemplates/includes/PHP File Header.php
generated
@ -16,6 +16,6 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
@ -18,6 +18,9 @@ return (new PhpCsFixer\Config)
|
|||||||
'array_syntax' => [
|
'array_syntax' => [
|
||||||
'syntax' => 'short'
|
'syntax' => 'short'
|
||||||
],
|
],
|
||||||
|
'binary_operator_spaces' => [
|
||||||
|
'default' => 'single_space'
|
||||||
|
],
|
||||||
'blank_line_after_namespace' => true,
|
'blank_line_after_namespace' => true,
|
||||||
'blank_line_after_opening_tag' => true,
|
'blank_line_after_opening_tag' => true,
|
||||||
'blank_line_before_statement' => [
|
'blank_line_before_statement' => [
|
||||||
@ -33,12 +36,36 @@ return (new PhpCsFixer\Config)
|
|||||||
],
|
],
|
||||||
'declare_strict_types' => true,
|
'declare_strict_types' => true,
|
||||||
'elseif' => true,
|
'elseif' => true,
|
||||||
|
'fully_qualified_strict_types' => true,
|
||||||
'global_namespace_import' => [
|
'global_namespace_import' => [
|
||||||
'import_constants' => true,
|
'import_constants' => true,
|
||||||
'import_functions' => true,
|
'import_functions' => true,
|
||||||
'import_classes' => null,
|
'import_classes' => null,
|
||||||
],
|
],
|
||||||
|
'header_comment' => [
|
||||||
|
'comment_type' => 'comment',
|
||||||
|
'header' => <<<BODY
|
||||||
|
|
||||||
|
____ _ _ __ __ _ __ __ ____
|
||||||
|
| _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
| |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
| __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
|_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
@author PocketMine Team
|
||||||
|
@link http://www.pocketmine.net/
|
||||||
|
|
||||||
|
|
||||||
|
BODY,
|
||||||
|
'location' => 'after_open'
|
||||||
|
],
|
||||||
'indentation_type' => true,
|
'indentation_type' => true,
|
||||||
|
'logical_operators' => true,
|
||||||
'native_function_invocation' => [
|
'native_function_invocation' => [
|
||||||
'scope' => 'namespaced',
|
'scope' => 'namespaced',
|
||||||
'include' => ['@all'],
|
'include' => ['@all'],
|
||||||
@ -61,10 +88,20 @@ return (new PhpCsFixer\Config)
|
|||||||
],
|
],
|
||||||
'sort_algorithm' => 'alpha'
|
'sort_algorithm' => 'alpha'
|
||||||
],
|
],
|
||||||
|
'phpdoc_line_span' => [
|
||||||
|
'property' => 'single',
|
||||||
|
'method' => null,
|
||||||
|
'const' => null
|
||||||
|
],
|
||||||
'phpdoc_trim' => true,
|
'phpdoc_trim' => true,
|
||||||
'phpdoc_trim_consecutive_blank_line_separation' => true,
|
'phpdoc_trim_consecutive_blank_line_separation' => true,
|
||||||
|
'return_type_declaration' => [
|
||||||
|
'space_before' => 'one'
|
||||||
|
],
|
||||||
|
'single_blank_line_at_eof' => true,
|
||||||
'single_import_per_statement' => true,
|
'single_import_per_statement' => true,
|
||||||
'strict_param' => true,
|
'strict_param' => true,
|
||||||
|
'unary_operator_spaces' => true,
|
||||||
])
|
])
|
||||||
->setFinder($finder)
|
->setFinder($finder)
|
||||||
->setIndent("\t")
|
->setIndent("\t")
|
||||||
|
11
BUILDING.md
11
BUILDING.md
@ -2,25 +2,24 @@
|
|||||||
## Pre-requisites
|
## Pre-requisites
|
||||||
- A bash shell (git bash is sufficient for Windows)
|
- A bash shell (git bash is sufficient for Windows)
|
||||||
- [`git`](https://git-scm.com) available in your shell
|
- [`git`](https://git-scm.com) available in your shell
|
||||||
- PHP 7.4 or newer available in your shell
|
- PHP 8.0 or newer available in your shell
|
||||||
- [`composer`](https://getcomposer.org) available in your shell
|
- [`composer`](https://getcomposer.org) available in your shell
|
||||||
|
|
||||||
## Custom PHP binaries
|
## Custom PHP binaries
|
||||||
Because PocketMine-MP requires several non-standard PHP extensions and configuration, PMMP provides scripts to build custom binaries for running PocketMine-MP, as well as prebuilt binaries.
|
Because PocketMine-MP requires several non-standard PHP extensions and configuration, PMMP provides scripts to build custom binaries for running PocketMine-MP, as well as prebuilt binaries.
|
||||||
|
|
||||||
- [Prebuilt binaries](https://jenkins.pmmp.io/job/PHP-7.4-Aggregate)
|
- [Prebuilt binaries](https://jenkins.pmmp.io/job/PHP-8.0-Aggregate)
|
||||||
- [Compile scripts](https://github.com/pmmp/php-build-scripts) are provided as a submodule in the path `build/php`
|
- [Compile scripts](https://github.com/pmmp/php-build-scripts) are provided as a submodule in the path `build/php`
|
||||||
|
|
||||||
If you use a custom binary, you'll need to replace `composer` usages in this guide with `path/to/your/php path/to/your/composer.phar`.
|
If you use a custom binary, you'll need to replace `composer` usages in this guide with `path/to/your/php path/to/your/composer.phar`.
|
||||||
|
|
||||||
## Setting up environment
|
## Setting up environment
|
||||||
1. `git clone --recursive https://github.com/pmmp/PocketMine-MP.git`
|
1. `git clone https://github.com/pmmp/PocketMine-MP.git`
|
||||||
2. `composer install`
|
2. `composer install`
|
||||||
|
|
||||||
## Checking out a different branch to build
|
## Checking out a different branch to build
|
||||||
1. `git checkout <branch to checkout>`
|
1. `git checkout <branch to checkout>`
|
||||||
2. `git submodule update --init`
|
2. Re-run `composer install` to synchronize dependencies.
|
||||||
3. Re-run `composer install` to synchronize dependencies.
|
|
||||||
|
|
||||||
## Optimizing for release builds
|
## 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.
|
1. Add the flags `--no-dev --classmap-authoritative` to your `composer install` command. This will reduce build size and improve autoloading speed.
|
||||||
@ -34,7 +33,7 @@ There is a bug in PHP that might cause an error which looks like this:
|
|||||||
```
|
```
|
||||||
Fatal error: Uncaught BadMethodCallException: unable to create temporary file in PocketMine-MP/build/server-phar.php:119
|
Fatal error: Uncaught BadMethodCallException: unable to create temporary file in PocketMine-MP/build/server-phar.php:119
|
||||||
```
|
```
|
||||||
You can work around it by setting `ulimit -n` to some bigger number, e.g. `8192`, or by updating your PHP version to at least 7.4.16 or 8.0.3.
|
You can work around it by setting `ulimit -n` to some bigger number, e.g. `8192`, or by updating your PHP version to at least 8.0.3.
|
||||||
|
|
||||||
## Running PocketMine-MP from source code
|
## Running PocketMine-MP from source code
|
||||||
Run `src/PocketMine.php` using your preferred PHP binary.
|
Run `src/PocketMine.php` using your preferred PHP binary.
|
||||||
|
20
README.md
20
README.md
@ -1,13 +1,24 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://pmmp.io"><img src="http://cdn.pocketmine.net/img/PocketMine-MP-h.png"></img></a><br>
|
<a href="https://pmmp.io">
|
||||||
|
<!--[if IE]>
|
||||||
|
<img src="https://github.com/pmmp/PocketMine-MP/blob/stable/.github/readme/pocketmine.png" alt="The PocketMine-MP logo" title="PocketMine" loading="eager" />
|
||||||
|
<![endif]-->
|
||||||
|
<picture>
|
||||||
|
<source srcset="https://github.com/pmmp/PocketMine-MP/raw/stable/.github/readme/pocketmine-dark.png" media="(prefers-color-scheme: dark)">
|
||||||
|
<img src="https://github.com/pmmp/PocketMine-MP/raw/stable/.github/readme/pocketmine.png" loading="eager" />
|
||||||
|
</picture>
|
||||||
|
</a><br>
|
||||||
<b>A highly customisable, open source server software for Minecraft: Bedrock Edition written in PHP</b>
|
<b>A highly customisable, open source server software for Minecraft: Bedrock Edition written in PHP</b>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://github.com/pmmp/PocketMine-MP/workflows/CI/badge.svg" alt="CI" />
|
<a href="https://github.com/pmmp/PocketMine-MP/actions/workflows/main.yml"><img src="https://github.com/pmmp/PocketMine-MP/workflows/CI/badge.svg" alt="CI" /></a>
|
||||||
<a href="https://github.com/pmmp/PocketMine-MP/releases"><img src="https://img.shields.io/github/v/tag/pmmp/PocketMine-MP?label=release&logo=github" alt="GitHub tag (latest semver)" /></a>
|
<a href="https://github.com/pmmp/PocketMine-MP/releases/latest"><img alt="GitHub release (latest SemVer)" src="https://img.shields.io/github/v/release/pmmp/PocketMine-MP?label=release&sort=semver"></a>
|
||||||
<a href="https://hub.docker.com/r/pmmp/pocketmine-mp"><img src="https://img.shields.io/docker/v/pmmp/pocketmine-mp?logo=docker&label=image" alt="Docker image version (latest semver)" /></a>
|
<a href="https://hub.docker.com/r/pmmp/pocketmine-mp"><img src="https://img.shields.io/docker/v/pmmp/pocketmine-mp?logo=docker&label=image" alt="Docker image version (latest semver)" /></a>
|
||||||
<a href="https://discord.gg/bmSAZBG"><img src="https://img.shields.io/discord/373199722573201408?label=discord&color=7289DA&logo=discord" alt="Discord" /></a>
|
<a href="https://discord.gg/bmSAZBG"><img src="https://img.shields.io/discord/373199722573201408?label=discord&color=7289DA&logo=discord" alt="Discord" /></a>
|
||||||
|
<br>
|
||||||
|
<a href="https://github.com/pmmp/PocketMine-MP/releases"><img alt="GitHub all releases" src="https://img.shields.io/github/downloads/pmmp/PocketMine-MP/total?label=downloads%40total"></a>
|
||||||
|
<a href="https://github.com/pmmp/PocketMine-MP/releases/latest"><img alt="GitHub release (latest by SemVer)" src="https://img.shields.io/github/downloads/pmmp/PocketMine-MP/latest/total?sort=semver"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
@ -24,7 +35,8 @@
|
|||||||
## For developers
|
## For developers
|
||||||
* [Building and running from source](BUILDING.md)
|
* [Building and running from source](BUILDING.md)
|
||||||
* [Developer documentation](https://devdoc.pmmp.io) - General documentation for PocketMine-MP plugin developers
|
* [Developer documentation](https://devdoc.pmmp.io) - General documentation for PocketMine-MP plugin developers
|
||||||
* [Latest API documentation](https://jenkins.pmmp.io/job/PocketMine-MP-doc/doxygen/) - Doxygen documentation generated from development
|
* [Latest release API documentation](https://apidoc.pmmp.io) - Doxygen API documentation generated for each release
|
||||||
|
* [Latest bleeding-edge API documentation](https://apidoc-dev.pmmp.io) - Doxygen API documentation generated weekly from `next-major` branch
|
||||||
* [DevTools](https://github.com/pmmp/DevTools/) - Development tools plugin for creating plugins
|
* [DevTools](https://github.com/pmmp/DevTools/) - Development tools plugin for creating plugins
|
||||||
* [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
|
* [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
|
||||||
* [Contributing Guidelines](CONTRIBUTING.md)
|
* [Contributing Guidelines](CONTRIBUTING.md)
|
||||||
|
@ -17,21 +17,21 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
if(count($argv) !== 4){
|
if(count($argv) !== 5){
|
||||||
fwrite(STDERR, "required args: <git hash> <tag name> <github repo (owner/name)>");
|
fwrite(STDERR, "required args: <git hash> <tag name> <github repo (owner/name)> <build number>");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
"php_version" => sprintf("%d.%d", PHP_MAJOR_VERSION, PHP_MINOR_VERSION),
|
"php_version" => sprintf("%d.%d", PHP_MAJOR_VERSION, PHP_MINOR_VERSION),
|
||||||
"base_version" => \pocketmine\VersionInfo::BASE_VERSION,
|
"base_version" => \pocketmine\VersionInfo::BASE_VERSION,
|
||||||
"build" => \pocketmine\VersionInfo::BUILD_NUMBER,
|
"build" => (int) $argv[4],
|
||||||
"is_dev" => \pocketmine\VersionInfo::IS_DEVELOPMENT_BUILD,
|
"is_dev" => \pocketmine\VersionInfo::IS_DEVELOPMENT_BUILD,
|
||||||
"channel" => \pocketmine\VersionInfo::BUILD_CHANNEL,
|
"channel" => \pocketmine\VersionInfo::BUILD_CHANNEL,
|
||||||
"git_commit" => $argv[1],
|
"git_commit" => $argv[1],
|
||||||
@ -40,4 +40,4 @@ echo json_encode([
|
|||||||
"details_url" => "https://github.com/$argv[3]/releases/tag/$argv[2]",
|
"details_url" => "https://github.com/$argv[3]/releases/tag/$argv[2]",
|
||||||
"download_url" => "https://github.com/$argv[3]/releases/download/$argv[2]/PocketMine-MP.phar",
|
"download_url" => "https://github.com/$argv[3]/releases/download/$argv[2]/PocketMine-MP.phar",
|
||||||
"source_url" => "https://github.com/$argv[3]/tree/$argv[2]",
|
"source_url" => "https://github.com/$argv[3]/tree/$argv[2]",
|
||||||
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n";
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR) . "\n";
|
||||||
|
@ -17,13 +17,14 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\build\generate_known_translation_apis;
|
namespace pocketmine\build\generate_known_translation_apis;
|
||||||
|
|
||||||
use pocketmine\lang\Translatable;
|
use pocketmine\lang\Translatable;
|
||||||
|
use pocketmine\utils\Utils;
|
||||||
use Webmozart\PathUtil\Path;
|
use Webmozart\PathUtil\Path;
|
||||||
use function array_map;
|
use function array_map;
|
||||||
use function count;
|
use function count;
|
||||||
@ -40,6 +41,7 @@ use function preg_match_all;
|
|||||||
use function str_replace;
|
use function str_replace;
|
||||||
use function strtoupper;
|
use function strtoupper;
|
||||||
use const INI_SCANNER_RAW;
|
use const INI_SCANNER_RAW;
|
||||||
|
use const SORT_NUMERIC;
|
||||||
use const SORT_STRING;
|
use const SORT_STRING;
|
||||||
use const STDERR;
|
use const STDERR;
|
||||||
|
|
||||||
@ -73,7 +75,7 @@ const SHARED_HEADER = <<<'HEADER'
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -94,13 +96,15 @@ function generate_known_translation_keys(array $languageDefinitions) : void{
|
|||||||
/**
|
/**
|
||||||
* This class contains constants for all the translations known to PocketMine-MP as per the used version of pmmp/Language.
|
* This class contains constants for all the translations known to PocketMine-MP as per the used version of pmmp/Language.
|
||||||
* This class is generated automatically, do NOT modify it by hand.
|
* This class is generated automatically, do NOT modify it by hand.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
final class KnownTranslationKeys{
|
final class KnownTranslationKeys{
|
||||||
|
|
||||||
HEADER;
|
HEADER;
|
||||||
|
|
||||||
ksort($languageDefinitions, SORT_STRING);
|
ksort($languageDefinitions, SORT_STRING);
|
||||||
foreach($languageDefinitions as $k => $_){
|
foreach(Utils::stringifyKeys($languageDefinitions) as $k => $_){
|
||||||
echo "\tpublic const ";
|
echo "\tpublic const ";
|
||||||
echo constantify($k);
|
echo constantify($k);
|
||||||
echo " = \"" . $k . "\";\n";
|
echo " = \"" . $k . "\";\n";
|
||||||
@ -126,6 +130,8 @@ function generate_known_translation_factory(array $languageDefinitions) : void{
|
|||||||
* This class contains factory methods for all the translations known to PocketMine-MP as per the used version of
|
* This class contains factory methods for all the translations known to PocketMine-MP as per the used version of
|
||||||
* pmmp/Language.
|
* pmmp/Language.
|
||||||
* This class is generated automatically, do NOT modify it by hand.
|
* This class is generated automatically, do NOT modify it by hand.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
final class KnownTranslationFactory{
|
final class KnownTranslationFactory{
|
||||||
|
|
||||||
@ -135,17 +141,22 @@ HEADER;
|
|||||||
$parameterRegex = '/{%(.+?)}/';
|
$parameterRegex = '/{%(.+?)}/';
|
||||||
|
|
||||||
$translationContainerClass = (new \ReflectionClass(Translatable::class))->getShortName();
|
$translationContainerClass = (new \ReflectionClass(Translatable::class))->getShortName();
|
||||||
foreach($languageDefinitions as $key => $value){
|
foreach(Utils::stringifyKeys($languageDefinitions) as $key => $value){
|
||||||
$parameters = [];
|
$parameters = [];
|
||||||
|
$allParametersPositional = true;
|
||||||
if(preg_match_all($parameterRegex, $value, $matches) > 0){
|
if(preg_match_all($parameterRegex, $value, $matches) > 0){
|
||||||
foreach($matches[1] as $parameterName){
|
foreach($matches[1] as $parameterName){
|
||||||
if(is_numeric($parameterName)){
|
if(is_numeric($parameterName)){
|
||||||
$parameters[$parameterName] = "param$parameterName";
|
$parameters[$parameterName] = "param$parameterName";
|
||||||
}else{
|
}else{
|
||||||
$parameters[$parameterName] = $parameterName;
|
$parameters[$parameterName] = $parameterName;
|
||||||
|
$allParametersPositional = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if($allParametersPositional){
|
||||||
|
ksort($parameters, SORT_NUMERIC);
|
||||||
|
}
|
||||||
echo "\tpublic static function " .
|
echo "\tpublic static function " .
|
||||||
functionify($key) .
|
functionify($key) .
|
||||||
"(" . implode(", ", array_map(fn(string $paramName) => "$translationContainerClass|string \$$paramName", $parameters)) . ") : $translationContainerClass{\n";
|
"(" . implode(", ", array_map(fn(string $paramName) => "$translationContainerClass|string \$$paramName", $parameters)) . ") : $translationContainerClass{\n";
|
||||||
@ -172,7 +183,7 @@ HEADER;
|
|||||||
echo "Done generating KnownTranslationFactory.\n";
|
echo "Done generating KnownTranslationFactory.\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
$lang = parse_ini_file(Path::join(\pocketmine\RESOURCE_PATH, "locale", "eng.ini"), false, INI_SCANNER_RAW);
|
$lang = parse_ini_file(Path::join(\pocketmine\LOCALE_DATA_PATH, "eng.ini"), false, INI_SCANNER_RAW);
|
||||||
if($lang === false){
|
if($lang === false){
|
||||||
fwrite(STDERR, "Missing language files!\n");
|
fwrite(STDERR, "Missing language files!\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ function generateMethodAnnotations(string $namespaceName, array $members) : stri
|
|||||||
$memberLines = [];
|
$memberLines = [];
|
||||||
foreach($members as $name => $member){
|
foreach($members as $name => $member){
|
||||||
$reflect = new \ReflectionClass($member);
|
$reflect = new \ReflectionClass($member);
|
||||||
while($reflect !== false and $reflect->isAnonymous()){
|
while($reflect !== false && $reflect->isAnonymous()){
|
||||||
$reflect = $reflect->getParentClass();
|
$reflect = $reflect->getParentClass();
|
||||||
}
|
}
|
||||||
if($reflect === false){
|
if($reflect === false){
|
||||||
@ -82,6 +82,7 @@ function generateMethodAnnotations(string $namespaceName, array $members) : stri
|
|||||||
|
|
||||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
|
/** @var string $file */
|
||||||
foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($argv[1], \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::CURRENT_AS_PATHNAME)) as $file){
|
foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($argv[1], \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::CURRENT_AS_PATHNAME)) as $file){
|
||||||
if(substr($file, -4) !== ".php"){
|
if(substr($file, -4) !== ".php"){
|
||||||
continue;
|
continue;
|
||||||
@ -91,7 +92,7 @@ foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($argv[1],
|
|||||||
throw new \RuntimeException("Failed to get contents of $file");
|
throw new \RuntimeException("Failed to get contents of $file");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(preg_match("/^namespace (.+);$/m", $contents, $matches) !== 1 || preg_match('/^((final|abstract)\s+)?class /m', $contents) !== 1){
|
if(preg_match("/(*ANYCRLF)^namespace (.+);$/m", $contents, $matches) !== 1 || preg_match('/(*ANYCRLF)^((final|abstract)\s+)?class /m', $contents) !== 1){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$shortClassName = basename($file, ".php");
|
$shortClassName = basename($file, ".php");
|
||||||
@ -101,7 +102,7 @@ foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($argv[1],
|
|||||||
}
|
}
|
||||||
$reflect = new \ReflectionClass($className);
|
$reflect = new \ReflectionClass($className);
|
||||||
$docComment = $reflect->getDocComment();
|
$docComment = $reflect->getDocComment();
|
||||||
if($docComment === false || preg_match("/^\s*\*\s*@generate-registry-docblock$/m", $docComment) !== 1){
|
if($docComment === false || preg_match("/(*ANYCRLF)^\s*\*\s*@generate-registry-docblock$/m", $docComment) !== 1){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
echo "Found registry in $file\n";
|
echo "Found registry in $file\n";
|
||||||
@ -116,4 +117,3 @@ foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($argv[1],
|
|||||||
echo "No changes made to file $file\n";
|
echo "No changes made to file $file\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,31 +17,40 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\build\make_release;
|
namespace pocketmine\build\make_release;
|
||||||
|
|
||||||
|
use pocketmine\utils\Utils;
|
||||||
use pocketmine\utils\VersionString;
|
use pocketmine\utils\VersionString;
|
||||||
use pocketmine\VersionInfo;
|
use pocketmine\VersionInfo;
|
||||||
use function count;
|
use function array_keys;
|
||||||
|
use function array_map;
|
||||||
use function dirname;
|
use function dirname;
|
||||||
use function fgets;
|
use function fgets;
|
||||||
use function file_get_contents;
|
use function file_get_contents;
|
||||||
use function file_put_contents;
|
use function file_put_contents;
|
||||||
use function fwrite;
|
use function fwrite;
|
||||||
|
use function getopt;
|
||||||
|
use function is_string;
|
||||||
|
use function max;
|
||||||
use function preg_replace;
|
use function preg_replace;
|
||||||
use function sleep;
|
use function sleep;
|
||||||
use function sprintf;
|
use function sprintf;
|
||||||
|
use function str_pad;
|
||||||
|
use function strlen;
|
||||||
use function system;
|
use function system;
|
||||||
use const STDERR;
|
use const STDERR;
|
||||||
use const STDIN;
|
use const STDIN;
|
||||||
|
use const STDOUT;
|
||||||
|
use const STR_PAD_LEFT;
|
||||||
|
|
||||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev, string $channel) : void{
|
function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev, string $channel) : void{
|
||||||
$versionInfo = file_get_contents($versionInfoPath);
|
$versionInfo = Utils::assumeNotFalse(file_get_contents($versionInfoPath), $versionInfoPath . " should always exist");
|
||||||
$versionInfo = preg_replace(
|
$versionInfo = preg_replace(
|
||||||
$pattern = '/^([\t ]*public )?const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m',
|
$pattern = '/^([\t ]*public )?const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m',
|
||||||
'$1const BASE_VERSION = "' . $newVersion . '";',
|
'$1const BASE_VERSION = "' . $newVersion . '";',
|
||||||
@ -60,22 +69,46 @@ function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev
|
|||||||
file_put_contents($versionInfoPath, $versionInfo);
|
file_put_contents($versionInfoPath, $versionInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
const ACCEPTED_OPTS = [
|
||||||
* @param string[] $argv
|
"current" => "Version to insert and tag",
|
||||||
* @phpstan-param list<string> $argv
|
"next" => "Version to put in the file after tagging",
|
||||||
*/
|
"channel" => "Release channel to post this build into"
|
||||||
function main(array $argv) : void{
|
];
|
||||||
if(count($argv) < 2){
|
|
||||||
fwrite(STDERR, "Arguments: <channel> [release version] [next version]\n");
|
function systemWrapper(string $command, string $errorMessage) : void{
|
||||||
|
system($command, $result);
|
||||||
|
if($result !== 0){
|
||||||
|
echo "error: $errorMessage; aborting\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if(isset($argv[2])){
|
}
|
||||||
$currentVer = new VersionString($argv[2]);
|
|
||||||
}else{
|
function main() : void{
|
||||||
$currentVer = VersionInfo::VERSION();
|
$filteredOpts = [];
|
||||||
|
foreach(Utils::stringifyKeys(getopt("", ["current:", "next:", "channel:", "help"])) as $optName => $optValue){
|
||||||
|
if($optName === "help"){
|
||||||
|
fwrite(STDOUT, "Options:\n");
|
||||||
|
|
||||||
|
$maxLength = max(array_map(fn(string $str) => strlen($str), array_keys(ACCEPTED_OPTS)));
|
||||||
|
foreach(ACCEPTED_OPTS as $acceptedName => $description){
|
||||||
|
fwrite(STDOUT, str_pad("--$acceptedName", $maxLength + 4, " ", STR_PAD_LEFT) . ": $description\n");
|
||||||
}
|
}
|
||||||
if(isset($argv[3])){
|
exit(0);
|
||||||
$nextVer = new VersionString($argv[3]);
|
}
|
||||||
|
if(!is_string($optValue)){
|
||||||
|
fwrite(STDERR, "--$optName expects exactly 1 value\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
$filteredOpts[$optName] = $optValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset($filteredOpts["current"])){
|
||||||
|
$currentVer = new VersionString($filteredOpts["current"]);
|
||||||
|
}else{
|
||||||
|
$currentVer = new VersionString(VersionInfo::BASE_VERSION);
|
||||||
|
}
|
||||||
|
if(isset($filteredOpts["next"])){
|
||||||
|
$nextVer = new VersionString($filteredOpts["next"]);
|
||||||
}else{
|
}else{
|
||||||
$nextVer = new VersionString(sprintf(
|
$nextVer = new VersionString(sprintf(
|
||||||
"%u.%u.%u",
|
"%u.%u.%u",
|
||||||
@ -84,26 +117,29 @@ function main(array $argv) : void{
|
|||||||
$currentVer->getPatch() + 1
|
$currentVer->getPatch() + 1
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
$channel = $filteredOpts["channel"] ?? VersionInfo::BUILD_CHANNEL;
|
||||||
|
|
||||||
echo "About to tag version $currentVer. Next version will be $nextVer.\n";
|
echo "About to tag version $currentVer. Next version will be $nextVer.\n";
|
||||||
|
echo "$currentVer will be published on release channel \"$channel\".\n";
|
||||||
echo "please add appropriate notes to the changelog and press enter...";
|
echo "please add appropriate notes to the changelog and press enter...";
|
||||||
fgets(STDIN);
|
fgets(STDIN);
|
||||||
system('git add "' . dirname(__DIR__) . '/changelogs"');
|
systemWrapper('git add "' . dirname(__DIR__) . '/changelogs"', "failed to stage changelog changes");
|
||||||
system('git diff --cached --quiet "' . dirname(__DIR__) . '/changelogs"', $result);
|
system('git diff --cached --quiet "' . dirname(__DIR__) . '/changelogs"', $result);
|
||||||
if($result === 0){
|
if($result === 0){
|
||||||
echo "error: no changelog changes detected; aborting\n";
|
echo "error: no changelog changes detected; aborting\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
$versionInfoPath = dirname(__DIR__) . '/src/VersionInfo.php';
|
$versionInfoPath = dirname(__DIR__) . '/src/VersionInfo.php';
|
||||||
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false, $argv[1]);
|
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false, $channel);
|
||||||
system('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"');
|
systemWrapper('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"', "failed to create release commit");
|
||||||
system('git tag ' . $currentVer->getBaseVersion());
|
systemWrapper('git tag ' . $currentVer->getBaseVersion(), "failed to create release tag");
|
||||||
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true, "");
|
|
||||||
system('git add "' . $versionInfoPath . '"');
|
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true, $channel);
|
||||||
system('git commit -m "' . $nextVer->getBaseVersion() . ' is next" --include "' . $versionInfoPath . '"');
|
systemWrapper('git add "' . $versionInfoPath . '"', "failed to stage changes for post-release commit");
|
||||||
|
systemWrapper('git commit -m "' . $nextVer->getBaseVersion() . ' is next" --include "' . $versionInfoPath . '"', "failed to create post-release commit");
|
||||||
echo "pushing changes in 5 seconds\n";
|
echo "pushing changes in 5 seconds\n";
|
||||||
sleep(5);
|
sleep(5);
|
||||||
system('git push origin HEAD ' . $currentVer->getBaseVersion());
|
systemWrapper('git push origin HEAD ' . $currentVer->getBaseVersion(), "failed to push changes to remote");
|
||||||
}
|
}
|
||||||
|
|
||||||
main($argv);
|
main();
|
||||||
|
Submodule build/php updated: ad9cd1fdb4...11103498ca
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -134,13 +134,18 @@ function main() : void{
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$opts = getopt("", ["out:", "git:"]);
|
$opts = getopt("", ["out:", "git:", "build:"]);
|
||||||
if(isset($opts["git"])){
|
if(isset($opts["git"])){
|
||||||
$gitHash = $opts["git"];
|
$gitHash = $opts["git"];
|
||||||
}else{
|
}else{
|
||||||
$gitHash = Git::getRepositoryStatePretty(dirname(__DIR__));
|
$gitHash = Git::getRepositoryStatePretty(dirname(__DIR__));
|
||||||
echo "Git hash detected as $gitHash" . PHP_EOL;
|
echo "Git hash detected as $gitHash" . PHP_EOL;
|
||||||
}
|
}
|
||||||
|
if(isset($opts["build"])){
|
||||||
|
$build = (int) $opts["build"];
|
||||||
|
}else{
|
||||||
|
$build = 0;
|
||||||
|
}
|
||||||
foreach(buildPhar(
|
foreach(buildPhar(
|
||||||
$opts["out"] ?? getcwd() . DIRECTORY_SEPARATOR . "PocketMine-MP.phar",
|
$opts["out"] ?? getcwd() . DIRECTORY_SEPARATOR . "PocketMine-MP.phar",
|
||||||
dirname(__DIR__) . DIRECTORY_SEPARATOR,
|
dirname(__DIR__) . DIRECTORY_SEPARATOR,
|
||||||
@ -150,7 +155,8 @@ function main() : void{
|
|||||||
'vendor'
|
'vendor'
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'git' => $gitHash
|
'git' => $gitHash,
|
||||||
|
'build' => $build
|
||||||
],
|
],
|
||||||
<<<'STUB'
|
<<<'STUB'
|
||||||
<?php
|
<?php
|
||||||
|
14
changelogs/3.23.md
Normal file
14
changelogs/3.23.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.17.30**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 3.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 3.23.0
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.17.30.
|
||||||
|
- Removed compatibility with earlier versions.
|
||||||
|
|
||||||
|
# 3.23.1
|
||||||
|
- Fixed broken build of 3.23.0.
|
12
changelogs/3.24.md
Normal file
12
changelogs/3.24.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.17.30**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 3.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 3.24.0
|
||||||
|
- PHP 8.0 is now required as a minimum.
|
||||||
|
- Fixed stats reporting checking the wrong `pocketmine.yml` property.
|
||||||
|
- Fixed `Projectile->move()` not respecting the given `dx`/`dy`/`dz` and using its own motion instead.
|
38
changelogs/3.25.md
Normal file
38
changelogs/3.25.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.17.40**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 3.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 3.25.0
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.17.40.
|
||||||
|
- Removed compatibility with earlier versions.
|
||||||
|
|
||||||
|
# 3.25.1
|
||||||
|
- Fixed autosave bug that caused unmodified chunks to be saved at least once (during the first autosave after they were loaded).
|
||||||
|
- `Entity->spawnTo()` now has an additional sanity check for matching worlds (might expose a few new errors in plugins).
|
||||||
|
- Fixed a missing field in `CraftRecipeAuto` item stack request type.
|
||||||
|
|
||||||
|
# 3.25.2
|
||||||
|
- Now analysed using level 9 on PHPStan 1.0.0.
|
||||||
|
- `ext-pthreads` v4.0.0 or newer is now required.
|
||||||
|
- Fixed crash in `Player->showPlayer()` when the target is not in the same world.
|
||||||
|
- `Human->setLifetimeTotalXp()` now limits the maximum value to 2^31.
|
||||||
|
- Fixed players, who died in hardcore mode and were unbanned, getting re-banned on next server join.
|
||||||
|
|
||||||
|
# 3.25.3
|
||||||
|
- Fixed crash when players try to pickup XP while already having max XP.
|
||||||
|
- Added a sanity check to `Human->setCurrentTotalXp()` to try and catch an elusive bug that's been appearing in the wild - please get in touch if you know how to reproduce it!
|
||||||
|
|
||||||
|
# 3.25.4
|
||||||
|
- Fixed a long-standing issue with `Player->removeWindow()` breaking inventory UIs on the client.
|
||||||
|
|
||||||
|
# 3.25.5
|
||||||
|
- Protocol: Fixed incorrect encoding in `StructureSettings`
|
||||||
|
- Fixed reading tags from non-docblock comments in script plugins.
|
||||||
|
- Build number is now defined in phar metadata instead of being patched into the source code directly.
|
||||||
|
|
||||||
|
# 3.25.6
|
||||||
|
- Fixed borked build number in release build of 3.25.5.
|
32
changelogs/3.26.md
Normal file
32
changelogs/3.26.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.18.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.26.0
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.18.0.
|
||||||
|
- Removed compatibility with earlier versions.
|
||||||
|
|
||||||
|
# 3.26.1
|
||||||
|
- Fixed a bug in chunk sending that caused double chests to not be paired, signs to be blank, and various other issues.
|
||||||
|
|
||||||
|
# 3.26.2
|
||||||
|
- Improved error messages shown by `start.cmd`, `start.sh` and `start.ps1` when the PHP binary was not found.
|
||||||
|
- The value of PHPRC is now shown when erroring out due to unsatisfied PHP requirements.
|
||||||
|
- Removed restriction on the range of valid channels for `auto-updater.channel` in `pocketmine.yml`.
|
||||||
|
|
||||||
|
# 3.26.3
|
||||||
|
- `PlayerExperienceChangeEvent->setNewProgress()` now performs range checks. This fixes the root of a very old and confusing crash bug which took several years to identify the cause of.
|
||||||
|
- Note that the defective plugin(s) which caused this problem will still cause a server crash, but the plugin responsible will now get blamed correctly.
|
||||||
|
|
||||||
|
# 3.26.4
|
||||||
|
- Fixed skins appearing black when using RTX resource packs.
|
||||||
|
- Fixed chunks containing furnaces in old worlds (pre-2017) being discarded as corrupted.
|
||||||
|
- This was caused by a strict corruption check detecting bad data created by a bug in PocketMine-MP that was fixed in 2017.
|
||||||
|
|
||||||
|
# 3.26.5
|
||||||
|
- Fixed several denial-of-service attack vectors related to writable book text length and encoding.
|
||||||
|
- Fixed several denial-of-service attack vectors related to skin data field lengths.
|
15
changelogs/3.27.md
Normal file
15
changelogs/3.27.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.18.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.27.0
|
||||||
|
- Introduced support for protocol encryption.
|
||||||
|
- Encryption is enabled by default.
|
||||||
|
- Fixes login replay attacks.
|
||||||
|
- This may cause some performance degradation.
|
||||||
|
- Encryption can be disabled by setting `network.enable-encryption` to `false` in `pocketmine.yml`. DO NOT do this unless you understand the risks involved.
|
||||||
|
- An obsoletion notice has been added to the console during server startup.
|
1767
changelogs/4.0-beta.md
Normal file
1767
changelogs/4.0-beta.md
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
166
changelogs/4.1-beta.md
Normal file
166
changelogs/4.1-beta.md
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.18.0**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.1.0-BETA1
|
||||||
|
Released 22nd January 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Game mode names (e.g. `survival`, `creative`) may now be used for the `gamemode` property in `server.properties`.
|
||||||
|
- Increased default maximum render distance to 16 chunks. Players with a render distance smaller than this will notice no difference.
|
||||||
|
- The setup wizard now prompts for a maximum render distance value.
|
||||||
|
- The setup wizard now prompts for an IPv6 port selection. Previously it would always use 19133.
|
||||||
|
- `chunk-ticking.disable-block-ticking` now accepts block names like those used in the `/give` command.
|
||||||
|
- The `/clear` command now behaves more like vanilla:
|
||||||
|
- The order of inventories is now the same as Bedrock.
|
||||||
|
- The cursor and offhand inventories are now cleared if necessary.
|
||||||
|
|
||||||
|
## Technical
|
||||||
|
- `PlayerAuthInputPacket` is now used instead of `MovePlayerPacket` for processing movements. This improves position and rotation accuracy.
|
||||||
|
- `&&` and `||` are now always used instead of `and` and `or`.
|
||||||
|
- New version of `pocketmine/errorhandler` is used by this version, adding support for `ErrorToExceptionHandler::trap()`. This enables reliably capturing `E_WARNING` and `E_NOTICE` from functions such as `yaml_parse()` and friends.
|
||||||
|
- New dependency versions are required by this version:
|
||||||
|
- `pocketmine/bedrock-protocol` has been updated from 7.1.0 to [7.3.0](https://github.com/pmmp/BedrockProtocol/releases/tag/7.3.0%2Bbedrock-1.18.0).
|
||||||
|
- `pocketmine/errorhandler` has been updated from 0.3.0 to [0.6.0](https://github.com/pmmp/ErrorHandler/releases/tag/0.6.0).
|
||||||
|
|
||||||
|
## API
|
||||||
|
### Block
|
||||||
|
- The following classes have been added:
|
||||||
|
- `Lectern`
|
||||||
|
- `Pumpkin`
|
||||||
|
- The following public API methods have been added:
|
||||||
|
- `Block->getTypeId() : int` - returns an integer which uniquely identifies the block type, ignoring things like facing, colour etc.
|
||||||
|
- `VanillaBlocks::LECTERN()`
|
||||||
|
|
||||||
|
### Entity
|
||||||
|
- The following classes have been added:
|
||||||
|
- `animation\ItemEntityStackSizeChangeAnimation`
|
||||||
|
- The following public API methods have been added:
|
||||||
|
- `object\ItemEntity->isMergeable(object\ItemEntity $other) : bool`
|
||||||
|
- `object\ItemEntity->setStackSize(int $size) : void`
|
||||||
|
- `object\ItemEntity->tryMergeInto(object\ItemEntity $other) : bool`
|
||||||
|
- `ExperienceManager->canAttractXpOrbs() : bool`
|
||||||
|
- `ExperienceManager->setCanAttractXpOrbs(bool $v = true) : void`
|
||||||
|
- `Entity->getSize() : EntitySizeInfo`
|
||||||
|
- `Living->isGliding() : bool`
|
||||||
|
- `Living->isSwimming() : bool`
|
||||||
|
- `Living->setGliding(bool $value = true) : void`
|
||||||
|
- `Living->setSwimming(bool $value = true) : void`
|
||||||
|
- The following protected API methods have been added:
|
||||||
|
- `Entity->getBlocksIntersected(float $inset) : \Generator<int, Block, void, void>`
|
||||||
|
|
||||||
|
### Event
|
||||||
|
- `BlockSpreadEvent` is now called when fire spreads to the positions of blocks it burns away.
|
||||||
|
- `BlockFormEvent` is now called when concrete powder turns into concrete due to contact with water.
|
||||||
|
- The following classes have been added:
|
||||||
|
- `BlockMeltEvent` - called when ice or snow melts
|
||||||
|
- `ChestPairEvent` - called when two chests try to form a pair
|
||||||
|
- `PlayerToggleGlideEvent` - called when a player starts or stops gliding
|
||||||
|
- `PlayerToggleSwimEvent` - called when a player starts or stops swimming
|
||||||
|
|
||||||
|
### Item
|
||||||
|
- The following public API methods have been added:
|
||||||
|
- `SplashPotion->getType() : PotionType`
|
||||||
|
- `VanillaItems::AIR()`
|
||||||
|
- The following API methods have been deprecated:
|
||||||
|
- `ItemFactory::air()` - use `VanillaItems::AIR()` instead
|
||||||
|
|
||||||
|
### Player
|
||||||
|
- The following public API methods have been added:
|
||||||
|
- `Player->hasBlockCollision() : bool`
|
||||||
|
- `Player->setHasBlockCollision(bool $value)` - allows controlling spectator-like no-clip behaviour without changing game mode
|
||||||
|
- `Player->toggleSwim(bool $swim) : bool` - called by the network system when the client tries to start/stop swimming
|
||||||
|
- `Player->toggleGlide(bool $glide) : bool` - called by the network system when the client tries to start/stop gliding
|
||||||
|
|
||||||
|
### Server
|
||||||
|
- The following public API constants have been added:
|
||||||
|
- `Server::DEFAULT_SERVER_NAME`
|
||||||
|
- `Server::DEFAULT_MAX_PLAYERS`
|
||||||
|
- `Server::DEFAULT_PORT_IPV4`
|
||||||
|
- `Server::DEFAULT_PORT_IPV6`
|
||||||
|
- `Server::DEFAULT_MAX_VIEW_DISTANCE`
|
||||||
|
|
||||||
|
### Utils
|
||||||
|
- Config parsing errors are now always represented by `ConfigLoadException` and include the path to the file in the message.
|
||||||
|
- Added `TextFormat::MINECOIN_GOLD`, and support for it to the various `TextFormat` methods.
|
||||||
|
- The following public API methods have been added:
|
||||||
|
- `Utils::assumeNotFalse()` - static analysis crutch to silence PHPStan errors without using `ignoreErrors` or `@phpstan-ignore-line`, which are both too coarse.
|
||||||
|
- The following public API properties have been added:
|
||||||
|
- `Terminal::$COLOR_MINECOIN_GOLD`
|
||||||
|
- The following classes have been added:
|
||||||
|
- `ConfigLoadException`
|
||||||
|
- Fixed `Random->nextSignedInt()` to actually return a signed int. Previously it would return any integer value between 0 and 4,294,957,295.
|
||||||
|
- Fixed `Random->nextSignedFloat()` to return a float between `-1.0` and `1.0`. Previously it would return any value between `0.0` and `2.0`.
|
||||||
|
- `VersionString->getNumber()` output is now structured differently to fix overflow issues caused by the old format.
|
||||||
|
|
||||||
|
### World
|
||||||
|
- The following classes have been added:
|
||||||
|
- `sound\ItemUseOnBlockSound`
|
||||||
|
- `sound\LecternPlaceBookSound`
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
### Blocks
|
||||||
|
- Fire now spreads.
|
||||||
|
- Implemented lectern blocks.
|
||||||
|
- Added missing sounds for hoeing grass and dirt.
|
||||||
|
- Added missing sounds for using a shovel on grass to create grass path.
|
||||||
|
- Pumpkins can now be carved using shears.
|
||||||
|
|
||||||
|
### Items
|
||||||
|
- Dropped items of the same type now merge with each other.
|
||||||
|
|
||||||
|
### Misc
|
||||||
|
- Implemented player swimming.
|
||||||
|
|
||||||
|
# 4.1.0-BETA2
|
||||||
|
Released 27th January 2022.
|
||||||
|
|
||||||
|
## API
|
||||||
|
### Block
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `utils\BrewingStandSlot->getSlotNumber() : int`
|
||||||
|
- `utils\FurnaceType->getCookSound() : Sound`
|
||||||
|
- The following API constants have been added:
|
||||||
|
- `tile\BrewingStand::BREW_TIME_TICKS`
|
||||||
|
|
||||||
|
### Crafting
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `CraftingManager->getPotionContainerChangeRecipes() : array<int, array<string, PotionContainerChangeRecipe>>`
|
||||||
|
- `CraftingManager->getPotionTypeRecipes() : array<string, array<string, PotionTypeRecipe>>`
|
||||||
|
- `CraftingManager->registerPotionContainerChangeRecipe(PotionContainerChangeRecipe $recipe) : void`
|
||||||
|
- `CraftingManager->registerPotionTypeRecipe(PotionTypeRecipe $recipe) : void`
|
||||||
|
- The following classes have been added:
|
||||||
|
- `BrewingRecipe`
|
||||||
|
- `PotionContainerChangeRecipe`
|
||||||
|
- `PotionTypeRecipe`
|
||||||
|
|
||||||
|
### Event
|
||||||
|
- The following classes have been added:
|
||||||
|
- `BrewItemEvent` - called when a brewing stand finishes brewing potions; this is called up to 3 times (once for each brewing slot, as needed)
|
||||||
|
- `BrewingFuelUseEvent` - called when a brewing stand consumes blaze powder
|
||||||
|
- `PlayerViewDistanceChangeEvent` - called whenever a player alters their render distance or requests one for the first time when connecting
|
||||||
|
|
||||||
|
### World
|
||||||
|
#### Sound
|
||||||
|
- The following classes have been added:
|
||||||
|
- `BlastFurnaceSound` - the sound made by a blast furnace during smelting
|
||||||
|
- `FurnaceSound` - the sound made by a regular furnace during cooking or smelting
|
||||||
|
- `PotionFinishBrewingSound` - the sound made by a brewing stand when a potion finishes being brewed
|
||||||
|
- `SmokerSound` - the sound made by a smoker during cooking
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
### Blocks
|
||||||
|
- Brewing stands can now be used for brewing potions.
|
||||||
|
- The visual appearance of a brewing stand now updates correctly when the contents of its inventory changes (adding/removing potions).
|
||||||
|
- Added missing sounds for furnace, blast furnace and smoker.
|
||||||
|
- Fixed ender chest not dropping itself when mined with a Silk Touch pickaxe.
|
||||||
|
- Cobwebs now drop themselves when mined using shears.
|
||||||
|
- The correct amount of fall damage is now taken when falling from a height onto hay bales.
|
||||||
|
- Fixed block updating bug introduced by beta1 which caused crops and other plants to never grow.
|
||||||
|
|
||||||
|
### Misc
|
||||||
|
- Added a workaround for client hitbox size bug after swimming which caused the player to be able to fit into one-block-tall gaps.
|
142
changelogs/4.1.md
Normal file
142
changelogs/4.1.md
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.18.0**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.1.0
|
||||||
|
Released 7th February 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Game mode names (e.g. `survival`, `creative`) may now be used for the `gamemode` property in `server.properties`.
|
||||||
|
- Increased default maximum render distance to 16 chunks. Players with a render distance smaller than this will notice no difference.
|
||||||
|
- The setup wizard now prompts for a maximum render distance value.
|
||||||
|
- The setup wizard now prompts for an IPv6 port selection. Previously it would always use 19133.
|
||||||
|
- `chunk-ticking.disable-block-ticking` now accepts block names like those used in the `/give` command.
|
||||||
|
- The `/clear` command now behaves more like vanilla:
|
||||||
|
- The order of inventories is now the same as Bedrock.
|
||||||
|
- The cursor and offhand inventories are now cleared if necessary.
|
||||||
|
|
||||||
|
## Technical
|
||||||
|
- `PlayerAuthInputPacket` is now used instead of `MovePlayerPacket` for processing movements. This improves position and rotation accuracy.
|
||||||
|
- `&&` and `||` are now always used instead of `and` and `or`.
|
||||||
|
- New version of `pocketmine/errorhandler` is used by this version, adding support for `ErrorToExceptionHandler::trap()`. This enables reliably capturing `E_WARNING` and `E_NOTICE` from functions such as `yaml_parse()` and friends.
|
||||||
|
- New dependency versions are required by this version:
|
||||||
|
- `pocketmine/bedrock-protocol` has been updated from 7.1.0 to [7.3.0](https://github.com/pmmp/BedrockProtocol/releases/tag/7.3.0%2Bbedrock-1.18.0).
|
||||||
|
- `pocketmine/errorhandler` has been updated from 0.3.0 to [0.6.0](https://github.com/pmmp/ErrorHandler/releases/tag/0.6.0).
|
||||||
|
|
||||||
|
## API
|
||||||
|
### Block
|
||||||
|
- The following classes have been added:
|
||||||
|
- `Lectern`
|
||||||
|
- `Pumpkin`
|
||||||
|
- The following public API methods have been added:
|
||||||
|
- `Block->getTypeId() : int` - returns an integer which uniquely identifies the block type, ignoring things like facing, colour etc.
|
||||||
|
- `VanillaBlocks::LECTERN()`
|
||||||
|
- `utils\BrewingStandSlot->getSlotNumber() : int`
|
||||||
|
- `utils\FurnaceType->getCookSound() : Sound`
|
||||||
|
- The following API constants have been added:
|
||||||
|
- `tile\BrewingStand::BREW_TIME_TICKS`
|
||||||
|
|
||||||
|
### Crafting
|
||||||
|
- The following API methods have been added:
|
||||||
|
- `CraftingManager->getPotionContainerChangeRecipes() : array<int, array<string, PotionContainerChangeRecipe>>`
|
||||||
|
- `CraftingManager->getPotionTypeRecipes() : array<string, array<string, PotionTypeRecipe>>`
|
||||||
|
- `CraftingManager->registerPotionContainerChangeRecipe(PotionContainerChangeRecipe $recipe) : void`
|
||||||
|
- `CraftingManager->registerPotionTypeRecipe(PotionTypeRecipe $recipe) : void`
|
||||||
|
- The following classes have been added:
|
||||||
|
- `BrewingRecipe`
|
||||||
|
- `PotionContainerChangeRecipe`
|
||||||
|
- `PotionTypeRecipe`
|
||||||
|
|
||||||
|
### Entity
|
||||||
|
- The following classes have been added:
|
||||||
|
- `animation\ItemEntityStackSizeChangeAnimation`
|
||||||
|
- The following public API methods have been added:
|
||||||
|
- `object\ItemEntity->isMergeable(object\ItemEntity $other) : bool`
|
||||||
|
- `object\ItemEntity->setStackSize(int $size) : void`
|
||||||
|
- `object\ItemEntity->tryMergeInto(object\ItemEntity $other) : bool`
|
||||||
|
- `ExperienceManager->canAttractXpOrbs() : bool`
|
||||||
|
- `ExperienceManager->setCanAttractXpOrbs(bool $v = true) : void`
|
||||||
|
- `Entity->getSize() : EntitySizeInfo`
|
||||||
|
- `Living->isGliding() : bool`
|
||||||
|
- `Living->isSwimming() : bool`
|
||||||
|
- `Living->setGliding(bool $value = true) : void`
|
||||||
|
- `Living->setSwimming(bool $value = true) : void`
|
||||||
|
- The following protected API methods have been added:
|
||||||
|
- `Entity->getBlocksIntersected(float $inset) : \Generator<int, Block, void, void>`
|
||||||
|
|
||||||
|
### Event
|
||||||
|
- `BlockSpreadEvent` is now called when fire spreads to the positions of blocks it burns away.
|
||||||
|
- `BlockFormEvent` is now called when concrete powder turns into concrete due to contact with water.
|
||||||
|
- The following classes have been added:
|
||||||
|
- `BlockMeltEvent` - called when ice or snow melts
|
||||||
|
- `BrewItemEvent` - called when a brewing stand finishes brewing potions; this is called up to 3 times (once for each brewing slot, as needed)
|
||||||
|
- `BrewingFuelUseEvent` - called when a brewing stand consumes blaze powder
|
||||||
|
- `ChestPairEvent` - called when two chests try to form a pair
|
||||||
|
- `PlayerToggleGlideEvent` - called when a player starts or stops gliding
|
||||||
|
- `PlayerToggleSwimEvent` - called when a player starts or stops swimming
|
||||||
|
- `PlayerViewDistanceChangeEvent` - called whenever a player alters their render distance or requests one for the first time when connecting
|
||||||
|
|
||||||
|
### Item
|
||||||
|
- The following public API methods have been added:
|
||||||
|
- `SplashPotion->getType() : PotionType`
|
||||||
|
- `VanillaItems::AIR()`
|
||||||
|
- The following API methods have been deprecated:
|
||||||
|
- `ItemFactory::air()` - use `VanillaItems::AIR()` instead
|
||||||
|
|
||||||
|
### Player
|
||||||
|
- The following public API methods have been added:
|
||||||
|
- `Player->hasBlockCollision() : bool`
|
||||||
|
- `Player->setHasBlockCollision(bool $value)` - allows controlling spectator-like no-clip behaviour without changing game mode
|
||||||
|
- `Player->toggleSwim(bool $swim) : bool` - called by the network system when the client tries to start/stop swimming
|
||||||
|
- `Player->toggleGlide(bool $glide) : bool` - called by the network system when the client tries to start/stop gliding
|
||||||
|
|
||||||
|
### Server
|
||||||
|
- The following public API constants have been added:
|
||||||
|
- `Server::DEFAULT_SERVER_NAME`
|
||||||
|
- `Server::DEFAULT_MAX_PLAYERS`
|
||||||
|
- `Server::DEFAULT_PORT_IPV4`
|
||||||
|
- `Server::DEFAULT_PORT_IPV6`
|
||||||
|
- `Server::DEFAULT_MAX_VIEW_DISTANCE`
|
||||||
|
|
||||||
|
### Utils
|
||||||
|
- Config parsing errors are now always represented by `ConfigLoadException` and include the path to the file in the message.
|
||||||
|
- Added `TextFormat::MINECOIN_GOLD`, and support for it to the various `TextFormat` methods.
|
||||||
|
- The following public API methods have been added:
|
||||||
|
- `Utils::assumeNotFalse()` - static analysis crutch to silence PHPStan errors without using `ignoreErrors` or `@phpstan-ignore-line`, which are both too coarse.
|
||||||
|
- The following public API properties have been added:
|
||||||
|
- `Terminal::$COLOR_MINECOIN_GOLD`
|
||||||
|
- The following classes have been added:
|
||||||
|
- `ConfigLoadException`
|
||||||
|
- Fixed `Random->nextSignedInt()` to actually return a signed int. Previously it would return any integer value between 0 and 4,294,957,295.
|
||||||
|
- Fixed `Random->nextSignedFloat()` to return a float between `-1.0` and `1.0`. Previously it would return any value between `0.0` and `2.0`.
|
||||||
|
- `VersionString->getNumber()` output is now structured differently to fix overflow issues caused by the old format.
|
||||||
|
|
||||||
|
### World
|
||||||
|
- The following classes have been added:
|
||||||
|
- `sound\BlastFurnaceSound` - the sound made by a blast furnace during smelting
|
||||||
|
- `sound\FurnaceSound` - the sound made by a regular furnace during cooking or smelting
|
||||||
|
- `sound\ItemUseOnBlockSound`
|
||||||
|
- `sound\LecternPlaceBookSound`
|
||||||
|
- `sound\PotionFinishBrewingSound` - the sound made by a brewing stand when a potion finishes being brewed
|
||||||
|
- `sound\SmokerSound` - the sound made by a smoker during cooking
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
### Blocks
|
||||||
|
- Fire now spreads.
|
||||||
|
- Implemented lectern blocks.
|
||||||
|
- Added missing sounds for hoeing grass and dirt.
|
||||||
|
- Added missing sounds for using a shovel on grass to create grass path.
|
||||||
|
- Pumpkins can now be carved using shears.
|
||||||
|
- Brewing stands can now be used for brewing potions.
|
||||||
|
- The visual appearance of a brewing stand now updates correctly when the contents of its inventory changes (adding/removing potions).
|
||||||
|
- Added missing sounds for furnace, blast furnace and smoker.
|
||||||
|
- Fixed ender chest not dropping itself when mined with a Silk Touch pickaxe.
|
||||||
|
- Cobwebs now drop themselves when mined using shears.
|
||||||
|
- The correct amount of fall damage is now taken when falling from a height onto hay bales.
|
||||||
|
|
||||||
|
### Items
|
||||||
|
- Dropped items of the same type now merge with each other.
|
121
changelogs/4.2.md
Normal file
121
changelogs/4.2.md
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.18.10**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.2.0
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.18.10.
|
||||||
|
|
||||||
|
# 4.2.1
|
||||||
|
Released 19th February 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Improved performance of `Item::nbtSerialize()` - this will improve performance during world saves.
|
||||||
|
- Added more missing changes to the 4.0.0 changelog.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed multiple players being able to sleep in the same bed.
|
||||||
|
- Fixed hitbox not resetting properly after swimming or gliding.
|
||||||
|
|
||||||
|
# 4.2.2
|
||||||
|
Released 2nd March 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed crash in `/dumpmemory` due to usage of non-printable string keys in `CraftingManager`. Array contents in memory dumps are now rendered as prettified key-value pairs.
|
||||||
|
- Fixed output directory for `/dumpmemory`.
|
||||||
|
- `PlayerInventory->isHotbarSlot()` now correctly returns `false` when given `9`.
|
||||||
|
- Fixed ghost items left in the inventory when dropping tools while mining.
|
||||||
|
|
||||||
|
# 4.2.3
|
||||||
|
Released 9th March 2022.
|
||||||
|
|
||||||
|
## Technical
|
||||||
|
- Now analysed using PHPStan 1.4.8.
|
||||||
|
- Now using `pocketmine/bedrock-protocol` [`8.0.1`](https://github.com/pmmp/BedrockProtocol/releases/tag/8.0.1%2Bbedrock-1.18.10).
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
### Core
|
||||||
|
- Fixed a memory leak and other bugs related to plugins disabling themselves during `onEnable()`.
|
||||||
|
|
||||||
|
### Gameplay
|
||||||
|
- Sweet berry bushes now absorb fall damage.
|
||||||
|
- Fixed mycelium spreading onto coarse dirt.
|
||||||
|
- Fixed blocks placed during `Block->onIncinerate()` getting overwritten.
|
||||||
|
- Fixed shulker boxes being unopenable when underwater.
|
||||||
|
- Fixed invisible fire on top of transparent non-flammable blocks.
|
||||||
|
|
||||||
|
### API
|
||||||
|
- Various APIs accepting `Vector3`, `Position` or `Location` no longer accept objects containing `INF` or `NaN` in any component. Previously, this was allowed, but would cause lots of obscure crashes later on.
|
||||||
|
- `Entity->setRotation()` no longer accepts `INF` or `NaN`.
|
||||||
|
- Fixed missing bounds check for `ItemFrame->setItemDropChance()`.
|
||||||
|
|
||||||
|
# 4.2.4
|
||||||
|
Released 18th March 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed a crash when handling out-of-bounds meta values on the network.
|
||||||
|
|
||||||
|
# 4.2.5
|
||||||
|
Released 28th March 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- The layout of the human-readable part of crashdumps has been changed in an effort to improve the useful information density. It is hoped that this change will cause more useful information to be provided when people paste crash traces on Discord, since all the most important information is now at the top of the file.
|
||||||
|
- Version, git hash, PHP version and OS have been moved to the top of the crashdump.
|
||||||
|
- Backtrace has been moved above code sample.
|
||||||
|
- Docker images are now built by GitHub Actions (first live test).
|
||||||
|
|
||||||
|
## Technical
|
||||||
|
- The methods of `Inventory` and `BaseInventory` have been rearranged to improve coherency.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
### API
|
||||||
|
- Enum members of enums created using `EnumTrait` are now able to have single-character names.
|
||||||
|
- Registry members of registries created using `RegistryTrait` or `CloningRegistryTrait` now have their names checked for invalid characters.
|
||||||
|
- `Entity::__construct()` now uses a guard variable to prevent it from being called multiple times unintentionally. This is necessary because `Entity::__construct()` has side effects.
|
||||||
|
- Fixed `PlayerItemHeldEvent` not being called when the content of the held slot was changed (e.g. replacing the held item via inventory menu).
|
||||||
|
|
||||||
|
### Gameplay
|
||||||
|
- Reduced the appearance of ghost items in unsupported gameplay scenarios using client prediction information. This fixes, for example, the appearance of ghost items when right-clicking on a filled flower pot.
|
||||||
|
|
||||||
|
# 4.2.6
|
||||||
|
Released 1st April 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed buffer length underflow crash in `LoginPacket` handling.
|
||||||
|
|
||||||
|
# 4.2.7
|
||||||
|
Released 15th April 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added lots more documentation (in comments) about the `aliases` section in `pocketmine.yml`. You can read about this feature in the `aliases` section of the [updated `pocketmine.yml` template](/resources/pocketmine.yml).
|
||||||
|
- Improved wording of documentation of `PlayerPreLoginEvent`.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed core server crash when a plugin causes another plugin to be disabled during a scheduled task.
|
||||||
|
- Fixed core server crash when loading a plugin with an abstract main class.
|
||||||
|
- Fixed ghost items in many interaction situations (most notably, using projectiles while looking at an entity or block).
|
||||||
|
- Implemented a workaround for a client teleport bug which led to player positions not updating properly when using ender pearls.
|
||||||
|
- Fixed buggy movement when teleporting the player during `PlayerToggleSneakEvent`, `PlayerToggleSprintEvent`, `PlayerToggleSwimEvent` and `PlayerToggleGlideEvent`.
|
||||||
|
|
||||||
|
# 4.2.8
|
||||||
|
Released 17th April 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed a memory leak in RakLib which could result in a server crash when players stay online for a long time.
|
||||||
|
- Fixed server crash when attempting to load a corrupted empty resource pack.
|
||||||
|
- Fixed users with the same name with differerently cased letters being able to duplicate items (userdata is matched by case-insensitive name).
|
||||||
|
|
||||||
|
# 4.2.9
|
||||||
|
Released 19th April 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed several potential crashes when deserializing item NBT (due to insufficient validation of input data).
|
||||||
|
|
||||||
|
# 4.2.10
|
||||||
|
Released 20th April 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed performance issue when chat messages received from the client contain many newlines. This security vulnerability was disclosed publicly necessitating a priority fix.
|
77
changelogs/4.3.md
Normal file
77
changelogs/4.3.md
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.18.30**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.3.0
|
||||||
|
Released 20th April 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.18.30.
|
||||||
|
- Removed support for older versions.
|
||||||
|
|
||||||
|
# 4.3.1
|
||||||
|
Released 23rd April 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Updated BedrockProtocol dependency to fix incorrect command argument types.
|
||||||
|
- Creative players no longer die in the void.
|
||||||
|
|
||||||
|
# 4.3.2
|
||||||
|
Released 10th May 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed an assertion failure in certain edge cases during world generation.
|
||||||
|
- Fixed `Entity::setNameTagVisible()` not immediately showing results to players already online.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
- Added more documentation in the template `pocketmine.yml` for the `aliases` config section.
|
||||||
|
- Removed useless doc comment in `PlayerChangeSkinEvent`.
|
||||||
|
|
||||||
|
# 4.3.3
|
||||||
|
Released 16th May 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Improved display of parameters in exception stack trace logs.
|
||||||
|
- Exception stack traces now include names for dynamic named arguments (i.e. arguments that don't match any parameter of the function), if any were given.
|
||||||
|
- Note: Named arguments which do match parameters are not shown this way, since PHP reduces them to positional arguments for performance reasons.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed server crash when chunks are unloaded during chunk generation callbacks
|
||||||
|
- Fixed dead coral fan items placing coral fans in the wrong orientation.
|
||||||
|
- Fixed max stack size of boat items.
|
||||||
|
|
||||||
|
# 4.3.4
|
||||||
|
Released 22nd May 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed `difficulty` in `server.properties` having no effect - it's now applied to newly generated worlds.
|
||||||
|
- Note: this setting still doesn't behave the same way as vanilla due to potential disruption to existing servers.
|
||||||
|
- Fixed paintings not working in newly generated worlds and some other cases.
|
||||||
|
- Fixed inventory window switching breaking the inventory UI in some cases (e.g. pressing E while clicking a chest).
|
||||||
|
- Fixed minecart items incorrectly stacking.
|
||||||
|
- Fixed incorrect light levels in translucent blocks at the top of the world.
|
||||||
|
- Fixed teleporting sleeping players causing broken behaviour on the sleeping player's client.
|
||||||
|
- Fixed `EntityExplodeEvent->setYield()` accepting values outside the range 0-100.
|
||||||
|
- Fixed `ExplosionPrimeEvent->setForce()` accepting negative values (later resulting in crashes).
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
- Updated documentation for the following events:
|
||||||
|
- `CommandEvent`
|
||||||
|
- `EntityDespawnEvent`
|
||||||
|
- `EntityExplodeEvent`
|
||||||
|
- `EntitySpawnEvent`
|
||||||
|
- `ExplosionPrimeEvent`
|
||||||
|
- `InventoryTransactionEvent`
|
||||||
|
- `ItemDespawnEvent`
|
||||||
|
- `ItemSpawnEvent`
|
||||||
|
- `PlayerCommandPreprocessEvent`
|
||||||
|
- `PlayerDropItemEvent`
|
||||||
|
- `PlayerItemHeldEvent`
|
||||||
|
- `PlayerKickEvent`
|
||||||
|
- `PlayerQuitEvent`
|
||||||
|
- `PlayerTransferEvent`
|
||||||
|
- `UpdateNotifyEvent`
|
77
changelogs/4.4-beta.md
Normal file
77
changelogs/4.4-beta.md
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.18.30**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.4.0-BETA1
|
||||||
|
Released 25th May 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- The server will now shut itself down if any of the following errors occur during startup:
|
||||||
|
- Any plugin fails to load or enable (plugins loaded by other plugins post-startup are **not** affected by this change) (**PR [#4951](https://github.com/pmmp/PocketMine-MP/pull/4951)**)
|
||||||
|
- The motivation for this change is to prevent situations where plugins failing to load could result in adverse outcomes, such as a world protection plugin leaving a lobby unprotected from griefing.
|
||||||
|
- If you encounter this problem, remove the offending plugin(s) or prevent it from loading using `plugin_list.yml`.
|
||||||
|
- See **PR [#4951](https://github.com/pmmp/PocketMine-MP/pull/4951)** for more detail on this change.
|
||||||
|
- Any world mentioned in `server.properties` or `pocketmine.yml` fails to load (worlds loaded by plugins are **not** affected by this change)
|
||||||
|
- Any world mentioned in `server.properties` or `pocketmine.yml` fails to generate (e.g. due to invalid generator settings)
|
||||||
|
- Enabling the server whitelist while the server is running (e.g. using `/whitelist on`) will now kick any non-whitelisted players currently on the server (**PR [#4774](https://github.com/pmmp/PocketMine-MP/pull/4774)**).
|
||||||
|
- Help for commands (`/help <name of command>`) now displays a list of aliases of that command.
|
||||||
|
- A CRITICAL log message is now generated if a plugin disables itself when enabling, in case the plugin doesn't emit any error of its own.
|
||||||
|
- The `/give` command now shows the alias used to find the given item in the success message, instead of the item ID/meta.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Block placement has been fixed in many places where it previously didn't work correctly (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**):
|
||||||
|
- torches on top of slabs, upside-down stairs
|
||||||
|
- torches on the back face of stairs
|
||||||
|
- flower pots on top of fences
|
||||||
|
- the list goes on and on ...
|
||||||
|
- Fixed backslash escapes not getting properly removed from commands in some cases.
|
||||||
|
- Fixed aliases defined in the `aliases` section of `pocketmine.yml` not being treated as quote-aware.
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
- Plants in flower pots can now be removed by right-clicking on the flower pot.
|
||||||
|
- Leaves now have a 2% chance of dropping sticks when destroyed by hand (**PR [#5019](https://github.com/pmmp/PocketMine-MP/pull/5019)**).
|
||||||
|
- Food exhaustion now matches Bedrock 1.18.30 (**PR [#5034](https://github.com/pmmp/PocketMine-MP/pull/5034)**).
|
||||||
|
- Implemented Stonecutter block (**PR [#4732](https://github.com/pmmp/PocketMine-MP/pull/4732)**).
|
||||||
|
|
||||||
|
## API
|
||||||
|
### Block
|
||||||
|
- Added `Block->getSupportType(Facing) : SupportType` (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**).
|
||||||
|
- This is used to determine the kind of support a block face can provide to a block (e.g. a torch) placed on it.
|
||||||
|
- Added `utils\SupportType` enum (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**).
|
||||||
|
- `tile\Spawnable->isDirty()` and `tile\Spawnable->setDirty()` are now `@deprecated`.
|
||||||
|
|
||||||
|
### Command
|
||||||
|
- Added `CommandStringHelper::parseQuoteAware()`. This static method contains the code used by `SimpleCommandMap` used to parse quoted command arguments.
|
||||||
|
|
||||||
|
### Entity
|
||||||
|
- Added `Human::emote()` (**PR [#4610](https://github.com/pmmp/PocketMine-MP/pull/4610)**)
|
||||||
|
|
||||||
|
### Event
|
||||||
|
- `PlayerCommandPreprocessEvent` is now `@deprecated`, since its functionality is entirely replaced by other, general-purpose events.
|
||||||
|
- Use `CommandEvent` to intercept commands.
|
||||||
|
- Use `PlayerChatEvent` to intercept chat messages.
|
||||||
|
- To convert a chat message into a command, pass it directly to `Server->dispatchCommand()` with the player as sender.
|
||||||
|
- Added `PlayerPostChunkSendEvent` (**PR [#4937](https://github.com/pmmp/PocketMine-MP/pull/4937)**).
|
||||||
|
- Added `PlayerDeathEvent->setKeepXp()` (**PR [#4015](https://github.com/pmmp/PocketMine-MP/pull/4015)**).
|
||||||
|
- `InventoryCloseEvent` is now called **after** the target window has been removed. This fixes various feedback loops caused by trying to open new windows to a player while there was one still active.
|
||||||
|
- As a side effect, this now means that `Player->getCurrentWindow()` will return `null` during `InventoryCloseEvent`. Use `InventoryCloseEvent->getInventory()` instead.
|
||||||
|
|
||||||
|
### Item
|
||||||
|
- `StringToItemParser` now recognizes `cod`, `raw_cod` and `cooked_cod` aliases.
|
||||||
|
|
||||||
|
### Plugin
|
||||||
|
- `DisablePluginException` may now be thrown from `Plugin::onEnable()` to make the server gracefully disable the plugin (without crashing) (**PR [#4780](https://github.com/pmmp/PocketMine-MP/pull/4780)**).
|
||||||
|
- `PluginManager->registerEvent()` now returns the `RegisteredListener` created for the handler, to permit unregistering it later.
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- Private property declarations now use typed properties (PHP 7.4) and promoted constructor properties (PHP 8.0) wherever possible.
|
||||||
|
- Protected and public properties remain unchanged, since they can't be changed without breaking subclasses.
|
||||||
|
- Promoted constructor properties are only used when it's consistently possible to promote most or all properties in a class.
|
||||||
|
- Simplified and improved legibility of `FormattedCommandAlias`.
|
||||||
|
- Added unit tests for the quote-aware command parser used by `SimpleCommandMap`.
|
||||||
|
- Various hardcoded values in `block` package classes have been moved to private constants to improve readability.
|
||||||
|
- Added various constants used in the `LevelDB` world provider.
|
97
changelogs/4.4.md
Normal file
97
changelogs/4.4.md
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.18.30**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.4.0
|
||||||
|
Released 1st June 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- The server will now shut itself down if any of the following errors occur during startup:
|
||||||
|
- Any plugin fails to load or enable (plugins loaded by other plugins post-startup are **not** affected by this change) (**PR [#4951](https://github.com/pmmp/PocketMine-MP/pull/4951)**)
|
||||||
|
- The motivation for this change is to prevent situations where plugins failing to load could result in adverse outcomes, such as a world protection plugin leaving a lobby unprotected from griefing.
|
||||||
|
- If you encounter this problem, remove the offending plugin(s) or prevent it from loading using `plugin_list.yml`.
|
||||||
|
- See **PR [#4951](https://github.com/pmmp/PocketMine-MP/pull/4951)** for more detail on this change.
|
||||||
|
- Any world mentioned in `server.properties` or `pocketmine.yml` fails to load (worlds loaded by plugins are **not** affected by this change)
|
||||||
|
- Any world mentioned in `server.properties` or `pocketmine.yml` fails to generate (e.g. due to invalid generator settings)
|
||||||
|
- Enabling the server whitelist while the server is running (e.g. using `/whitelist on`) will now kick any non-whitelisted players currently on the server (**PR [#4774](https://github.com/pmmp/PocketMine-MP/pull/4774)**).
|
||||||
|
- Help for commands (`/help <name of command>`) now displays a list of aliases of that command.
|
||||||
|
- A CRITICAL log message is now generated if a plugin disables itself when enabling, in case the plugin doesn't emit any error of its own.
|
||||||
|
- The `/give` command now shows the alias used to find the given item in the success message, instead of the item ID/meta.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Block placement has been fixed in many places where it previously didn't work correctly (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**):
|
||||||
|
- torches on top of slabs, upside-down stairs
|
||||||
|
- torches on the back face of stairs
|
||||||
|
- flower pots on top of fences
|
||||||
|
- the list goes on and on ...
|
||||||
|
- Fixed backslash escapes not getting properly removed from commands in some cases.
|
||||||
|
- Fixed aliases defined in the `aliases` section of `pocketmine.yml` not being treated as quote-aware.
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
- Plants in flower pots can now be removed by right-clicking on the flower pot.
|
||||||
|
- Leaves now have a 2% chance of dropping sticks when destroyed by hand (**PR [#5019](https://github.com/pmmp/PocketMine-MP/pull/5019)**).
|
||||||
|
- Food exhaustion now matches Bedrock 1.18.30 (**PR [#5034](https://github.com/pmmp/PocketMine-MP/pull/5034)**).
|
||||||
|
- Implemented Stonecutter block (**PR [#4732](https://github.com/pmmp/PocketMine-MP/pull/4732)**).
|
||||||
|
|
||||||
|
## API
|
||||||
|
### Block
|
||||||
|
- Added `Block->getSupportType(Facing) : SupportType` (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**).
|
||||||
|
- This is used to determine the kind of support a block face can provide to a block (e.g. a torch) placed on it.
|
||||||
|
- Added `utils\SupportType` enum (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**).
|
||||||
|
- `tile\Spawnable->isDirty()` and `tile\Spawnable->setDirty()` are now `@deprecated`.
|
||||||
|
|
||||||
|
### Command
|
||||||
|
- Added `CommandStringHelper::parseQuoteAware()`. This static method contains the code used by `SimpleCommandMap` used to parse quoted command arguments.
|
||||||
|
|
||||||
|
### Entity
|
||||||
|
- Added `Human::emote()` (**PR [#4610](https://github.com/pmmp/PocketMine-MP/pull/4610)**)
|
||||||
|
|
||||||
|
### Event
|
||||||
|
- `PlayerCommandPreprocessEvent` is now `@deprecated`, since its functionality is entirely replaced by other, general-purpose events.
|
||||||
|
- Use `CommandEvent` to intercept commands.
|
||||||
|
- Use `PlayerChatEvent` to intercept chat messages.
|
||||||
|
- To convert a chat message into a command, pass it directly to `Server->dispatchCommand()` with the player as sender.
|
||||||
|
- Added `PlayerPostChunkSendEvent` (**PR [#4937](https://github.com/pmmp/PocketMine-MP/pull/4937)**).
|
||||||
|
- Added `PlayerDeathEvent->setKeepXp()` (**PR [#4015](https://github.com/pmmp/PocketMine-MP/pull/4015)**).
|
||||||
|
- `InventoryCloseEvent` is now called **after** the target window has been removed. This fixes various feedback loops caused by trying to open new windows to a player while there was one still active.
|
||||||
|
- As a side effect, this now means that `Player->getCurrentWindow()` will return `null` during `InventoryCloseEvent`. Use `InventoryCloseEvent->getInventory()` instead.
|
||||||
|
|
||||||
|
### Item
|
||||||
|
- `StringToItemParser` now recognizes `cod`, `raw_cod` and `cooked_cod` aliases.
|
||||||
|
|
||||||
|
### Plugin
|
||||||
|
- `DisablePluginException` may now be thrown from `Plugin::onEnable()` to make the server gracefully disable the plugin (without crashing) (**PR [#4780](https://github.com/pmmp/PocketMine-MP/pull/4780)**).
|
||||||
|
- `PluginManager->registerEvent()` now returns the `RegisteredListener` created for the handler, to permit unregistering it later.
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
- Private property declarations now use typed properties (PHP 7.4) and promoted constructor properties (PHP 8.0) wherever possible.
|
||||||
|
- Protected and public properties remain unchanged, since they can't be changed without breaking subclasses.
|
||||||
|
- Promoted constructor properties are only used when it's consistently possible to promote most or all properties in a class.
|
||||||
|
- Simplified and improved legibility of `FormattedCommandAlias`.
|
||||||
|
- Added unit tests for the quote-aware command parser used by `SimpleCommandMap`.
|
||||||
|
- Various hardcoded values in `block` package classes have been moved to private constants to improve readability.
|
||||||
|
- Added various constants used in the `LevelDB` world provider.
|
||||||
|
|
||||||
|
# 4.4.1
|
||||||
|
Released 5th June 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- The server process will now exit with an error code if plugins, worlds or network interfaces failed to start.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed graylisted plugins preventing the server from starting.
|
||||||
|
- Fixed `composer make-devtools` command.
|
||||||
|
- Fixed the `Maximum memory (manager)` units being incorrectly displayed in `/status`.
|
||||||
|
- Fixed `Player->removeCurrentWindow()` breaking inventory windows.
|
||||||
|
|
||||||
|
# 4.4.2
|
||||||
|
Released 7th June 2022.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fixed a crash when arbitrary item IDs appeared in network items in some cases.
|
||||||
|
- Fixed saved paintings being deleted when loaded from disk (regression from 4.3.4).
|
||||||
|
- Fixed max stack size of fishing rods.
|
14
changelogs/4.5.md
Normal file
14
changelogs/4.5.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.0**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.5.0
|
||||||
|
Released 7th June 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.19.0.
|
||||||
|
- Removed support for older versions.
|
@ -7,7 +7,7 @@
|
|||||||
"require": {
|
"require": {
|
||||||
"php": "^8.0",
|
"php": "^8.0",
|
||||||
"php-64bit": "*",
|
"php-64bit": "*",
|
||||||
"ext-chunkutils2": "^0.3.0",
|
"ext-chunkutils2": "^0.3.1",
|
||||||
"ext-crypto": "^0.3.1",
|
"ext-crypto": "^0.3.1",
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-curl": "*",
|
"ext-curl": "*",
|
||||||
@ -22,7 +22,7 @@
|
|||||||
"ext-openssl": "*",
|
"ext-openssl": "*",
|
||||||
"ext-pcre": "*",
|
"ext-pcre": "*",
|
||||||
"ext-phar": "*",
|
"ext-phar": "*",
|
||||||
"ext-pthreads": "~3.2.0",
|
"ext-pthreads": "^4.0",
|
||||||
"ext-reflection": "*",
|
"ext-reflection": "*",
|
||||||
"ext-simplexml": "*",
|
"ext-simplexml": "*",
|
||||||
"ext-sockets": "*",
|
"ext-sockets": "*",
|
||||||
@ -34,28 +34,28 @@
|
|||||||
"adhocore/json-comment": "^1.1",
|
"adhocore/json-comment": "^1.1",
|
||||||
"fgrosse/phpasn1": "^2.3",
|
"fgrosse/phpasn1": "^2.3",
|
||||||
"netresearch/jsonmapper": "^4.0",
|
"netresearch/jsonmapper": "^4.0",
|
||||||
"pocketmine/bedrock-protocol": "2.0.0+bedrock1.17.30",
|
"pocketmine/bedrock-data": "~1.8.0+bedrock-1.19.0",
|
||||||
|
"pocketmine/bedrock-protocol": "~10.0.0+bedrock-1.19.0",
|
||||||
"pocketmine/binaryutils": "^0.2.1",
|
"pocketmine/binaryutils": "^0.2.1",
|
||||||
"pocketmine/callback-validator": "^1.0.2",
|
"pocketmine/callback-validator": "^1.0.2",
|
||||||
"pocketmine/classloader": "dev-master",
|
"pocketmine/classloader": "^0.2.0",
|
||||||
"pocketmine/color": "^0.2.0",
|
"pocketmine/color": "^0.2.0",
|
||||||
"pocketmine/errorhandler": "^0.3.0",
|
"pocketmine/errorhandler": "^0.6.0",
|
||||||
"pocketmine/log": "^0.3.0",
|
"pocketmine/locale-data": "~2.8.0",
|
||||||
"pocketmine/log-pthreads": "^0.2.0",
|
"pocketmine/log": "^0.4.0",
|
||||||
"pocketmine/math": "^0.3.0",
|
"pocketmine/log-pthreads": "^0.4.0",
|
||||||
"pocketmine/nbt": "^0.3.0",
|
"pocketmine/math": "^0.4.0",
|
||||||
"pocketmine/raklib": "^0.14.0",
|
"pocketmine/nbt": "^0.3.2",
|
||||||
|
"pocketmine/raklib": "^0.14.2",
|
||||||
"pocketmine/raklib-ipc": "^0.1.0",
|
"pocketmine/raklib-ipc": "^0.1.0",
|
||||||
"pocketmine/snooze": "^0.3.0",
|
"pocketmine/snooze": "^0.3.0",
|
||||||
"pocketmine/spl": "dev-master",
|
|
||||||
"ramsey/uuid": "^4.1",
|
"ramsey/uuid": "^4.1",
|
||||||
"respect/validation": "^2.0",
|
|
||||||
"webmozart/path-util": "^2.3"
|
"webmozart/path-util": "^2.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpstan/phpstan": "0.12.98",
|
"phpstan/phpstan": "1.7.8",
|
||||||
"phpstan/phpstan-phpunit": "^0.12.6",
|
"phpstan/phpstan-phpunit": "^1.1.0",
|
||||||
"phpstan/phpstan-strict-rules": "^0.12.2",
|
"phpstan/phpstan-strict-rules": "^1.2.0",
|
||||||
"phpunit/phpunit": "^9.2"
|
"phpunit/phpunit": "^9.2"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -79,7 +79,7 @@
|
|||||||
"sort-packages": true
|
"sort-packages": true
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"make-devtools": "@php -dphar.readonly=0 tests/plugins/DevTools/src/DevTools/ConsoleScript.php --make tests/plugins/DevTools --out plugins/DevTools.phar",
|
"make-devtools": "@php -dphar.readonly=0 tests/plugins/DevTools/src/ConsoleScript.php --make ./ --relative tests/plugins/DevTools --out plugins/DevTools.phar",
|
||||||
"make-server": [
|
"make-server": [
|
||||||
"@composer install --no-dev --classmap-authoritative --ignore-platform-reqs",
|
"@composer install --no-dev --classmap-authoritative --ignore-platform-reqs",
|
||||||
"@php -dphar.readonly=0 build/server-phar.php"
|
"@php -dphar.readonly=0 build/server-phar.php"
|
||||||
|
910
composer.lock
generated
910
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
# Doxyfile 1.8.15
|
# Doxyfile 1.9.3
|
||||||
|
|
||||||
# This file describes the settings to be used by the documentation system
|
# This file describes the settings to be used by the documentation system
|
||||||
# doxygen (www.doxygen.org) for a project.
|
# doxygen (www.doxygen.org) for a project.
|
||||||
@ -93,14 +93,6 @@ ALLOW_UNICODE_NAMES = NO
|
|||||||
|
|
||||||
OUTPUT_LANGUAGE = English
|
OUTPUT_LANGUAGE = English
|
||||||
|
|
||||||
# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
|
|
||||||
# documentation generated by doxygen is written. Doxygen will use this
|
|
||||||
# information to generate all generated output in the proper direction.
|
|
||||||
# Possible values are: None, LTR, RTL and Context.
|
|
||||||
# The default value is: None.
|
|
||||||
|
|
||||||
OUTPUT_TEXT_DIRECTION = None
|
|
||||||
|
|
||||||
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
|
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
|
||||||
# descriptions after the members that are listed in the file and class
|
# descriptions after the members that are listed in the file and class
|
||||||
# documentation (similar to Javadoc). Set to NO to disable this.
|
# documentation (similar to Javadoc). Set to NO to disable this.
|
||||||
@ -197,6 +189,16 @@ SHORT_NAMES = NO
|
|||||||
|
|
||||||
JAVADOC_AUTOBRIEF = NO
|
JAVADOC_AUTOBRIEF = NO
|
||||||
|
|
||||||
|
# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
|
||||||
|
# such as
|
||||||
|
# /***************
|
||||||
|
# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
|
||||||
|
# Javadoc-style will behave just like regular comments and it will not be
|
||||||
|
# interpreted by doxygen.
|
||||||
|
# The default value is: NO.
|
||||||
|
|
||||||
|
JAVADOC_BANNER = NO
|
||||||
|
|
||||||
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
|
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
|
||||||
# line (until the first dot) of a Qt-style comment as the brief description. If
|
# line (until the first dot) of a Qt-style comment as the brief description. If
|
||||||
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
|
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
|
||||||
@ -217,6 +219,14 @@ QT_AUTOBRIEF = NO
|
|||||||
|
|
||||||
MULTILINE_CPP_IS_BRIEF = NO
|
MULTILINE_CPP_IS_BRIEF = NO
|
||||||
|
|
||||||
|
# By default Python docstrings are displayed as preformatted text and doxygen's
|
||||||
|
# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
|
||||||
|
# doxygen's special commands can be used and the contents of the docstring
|
||||||
|
# documentation blocks is shown as doxygen documentation.
|
||||||
|
# The default value is: YES.
|
||||||
|
|
||||||
|
PYTHON_DOCSTRING = YES
|
||||||
|
|
||||||
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
|
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
|
||||||
# documentation from any documented member that it re-implements.
|
# documentation from any documented member that it re-implements.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
@ -240,25 +250,19 @@ TAB_SIZE = 4
|
|||||||
# the documentation. An alias has the form:
|
# the documentation. An alias has the form:
|
||||||
# name=value
|
# name=value
|
||||||
# For example adding
|
# For example adding
|
||||||
# "sideeffect=@par Side Effects:\n"
|
# "sideeffect=@par Side Effects:^^"
|
||||||
# will allow you to put the command \sideeffect (or @sideeffect) in the
|
# will allow you to put the command \sideeffect (or @sideeffect) in the
|
||||||
# documentation, which will result in a user-defined paragraph with heading
|
# documentation, which will result in a user-defined paragraph with heading
|
||||||
# "Side Effects:". You can put \n's in the value part of an alias to insert
|
# "Side Effects:". Note that you cannot put \n's in the value part of an alias
|
||||||
# newlines (in the resulting output). You can put ^^ in the value part of an
|
# to insert newlines (in the resulting output). You can put ^^ in the value part
|
||||||
# alias to insert a newline as if a physical newline was in the original file.
|
# of an alias to insert a newline as if a physical newline was in the original
|
||||||
# When you need a literal { or } or , in the value part of an alias you have to
|
# file. When you need a literal { or } or , in the value part of an alias you
|
||||||
# escape them by means of a backslash (\), this can lead to conflicts with the
|
# have to escape them by means of a backslash (\), this can lead to conflicts
|
||||||
# commands \{ and \} for these it is advised to use the version @{ and @} or use
|
# with the commands \{ and \} for these it is advised to use the version @{ and
|
||||||
# a double escape (\\{ and \\})
|
# @} or use a double escape (\\{ and \\})
|
||||||
|
|
||||||
ALIASES =
|
ALIASES =
|
||||||
|
|
||||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
|
||||||
# A mapping has the form "name=value". For example adding "class=itcl::class"
|
|
||||||
# will allow you to use the command class in the itcl::class meaning.
|
|
||||||
|
|
||||||
TCL_SUBST =
|
|
||||||
|
|
||||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
||||||
# only. Doxygen will then generate output that is more tailored for C. For
|
# only. Doxygen will then generate output that is more tailored for C. For
|
||||||
# instance, some of the names that are used will be different. The list of all
|
# instance, some of the names that are used will be different. The list of all
|
||||||
@ -299,19 +303,22 @@ OPTIMIZE_OUTPUT_SLICE = NO
|
|||||||
# parses. With this tag you can assign which parser to use for a given
|
# parses. With this tag you can assign which parser to use for a given
|
||||||
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
||||||
# using this tag. The format is ext=language, where ext is a file extension, and
|
# using this tag. The format is ext=language, where ext is a file extension, and
|
||||||
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
|
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
|
||||||
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
|
# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
|
||||||
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
||||||
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
|
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
|
||||||
# tries to guess whether the code is fixed or free formatted code, this is the
|
# tries to guess whether the code is fixed or free formatted code, this is the
|
||||||
# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
|
# default for Fortran type files). For instance to make doxygen treat .inc files
|
||||||
# .inc files as Fortran files (default is PHP), and .f files as C (default is
|
# as Fortran files (default is PHP), and .f files as C (default is Fortran),
|
||||||
# Fortran), use: inc=Fortran f=C.
|
# use: inc=Fortran f=C.
|
||||||
#
|
#
|
||||||
# Note: For files without extension you can use no_extension as a placeholder.
|
# Note: For files without extension you can use no_extension as a placeholder.
|
||||||
#
|
#
|
||||||
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
|
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
|
||||||
# the files are not read by doxygen.
|
# the files are not read by doxygen. When specifying no_extension you should add
|
||||||
|
# * to the FILE_PATTERNS.
|
||||||
|
#
|
||||||
|
# Note see also the list of default file extension mappings.
|
||||||
|
|
||||||
EXTENSION_MAPPING =
|
EXTENSION_MAPPING =
|
||||||
|
|
||||||
@ -329,7 +336,7 @@ MARKDOWN_SUPPORT = YES
|
|||||||
# to that level are automatically included in the table of contents, even if
|
# to that level are automatically included in the table of contents, even if
|
||||||
# they do not have an id attribute.
|
# they do not have an id attribute.
|
||||||
# Note: This feature currently applies only to Markdown headings.
|
# Note: This feature currently applies only to Markdown headings.
|
||||||
# Minimum value: 0, maximum value: 99, default value: 0.
|
# Minimum value: 0, maximum value: 99, default value: 5.
|
||||||
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
|
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
|
||||||
|
|
||||||
TOC_INCLUDE_HEADINGS = 0
|
TOC_INCLUDE_HEADINGS = 0
|
||||||
@ -445,6 +452,19 @@ TYPEDEF_HIDES_STRUCT = NO
|
|||||||
|
|
||||||
LOOKUP_CACHE_SIZE = 0
|
LOOKUP_CACHE_SIZE = 0
|
||||||
|
|
||||||
|
# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
|
||||||
|
# during processing. When set to 0 doxygen will based this on the number of
|
||||||
|
# cores available in the system. You can set it explicitly to a value larger
|
||||||
|
# than 0 to get more control over the balance between CPU load and processing
|
||||||
|
# speed. At this moment only the input processing can be done using multiple
|
||||||
|
# threads. Since this is still an experimental feature the default is set to 1,
|
||||||
|
# which effectively disables parallel processing. Please report any issues you
|
||||||
|
# encounter. Generating dot graphs in parallel is controlled by the
|
||||||
|
# DOT_NUM_THREADS setting.
|
||||||
|
# Minimum value: 0, maximum value: 32, default value: 1.
|
||||||
|
|
||||||
|
NUM_PROC_THREADS = 1
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Build related configuration options
|
# Build related configuration options
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
@ -465,6 +485,12 @@ EXTRACT_ALL = NO
|
|||||||
|
|
||||||
EXTRACT_PRIVATE = NO
|
EXTRACT_PRIVATE = NO
|
||||||
|
|
||||||
|
# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
|
||||||
|
# methods of a class will be included in the documentation.
|
||||||
|
# The default value is: NO.
|
||||||
|
|
||||||
|
EXTRACT_PRIV_VIRTUAL = NO
|
||||||
|
|
||||||
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
|
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
|
||||||
# scope will be included in the documentation.
|
# scope will be included in the documentation.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
@ -502,6 +528,13 @@ EXTRACT_LOCAL_METHODS = YES
|
|||||||
|
|
||||||
EXTRACT_ANON_NSPACES = YES
|
EXTRACT_ANON_NSPACES = YES
|
||||||
|
|
||||||
|
# If this flag is set to YES, the name of an unnamed parameter in a declaration
|
||||||
|
# will be determined by the corresponding definition. By default unnamed
|
||||||
|
# parameters remain unnamed in the output.
|
||||||
|
# The default value is: YES.
|
||||||
|
|
||||||
|
RESOLVE_UNNAMED_PARAMS = YES
|
||||||
|
|
||||||
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
|
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
|
||||||
# undocumented members inside documented classes or files. If set to NO these
|
# undocumented members inside documented classes or files. If set to NO these
|
||||||
# members will be included in the various overviews, but no documentation
|
# members will be included in the various overviews, but no documentation
|
||||||
@ -519,8 +552,8 @@ HIDE_UNDOC_MEMBERS = NO
|
|||||||
HIDE_UNDOC_CLASSES = NO
|
HIDE_UNDOC_CLASSES = NO
|
||||||
|
|
||||||
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
|
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
|
||||||
# (class|struct|union) declarations. If set to NO, these declarations will be
|
# declarations. If set to NO, these declarations will be included in the
|
||||||
# included in the documentation.
|
# documentation.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
HIDE_FRIEND_COMPOUNDS = NO
|
HIDE_FRIEND_COMPOUNDS = NO
|
||||||
@ -539,11 +572,18 @@ HIDE_IN_BODY_DOCS = YES
|
|||||||
|
|
||||||
INTERNAL_DOCS = NO
|
INTERNAL_DOCS = NO
|
||||||
|
|
||||||
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
|
# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
|
||||||
# names in lower-case letters. If set to YES, upper-case letters are also
|
# able to match the capabilities of the underlying filesystem. In case the
|
||||||
# allowed. This is useful if you have classes or files whose names only differ
|
# filesystem is case sensitive (i.e. it supports files in the same directory
|
||||||
# in case and if your file system supports case sensitive file names. Windows
|
# whose names only differ in casing), the option must be set to YES to properly
|
||||||
# and Mac users are advised to set this option to NO.
|
# deal with such files in case they appear in the input. For filesystems that
|
||||||
|
# are not case sensitive the option should be be set to NO to properly deal with
|
||||||
|
# output files written for symbols that only differ in casing, such as for two
|
||||||
|
# classes, one named CLASS and the other named Class, and to also support
|
||||||
|
# references to files without having to specify the exact matching casing. On
|
||||||
|
# Windows (including Cygwin) and MacOS, users should typically set this option
|
||||||
|
# to NO, whereas on Linux or other Unix flavors it should typically be set to
|
||||||
|
# YES.
|
||||||
# The default value is: system dependent.
|
# The default value is: system dependent.
|
||||||
|
|
||||||
CASE_SENSE_NAMES = NO
|
CASE_SENSE_NAMES = NO
|
||||||
@ -562,6 +602,12 @@ HIDE_SCOPE_NAMES = NO
|
|||||||
|
|
||||||
HIDE_COMPOUND_REFERENCE= NO
|
HIDE_COMPOUND_REFERENCE= NO
|
||||||
|
|
||||||
|
# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
|
||||||
|
# will show which file needs to be included to use the class.
|
||||||
|
# The default value is: YES.
|
||||||
|
|
||||||
|
SHOW_HEADERFILE = YES
|
||||||
|
|
||||||
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
|
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
|
||||||
# the files that are included by a file in the documentation of that file.
|
# the files that are included by a file in the documentation of that file.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
@ -719,7 +765,8 @@ FILE_VERSION_FILTER =
|
|||||||
# output files in an output format independent way. To create the layout file
|
# output files in an output format independent way. To create the layout file
|
||||||
# that represents doxygen's defaults, run doxygen with the -l option. You can
|
# that represents doxygen's defaults, run doxygen with the -l option. You can
|
||||||
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
|
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
|
||||||
# will be used as the name of the layout file.
|
# will be used as the name of the layout file. See also section "Changing the
|
||||||
|
# layout of pages" for information.
|
||||||
#
|
#
|
||||||
# Note that if you run doxygen from a directory containing a file called
|
# Note that if you run doxygen from a directory containing a file called
|
||||||
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
|
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
|
||||||
@ -765,24 +812,35 @@ WARNINGS = NO
|
|||||||
WARN_IF_UNDOCUMENTED = NO
|
WARN_IF_UNDOCUMENTED = NO
|
||||||
|
|
||||||
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
|
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
|
||||||
# potential errors in the documentation, such as not documenting some parameters
|
# potential errors in the documentation, such as documenting some parameters in
|
||||||
# in a documented function, or documenting parameters that don't exist or using
|
# a documented function twice, or documenting parameters that don't exist or
|
||||||
# markup commands wrongly.
|
# using markup commands wrongly.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
WARN_IF_DOC_ERROR = YES
|
WARN_IF_DOC_ERROR = YES
|
||||||
|
|
||||||
|
# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
|
||||||
|
# function parameter documentation. If set to NO, doxygen will accept that some
|
||||||
|
# parameters have no documentation without warning.
|
||||||
|
# The default value is: YES.
|
||||||
|
|
||||||
|
WARN_IF_INCOMPLETE_DOC = YES
|
||||||
|
|
||||||
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
|
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
|
||||||
# are documented, but have no documentation for their parameters or return
|
# are documented, but have no documentation for their parameters or return
|
||||||
# value. If set to NO, doxygen will only warn about wrong or incomplete
|
# value. If set to NO, doxygen will only warn about wrong parameter
|
||||||
# parameter documentation, but not about the absence of documentation. If
|
# documentation, but not about the absence of documentation. If EXTRACT_ALL is
|
||||||
# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
|
# set to YES then this flag will automatically be disabled. See also
|
||||||
|
# WARN_IF_INCOMPLETE_DOC
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
WARN_NO_PARAMDOC = NO
|
WARN_NO_PARAMDOC = NO
|
||||||
|
|
||||||
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
|
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
|
||||||
# a warning is encountered.
|
# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
|
||||||
|
# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
|
||||||
|
# at the end of the doxygen process doxygen will return with a non-zero status.
|
||||||
|
# Possible values are: NO, YES and FAIL_ON_WARNINGS.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
WARN_AS_ERROR = NO
|
WARN_AS_ERROR = NO
|
||||||
@ -799,7 +857,10 @@ WARN_FORMAT = "$file:$line: $text"
|
|||||||
|
|
||||||
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
|
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
|
||||||
# messages should be written. If left blank the output is written to standard
|
# messages should be written. If left blank the output is written to standard
|
||||||
# error (stderr).
|
# error (stderr). In case the file specified cannot be opened for writing the
|
||||||
|
# warning and error messages are written to standard error. When as file - is
|
||||||
|
# specified the warning and error messages are written to standard output
|
||||||
|
# (stdout).
|
||||||
|
|
||||||
WARN_LOGFILE =
|
WARN_LOGFILE =
|
||||||
|
|
||||||
@ -820,8 +881,8 @@ INPUT = ../src \
|
|||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||||
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
||||||
# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
|
# documentation (see:
|
||||||
# possible encodings.
|
# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
|
||||||
# The default value is: UTF-8.
|
# The default value is: UTF-8.
|
||||||
|
|
||||||
INPUT_ENCODING = UTF-8
|
INPUT_ENCODING = UTF-8
|
||||||
@ -834,11 +895,15 @@ INPUT_ENCODING = UTF-8
|
|||||||
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||||
# read by doxygen.
|
# read by doxygen.
|
||||||
#
|
#
|
||||||
|
# Note the list of default checked file patterns might differ from the list of
|
||||||
|
# default file extension mappings.
|
||||||
|
#
|
||||||
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
||||||
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
||||||
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
|
# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
|
||||||
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
|
# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
|
||||||
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
|
# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
|
||||||
|
# *.vhdl, *.ucf, *.qsf and *.ice.
|
||||||
|
|
||||||
FILE_PATTERNS = *.php
|
FILE_PATTERNS = *.php
|
||||||
|
|
||||||
@ -883,7 +948,7 @@ EXCLUDE_PATTERNS = */bin/* \
|
|||||||
# (namespaces, classes, functions, etc.) that should be excluded from the
|
# (namespaces, classes, functions, etc.) that should be excluded from the
|
||||||
# output. The symbol name can be a fully qualified name, a word, or if the
|
# output. The symbol name can be a fully qualified name, a word, or if the
|
||||||
# wildcard * is used, a substring. Examples: ANamespace, AClass,
|
# wildcard * is used, a substring. Examples: ANamespace, AClass,
|
||||||
# AClass::ANamespace, ANamespace::*Test
|
# ANamespace::AClass, ANamespace::*Test
|
||||||
#
|
#
|
||||||
# Note that the wildcards are matched against the file with absolute path, so to
|
# Note that the wildcards are matched against the file with absolute path, so to
|
||||||
# exclude all test directories use the pattern */test/*
|
# exclude all test directories use the pattern */test/*
|
||||||
@ -1059,16 +1124,24 @@ USE_HTAGS = NO
|
|||||||
VERBATIM_HEADERS = YES
|
VERBATIM_HEADERS = YES
|
||||||
|
|
||||||
# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
|
# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
|
||||||
# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
|
# clang parser (see:
|
||||||
# cost of reduced performance. This can be particularly helpful with template
|
# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
|
||||||
# rich C++ code for which doxygen's built-in parser lacks the necessary type
|
# performance. This can be particularly helpful with template rich C++ code for
|
||||||
# information.
|
# which doxygen's built-in parser lacks the necessary type information.
|
||||||
# Note: The availability of this option depends on whether or not doxygen was
|
# Note: The availability of this option depends on whether or not doxygen was
|
||||||
# generated with the -Duse_libclang=ON option for CMake.
|
# generated with the -Duse_libclang=ON option for CMake.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
CLANG_ASSISTED_PARSING = NO
|
CLANG_ASSISTED_PARSING = NO
|
||||||
|
|
||||||
|
# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS
|
||||||
|
# tag is set to YES then doxygen will add the directory of each input to the
|
||||||
|
# include path.
|
||||||
|
# The default value is: YES.
|
||||||
|
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
|
||||||
|
|
||||||
|
CLANG_ADD_INC_PATHS = YES
|
||||||
|
|
||||||
# If clang assisted parsing is enabled you can provide the compiler with command
|
# If clang assisted parsing is enabled you can provide the compiler with command
|
||||||
# line options that you would normally use when invoking the compiler. Note that
|
# line options that you would normally use when invoking the compiler. Note that
|
||||||
# the include paths will already be set by doxygen for the files and directories
|
# the include paths will already be set by doxygen for the files and directories
|
||||||
@ -1078,10 +1151,13 @@ CLANG_ASSISTED_PARSING = NO
|
|||||||
CLANG_OPTIONS =
|
CLANG_OPTIONS =
|
||||||
|
|
||||||
# If clang assisted parsing is enabled you can provide the clang parser with the
|
# If clang assisted parsing is enabled you can provide the clang parser with the
|
||||||
# path to the compilation database (see:
|
# path to the directory containing a file called compile_commands.json. This
|
||||||
# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files
|
# file is the compilation database (see:
|
||||||
# were built. This is equivalent to specifying the "-p" option to a clang tool,
|
# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
|
||||||
# such as clang-check. These options will then be passed to the parser.
|
# options used when the source files were built. This is equivalent to
|
||||||
|
# specifying the -p option to a clang tool, such as clang-check. These options
|
||||||
|
# will then be passed to the parser. Any options specified with CLANG_OPTIONS
|
||||||
|
# will be added as well.
|
||||||
# Note: The availability of this option depends on whether or not doxygen was
|
# Note: The availability of this option depends on whether or not doxygen was
|
||||||
# generated with the -Duse_libclang=ON option for CMake.
|
# generated with the -Duse_libclang=ON option for CMake.
|
||||||
|
|
||||||
@ -1098,13 +1174,6 @@ CLANG_DATABASE_PATH =
|
|||||||
|
|
||||||
ALPHABETICAL_INDEX = YES
|
ALPHABETICAL_INDEX = YES
|
||||||
|
|
||||||
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
|
|
||||||
# which the alphabetical index list will be split.
|
|
||||||
# Minimum value: 1, maximum value: 20, default value: 5.
|
|
||||||
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
|
|
||||||
|
|
||||||
COLS_IN_ALPHA_INDEX = 5
|
|
||||||
|
|
||||||
# In case all classes in a project start with a common prefix, all classes will
|
# In case all classes in a project start with a common prefix, all classes will
|
||||||
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
|
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
|
||||||
# can be used to specify a prefix (or a list of prefixes) that should be ignored
|
# can be used to specify a prefix (or a list of prefixes) that should be ignored
|
||||||
@ -1204,7 +1273,7 @@ HTML_EXTRA_FILES =
|
|||||||
|
|
||||||
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
|
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
|
||||||
# will adjust the colors in the style sheet and background images according to
|
# will adjust the colors in the style sheet and background images according to
|
||||||
# this color. Hue is specified as an angle on a colorwheel, see
|
# this color. Hue is specified as an angle on a color-wheel, see
|
||||||
# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
|
# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
|
||||||
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
|
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
|
||||||
# purple, and 360 is red again.
|
# purple, and 360 is red again.
|
||||||
@ -1214,7 +1283,7 @@ HTML_EXTRA_FILES =
|
|||||||
HTML_COLORSTYLE_HUE = 220
|
HTML_COLORSTYLE_HUE = 220
|
||||||
|
|
||||||
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
|
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
|
||||||
# in the HTML output. For a value of 0 the output will use grayscales only. A
|
# in the HTML output. For a value of 0 the output will use gray-scales only. A
|
||||||
# value of 255 will produce the most vivid colors.
|
# value of 255 will produce the most vivid colors.
|
||||||
# Minimum value: 0, maximum value: 255, default value: 100.
|
# Minimum value: 0, maximum value: 255, default value: 100.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
@ -1239,13 +1308,13 @@ HTML_COLORSTYLE_GAMMA = 80
|
|||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
HTML_TIMESTAMP = YES
|
HTML_TIMESTAMP = NO
|
||||||
|
|
||||||
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
|
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
|
||||||
# documentation will contain a main index with vertical navigation menus that
|
# documentation will contain a main index with vertical navigation menus that
|
||||||
# are dynamically created via Javascript. If disabled, the navigation index will
|
# are dynamically created via JavaScript. If disabled, the navigation index will
|
||||||
# consists of multiple levels of tabs that are statically embedded in every HTML
|
# consists of multiple levels of tabs that are statically embedded in every HTML
|
||||||
# page. Disable this option to support browsers that do not have Javascript,
|
# page. Disable this option to support browsers that do not have JavaScript,
|
||||||
# like the Qt help browser.
|
# like the Qt help browser.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
@ -1275,10 +1344,11 @@ HTML_INDEX_NUM_ENTRIES = 100
|
|||||||
|
|
||||||
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
|
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
|
||||||
# generated that can be used as input for Apple's Xcode 3 integrated development
|
# generated that can be used as input for Apple's Xcode 3 integrated development
|
||||||
# environment (see: https://developer.apple.com/xcode/), introduced with OSX
|
# environment (see:
|
||||||
# 10.5 (Leopard). To create a documentation set, doxygen will generate a
|
# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
|
||||||
# Makefile in the HTML output directory. Running make will produce the docset in
|
# create a documentation set, doxygen will generate a Makefile in the HTML
|
||||||
# that directory and running make install will install the docset in
|
# output directory. Running make will produce the docset in that directory and
|
||||||
|
# running make install will install the docset in
|
||||||
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
|
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
|
||||||
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
|
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
|
||||||
# genXcode/_index.html for more information.
|
# genXcode/_index.html for more information.
|
||||||
@ -1295,6 +1365,13 @@ GENERATE_DOCSET = NO
|
|||||||
|
|
||||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||||
|
|
||||||
|
# This tag determines the URL of the docset feed. A documentation feed provides
|
||||||
|
# an umbrella under which multiple documentation sets from a single provider
|
||||||
|
# (such as a company or product suite) can be grouped.
|
||||||
|
# This tag requires that the tag GENERATE_DOCSET is set to YES.
|
||||||
|
|
||||||
|
DOCSET_FEEDURL =
|
||||||
|
|
||||||
# This tag specifies a string that should uniquely identify the documentation
|
# This tag specifies a string that should uniquely identify the documentation
|
||||||
# set bundle. This should be a reverse domain-name style string, e.g.
|
# set bundle. This should be a reverse domain-name style string, e.g.
|
||||||
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
|
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
|
||||||
@ -1320,8 +1397,12 @@ DOCSET_PUBLISHER_NAME = Publisher
|
|||||||
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
|
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
|
||||||
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
|
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
|
||||||
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
|
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
|
||||||
# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
|
# on Windows. In the beginning of 2021 Microsoft took the original page, with
|
||||||
# Windows.
|
# a.o. the download links, offline the HTML help workshop was already many years
|
||||||
|
# in maintenance mode). You can download the HTML help workshop from the web
|
||||||
|
# archives at Installation executable (see:
|
||||||
|
# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
|
||||||
|
# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
|
||||||
#
|
#
|
||||||
# The HTML Help Workshop contains a compiler that can convert all HTML output
|
# The HTML Help Workshop contains a compiler that can convert all HTML output
|
||||||
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
|
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
|
||||||
@ -1351,7 +1432,7 @@ CHM_FILE =
|
|||||||
HHC_LOCATION =
|
HHC_LOCATION =
|
||||||
|
|
||||||
# The GENERATE_CHI flag controls if a separate .chi index file is generated
|
# The GENERATE_CHI flag controls if a separate .chi index file is generated
|
||||||
# (YES) or that it should be included in the master .chm file (NO).
|
# (YES) or that it should be included in the main .chm file (NO).
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||||
|
|
||||||
@ -1396,7 +1477,8 @@ QCH_FILE =
|
|||||||
|
|
||||||
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
|
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
|
||||||
# Project output. For more information please see Qt Help Project / Namespace
|
# Project output. For more information please see Qt Help Project / Namespace
|
||||||
# (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
# (see:
|
||||||
|
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
||||||
# The default value is: org.doxygen.Project.
|
# The default value is: org.doxygen.Project.
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
@ -1404,8 +1486,8 @@ QHP_NAMESPACE = org.doxygen.Project
|
|||||||
|
|
||||||
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
|
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
|
||||||
# Help Project output. For more information please see Qt Help Project / Virtual
|
# Help Project output. For more information please see Qt Help Project / Virtual
|
||||||
# Folders (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
|
# Folders (see:
|
||||||
# folders).
|
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
|
||||||
# The default value is: doc.
|
# The default value is: doc.
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
@ -1413,30 +1495,30 @@ QHP_VIRTUAL_FOLDER = doc
|
|||||||
|
|
||||||
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
|
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
|
||||||
# filter to add. For more information please see Qt Help Project / Custom
|
# filter to add. For more information please see Qt Help Project / Custom
|
||||||
# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
# Filters (see:
|
||||||
# filters).
|
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
QHP_CUST_FILTER_NAME =
|
QHP_CUST_FILTER_NAME =
|
||||||
|
|
||||||
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
|
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
|
||||||
# custom filter to add. For more information please see Qt Help Project / Custom
|
# custom filter to add. For more information please see Qt Help Project / Custom
|
||||||
# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
# Filters (see:
|
||||||
# filters).
|
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
QHP_CUST_FILTER_ATTRS =
|
QHP_CUST_FILTER_ATTRS =
|
||||||
|
|
||||||
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
|
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
|
||||||
# project's filter section matches. Qt Help Project / Filter Attributes (see:
|
# project's filter section matches. Qt Help Project / Filter Attributes (see:
|
||||||
# http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
|
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
QHP_SECT_FILTER_ATTRS =
|
QHP_SECT_FILTER_ATTRS =
|
||||||
|
|
||||||
# The QHG_LOCATION tag can be used to specify the location of Qt's
|
# The QHG_LOCATION tag can be used to specify the location (absolute path
|
||||||
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
|
# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
|
||||||
# generated .qhp file.
|
# run qhelpgenerator on the generated .qhp file.
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
QHG_LOCATION =
|
QHG_LOCATION =
|
||||||
@ -1479,16 +1561,28 @@ DISABLE_INDEX = NO
|
|||||||
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
|
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
|
||||||
# (i.e. any modern browser). Windows users are probably better off using the
|
# (i.e. any modern browser). Windows users are probably better off using the
|
||||||
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
|
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
|
||||||
# further fine-tune the look of the index. As an example, the default style
|
# further fine tune the look of the index (see "Fine-tuning the output"). As an
|
||||||
# sheet generated by doxygen has an example that shows how to put an image at
|
# example, the default style sheet generated by doxygen has an example that
|
||||||
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
|
# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
|
||||||
# the same information as the tab index, you could consider setting
|
# Since the tree basically has the same information as the tab index, you could
|
||||||
# DISABLE_INDEX to YES when enabling this option.
|
# consider setting DISABLE_INDEX to YES when enabling this option.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
GENERATE_TREEVIEW = YES
|
GENERATE_TREEVIEW = YES
|
||||||
|
|
||||||
|
# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
|
||||||
|
# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
|
||||||
|
# area (value NO) or if it should extend to the full height of the window (value
|
||||||
|
# YES). Setting this to YES gives a layout similar to
|
||||||
|
# https://docs.readthedocs.io with more room for contents, but less room for the
|
||||||
|
# project logo, title, and description. If either GENERATE_TREEVIEW or
|
||||||
|
# DISABLE_INDEX is set to NO, this option has no effect.
|
||||||
|
# The default value is: NO.
|
||||||
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
|
FULL_SIDEBAR = NO
|
||||||
|
|
||||||
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
|
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
|
||||||
# doxygen will group on one line in the generated HTML documentation.
|
# doxygen will group on one line in the generated HTML documentation.
|
||||||
#
|
#
|
||||||
@ -1513,6 +1607,24 @@ TREEVIEW_WIDTH = 250
|
|||||||
|
|
||||||
EXT_LINKS_IN_WINDOW = NO
|
EXT_LINKS_IN_WINDOW = NO
|
||||||
|
|
||||||
|
# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
|
||||||
|
# addresses.
|
||||||
|
# The default value is: YES.
|
||||||
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
|
OBFUSCATE_EMAILS = YES
|
||||||
|
|
||||||
|
# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
|
||||||
|
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
|
||||||
|
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
|
||||||
|
# the HTML output. These images will generally look nicer at scaled resolutions.
|
||||||
|
# Possible values are: png (the default) and svg (looks nicer but requires the
|
||||||
|
# pdf2svg or inkscape tool).
|
||||||
|
# The default value is: png.
|
||||||
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
|
HTML_FORMULA_FORMAT = png
|
||||||
|
|
||||||
# Use this tag to change the font size of LaTeX formulas included as images in
|
# Use this tag to change the font size of LaTeX formulas included as images in
|
||||||
# the HTML documentation. When you change the font size after a successful
|
# the HTML documentation. When you change the font size after a successful
|
||||||
# doxygen run you need to manually remove any form_*.png images from the HTML
|
# doxygen run you need to manually remove any form_*.png images from the HTML
|
||||||
@ -1533,8 +1645,14 @@ FORMULA_FONTSIZE = 10
|
|||||||
|
|
||||||
FORMULA_TRANSPARENT = YES
|
FORMULA_TRANSPARENT = YES
|
||||||
|
|
||||||
|
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
|
||||||
|
# to create new LaTeX commands to be used in formulas as building blocks. See
|
||||||
|
# the section "Including formulas" for details.
|
||||||
|
|
||||||
|
FORMULA_MACROFILE =
|
||||||
|
|
||||||
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
|
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
|
||||||
# https://www.mathjax.org) which uses client side Javascript for the rendering
|
# https://www.mathjax.org) which uses client side JavaScript for the rendering
|
||||||
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
|
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
|
||||||
# installed or if you want to formulas look prettier in the HTML output. When
|
# installed or if you want to formulas look prettier in the HTML output. When
|
||||||
# enabled you may also need to install MathJax separately and configure the path
|
# enabled you may also need to install MathJax separately and configure the path
|
||||||
@ -1544,11 +1662,29 @@ FORMULA_TRANSPARENT = YES
|
|||||||
|
|
||||||
USE_MATHJAX = YES
|
USE_MATHJAX = YES
|
||||||
|
|
||||||
|
# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
|
||||||
|
# Note that the different versions of MathJax have different requirements with
|
||||||
|
# regards to the different settings, so it is possible that also other MathJax
|
||||||
|
# settings have to be changed when switching between the different MathJax
|
||||||
|
# versions.
|
||||||
|
# Possible values are: MathJax_2 and MathJax_3.
|
||||||
|
# The default value is: MathJax_2.
|
||||||
|
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||||
|
|
||||||
|
MATHJAX_VERSION = MathJax_2
|
||||||
|
|
||||||
# When MathJax is enabled you can set the default output format to be used for
|
# When MathJax is enabled you can set the default output format to be used for
|
||||||
# the MathJax output. See the MathJax site (see:
|
# the MathJax output. For more details about the output format see MathJax
|
||||||
# http://docs.mathjax.org/en/latest/output.html) for more details.
|
# version 2 (see:
|
||||||
|
# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
|
||||||
|
# (see:
|
||||||
|
# http://docs.mathjax.org/en/latest/web/components/output.html).
|
||||||
# Possible values are: HTML-CSS (which is slower, but has the best
|
# Possible values are: HTML-CSS (which is slower, but has the best
|
||||||
# compatibility), NativeMML (i.e. MathML) and SVG.
|
# compatibility. This is the name for Mathjax version 2, for MathJax version 3
|
||||||
|
# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
|
||||||
|
# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
|
||||||
|
# is the name for Mathjax version 3, for MathJax version 2 this will be
|
||||||
|
# translated into HTML-CSS) and SVG.
|
||||||
# The default value is: HTML-CSS.
|
# The default value is: HTML-CSS.
|
||||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||||
|
|
||||||
@ -1561,22 +1697,29 @@ MATHJAX_FORMAT = HTML-CSS
|
|||||||
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
|
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
|
||||||
# Content Delivery Network so you can quickly see the result without installing
|
# Content Delivery Network so you can quickly see the result without installing
|
||||||
# MathJax. However, it is strongly recommended to install a local copy of
|
# MathJax. However, it is strongly recommended to install a local copy of
|
||||||
# MathJax from https://www.mathjax.org before deployment.
|
# MathJax from https://www.mathjax.org before deployment. The default value is:
|
||||||
# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
|
# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
|
||||||
|
# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
|
||||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||||
|
|
||||||
MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest
|
MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest
|
||||||
|
|
||||||
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
|
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
|
||||||
# extension names that should be enabled during MathJax rendering. For example
|
# extension names that should be enabled during MathJax rendering. For example
|
||||||
|
# for MathJax version 2 (see
|
||||||
|
# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
|
||||||
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
|
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
|
||||||
|
# For example for MathJax version 3 (see
|
||||||
|
# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
|
||||||
|
# MATHJAX_EXTENSIONS = ams
|
||||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||||
|
|
||||||
MATHJAX_EXTENSIONS =
|
MATHJAX_EXTENSIONS =
|
||||||
|
|
||||||
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
|
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
|
||||||
# of code that will be used on startup of the MathJax code. See the MathJax site
|
# of code that will be used on startup of the MathJax code. See the MathJax site
|
||||||
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
|
# (see:
|
||||||
|
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
|
||||||
# example see the documentation.
|
# example see the documentation.
|
||||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||||
|
|
||||||
@ -1604,7 +1747,7 @@ MATHJAX_CODEFILE =
|
|||||||
SEARCHENGINE = YES
|
SEARCHENGINE = YES
|
||||||
|
|
||||||
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
||||||
# implemented using a web server instead of a web client using Javascript. There
|
# implemented using a web server instead of a web client using JavaScript. There
|
||||||
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
|
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
|
||||||
# setting. When disabled, doxygen will generate a PHP script for searching and
|
# setting. When disabled, doxygen will generate a PHP script for searching and
|
||||||
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
|
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
|
||||||
@ -1623,7 +1766,8 @@ SERVER_BASED_SEARCH = NO
|
|||||||
#
|
#
|
||||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||||
# (doxysearch.cgi) which are based on the open source search engine library
|
# (doxysearch.cgi) which are based on the open source search engine library
|
||||||
# Xapian (see: https://xapian.org/).
|
# Xapian (see:
|
||||||
|
# https://xapian.org/).
|
||||||
#
|
#
|
||||||
# See the section "External Indexing and Searching" for details.
|
# See the section "External Indexing and Searching" for details.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
@ -1636,8 +1780,9 @@ EXTERNAL_SEARCH = NO
|
|||||||
#
|
#
|
||||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||||
# (doxysearch.cgi) which are based on the open source search engine library
|
# (doxysearch.cgi) which are based on the open source search engine library
|
||||||
# Xapian (see: https://xapian.org/). See the section "External Indexing and
|
# Xapian (see:
|
||||||
# Searching" for details.
|
# https://xapian.org/). See the section "External Indexing and Searching" for
|
||||||
|
# details.
|
||||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||||
|
|
||||||
SEARCHENGINE_URL =
|
SEARCHENGINE_URL =
|
||||||
@ -1708,10 +1853,11 @@ LATEX_CMD_NAME = latex
|
|||||||
MAKEINDEX_CMD_NAME = makeindex
|
MAKEINDEX_CMD_NAME = makeindex
|
||||||
|
|
||||||
# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
|
# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
|
||||||
# generate index for LaTeX.
|
# generate index for LaTeX. In case there is no backslash (\) as first character
|
||||||
|
# it will be automatically added in the LaTeX code.
|
||||||
# Note: This tag is used in the generated output file (.tex).
|
# Note: This tag is used in the generated output file (.tex).
|
||||||
# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
|
# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
|
||||||
# The default value is: \makeindex.
|
# The default value is: makeindex.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
LATEX_MAKEINDEX_CMD = \makeindex
|
LATEX_MAKEINDEX_CMD = \makeindex
|
||||||
@ -1745,29 +1891,31 @@ PAPER_TYPE = a4
|
|||||||
|
|
||||||
EXTRA_PACKAGES =
|
EXTRA_PACKAGES =
|
||||||
|
|
||||||
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
|
# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
|
||||||
# generated LaTeX document. The header should contain everything until the first
|
# the generated LaTeX document. The header should contain everything until the
|
||||||
# chapter. If it is left blank doxygen will generate a standard header. See
|
# first chapter. If it is left blank doxygen will generate a standard header. It
|
||||||
# section "Doxygen usage" for information on how to let doxygen write the
|
# is highly recommended to start with a default header using
|
||||||
# default header to a separate file.
|
# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
|
||||||
|
# and then modify the file new_header.tex. See also section "Doxygen usage" for
|
||||||
|
# information on how to generate the default header that doxygen normally uses.
|
||||||
#
|
#
|
||||||
# Note: Only use a user-defined header if you know what you are doing! The
|
# Note: Only use a user-defined header if you know what you are doing!
|
||||||
# following commands have a special meaning inside the header: $title,
|
# Note: The header is subject to change so you typically have to regenerate the
|
||||||
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
|
# default header when upgrading to a newer version of doxygen. The following
|
||||||
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
|
# commands have a special meaning inside the header (and footer): For a
|
||||||
# string, for the replacement values of the other commands the user is referred
|
# description of the possible markers and block names see the documentation.
|
||||||
# to HTML_HEADER.
|
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
LATEX_HEADER =
|
LATEX_HEADER =
|
||||||
|
|
||||||
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
|
# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
|
||||||
# generated LaTeX document. The footer should contain everything after the last
|
# the generated LaTeX document. The footer should contain everything after the
|
||||||
# chapter. If it is left blank doxygen will generate a standard footer. See
|
# last chapter. If it is left blank doxygen will generate a standard footer. See
|
||||||
# LATEX_HEADER for more information on how to generate a default footer and what
|
# LATEX_HEADER for more information on how to generate a default footer and what
|
||||||
# special commands can be used inside the footer.
|
# special commands can be used inside the footer. See also section "Doxygen
|
||||||
#
|
# usage" for information on how to generate the default footer that doxygen
|
||||||
# Note: Only use a user-defined footer if you know what you are doing!
|
# normally uses. Note: Only use a user-defined footer if you know what you are
|
||||||
|
# doing!
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
LATEX_FOOTER =
|
LATEX_FOOTER =
|
||||||
@ -1800,9 +1948,11 @@ LATEX_EXTRA_FILES =
|
|||||||
|
|
||||||
PDF_HYPERLINKS = YES
|
PDF_HYPERLINKS = YES
|
||||||
|
|
||||||
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
|
# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
|
||||||
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
|
# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
|
||||||
# higher quality PDF documentation.
|
# files. Set this option to YES, to get a higher quality PDF documentation.
|
||||||
|
#
|
||||||
|
# See also section LATEX_CMD_NAME for selecting the engine.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
@ -1810,8 +1960,7 @@ USE_PDFLATEX = YES
|
|||||||
|
|
||||||
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
|
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
|
||||||
# command to the generated LaTeX files. This will instruct LaTeX to keep running
|
# command to the generated LaTeX files. This will instruct LaTeX to keep running
|
||||||
# if errors occur, instead of asking the user for help. This option is also used
|
# if errors occur, instead of asking the user for help.
|
||||||
# when generating formulas in HTML.
|
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
@ -1824,16 +1973,6 @@ LATEX_BATCHMODE = NO
|
|||||||
|
|
||||||
LATEX_HIDE_INDICES = NO
|
LATEX_HIDE_INDICES = NO
|
||||||
|
|
||||||
# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
|
|
||||||
# code with syntax highlighting in the LaTeX output.
|
|
||||||
#
|
|
||||||
# Note that which sources are shown also depends on other settings such as
|
|
||||||
# SOURCE_BROWSER.
|
|
||||||
# The default value is: NO.
|
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
|
||||||
|
|
||||||
LATEX_SOURCE_CODE = NO
|
|
||||||
|
|
||||||
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
|
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
|
||||||
# bibliography, e.g. plainnat, or ieeetr. See
|
# bibliography, e.g. plainnat, or ieeetr. See
|
||||||
# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
|
# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
|
||||||
@ -1914,16 +2053,6 @@ RTF_STYLESHEET_FILE =
|
|||||||
|
|
||||||
RTF_EXTENSIONS_FILE =
|
RTF_EXTENSIONS_FILE =
|
||||||
|
|
||||||
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
|
|
||||||
# with syntax highlighting in the RTF output.
|
|
||||||
#
|
|
||||||
# Note that which sources are shown also depends on other settings such as
|
|
||||||
# SOURCE_BROWSER.
|
|
||||||
# The default value is: NO.
|
|
||||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
|
||||||
|
|
||||||
RTF_SOURCE_CODE = NO
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options related to the man page output
|
# Configuration options related to the man page output
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
@ -2020,15 +2149,6 @@ GENERATE_DOCBOOK = NO
|
|||||||
|
|
||||||
DOCBOOK_OUTPUT = docbook
|
DOCBOOK_OUTPUT = docbook
|
||||||
|
|
||||||
# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
|
|
||||||
# program listings (including syntax highlighting and cross-referencing
|
|
||||||
# information) to the DOCBOOK output. Note that enabling this will significantly
|
|
||||||
# increase the size of the DOCBOOK output.
|
|
||||||
# The default value is: NO.
|
|
||||||
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
|
|
||||||
|
|
||||||
DOCBOOK_PROGRAMLISTING = NO
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options for the AutoGen Definitions output
|
# Configuration options for the AutoGen Definitions output
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
@ -2203,34 +2323,10 @@ EXTERNAL_GROUPS = YES
|
|||||||
|
|
||||||
EXTERNAL_PAGES = YES
|
EXTERNAL_PAGES = YES
|
||||||
|
|
||||||
# The PERL_PATH should be the absolute path and name of the perl script
|
|
||||||
# interpreter (i.e. the result of 'which perl').
|
|
||||||
# The default file (with absolute path) is: /usr/bin/perl.
|
|
||||||
|
|
||||||
PERL_PATH = /usr/bin/perl
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options related to the dot tool
|
# Configuration options related to the dot tool
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
|
|
||||||
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
|
|
||||||
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
|
|
||||||
# disabled, but it is recommended to install and use dot, since it yields more
|
|
||||||
# powerful graphs.
|
|
||||||
# The default value is: YES.
|
|
||||||
|
|
||||||
CLASS_DIAGRAMS = NO
|
|
||||||
|
|
||||||
# You can define message sequence charts within doxygen comments using the \msc
|
|
||||||
# command. Doxygen will then run the mscgen tool (see:
|
|
||||||
# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
|
|
||||||
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
|
|
||||||
# the mscgen tool resides. If left empty the tool is assumed to be found in the
|
|
||||||
# default search path.
|
|
||||||
|
|
||||||
MSCGEN_PATH =
|
|
||||||
|
|
||||||
# You can include diagrams made with dia in doxygen documentation. Doxygen will
|
# You can include diagrams made with dia in doxygen documentation. Doxygen will
|
||||||
# then run dia to produce the diagram and insert it in the documentation. The
|
# then run dia to produce the diagram and insert it in the documentation. The
|
||||||
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
|
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
|
||||||
@ -2287,11 +2383,14 @@ DOT_FONTSIZE = 10
|
|||||||
|
|
||||||
DOT_FONTPATH =
|
DOT_FONTPATH =
|
||||||
|
|
||||||
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
|
# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
|
||||||
# each documented class showing the direct and indirect inheritance relations.
|
# graph for each documented class showing the direct and indirect inheritance
|
||||||
# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
|
# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
|
||||||
|
# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
|
||||||
|
# to TEXT the direct and indirect inheritance relations will be shown as texts /
|
||||||
|
# links.
|
||||||
|
# Possible values are: NO, YES, TEXT and GRAPH.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
|
||||||
|
|
||||||
CLASS_GRAPH = YES
|
CLASS_GRAPH = YES
|
||||||
|
|
||||||
@ -2328,10 +2427,32 @@ UML_LOOK = YES
|
|||||||
# but if the number exceeds 15, the total amount of fields shown is limited to
|
# but if the number exceeds 15, the total amount of fields shown is limited to
|
||||||
# 10.
|
# 10.
|
||||||
# Minimum value: 0, maximum value: 100, default value: 10.
|
# Minimum value: 0, maximum value: 100, default value: 10.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
# This tag requires that the tag UML_LOOK is set to YES.
|
||||||
|
|
||||||
UML_LIMIT_NUM_FIELDS = 10
|
UML_LIMIT_NUM_FIELDS = 10
|
||||||
|
|
||||||
|
# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
|
||||||
|
# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
|
||||||
|
# tag is set to YES, doxygen will add type and arguments for attributes and
|
||||||
|
# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
|
||||||
|
# will not generate fields with class member information in the UML graphs. The
|
||||||
|
# class diagrams will look similar to the default class diagrams but using UML
|
||||||
|
# notation for the relationships.
|
||||||
|
# Possible values are: NO, YES and NONE.
|
||||||
|
# The default value is: NO.
|
||||||
|
# This tag requires that the tag UML_LOOK is set to YES.
|
||||||
|
|
||||||
|
DOT_UML_DETAILS = NO
|
||||||
|
|
||||||
|
# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
|
||||||
|
# to display on a single line. If the actual line length exceeds this threshold
|
||||||
|
# significantly it will wrapped across multiple lines. Some heuristics are apply
|
||||||
|
# to avoid ugly line breaks.
|
||||||
|
# Minimum value: 0, maximum value: 1000, default value: 17.
|
||||||
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|
||||||
|
DOT_WRAP_THRESHOLD = 17
|
||||||
|
|
||||||
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
|
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
|
||||||
# collaboration graphs will show the relations between templates and their
|
# collaboration graphs will show the relations between templates and their
|
||||||
# instances.
|
# instances.
|
||||||
@ -2398,6 +2519,13 @@ GRAPHICAL_HIERARCHY = YES
|
|||||||
|
|
||||||
DIRECTORY_GRAPH = YES
|
DIRECTORY_GRAPH = YES
|
||||||
|
|
||||||
|
# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
|
||||||
|
# of child directories generated in directory dependency graphs by dot.
|
||||||
|
# Minimum value: 1, maximum value: 25, default value: 1.
|
||||||
|
# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
|
||||||
|
|
||||||
|
DIR_GRAPH_MAX_DEPTH = 1
|
||||||
|
|
||||||
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
|
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
|
||||||
# generated by dot. For an explanation of the image formats see the section
|
# generated by dot. For an explanation of the image formats see the section
|
||||||
# output formats in the documentation of the dot tool (Graphviz (see:
|
# output formats in the documentation of the dot tool (Graphviz (see:
|
||||||
@ -2451,10 +2579,10 @@ MSCFILE_DIRS =
|
|||||||
DIAFILE_DIRS =
|
DIAFILE_DIRS =
|
||||||
|
|
||||||
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
|
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
|
||||||
# path where java can find the plantuml.jar file. If left blank, it is assumed
|
# path where java can find the plantuml.jar file or to the filename of jar file
|
||||||
# PlantUML is not used or called during a preprocessing step. Doxygen will
|
# to be used. If left blank, it is assumed PlantUML is not used or called during
|
||||||
# generate a warning when it encounters a \startuml command in this case and
|
# a preprocessing step. Doxygen will generate a warning when it encounters a
|
||||||
# will not generate output for the diagram.
|
# \startuml command in this case and will not generate output for the diagram.
|
||||||
|
|
||||||
PLANTUML_JAR_PATH =
|
PLANTUML_JAR_PATH =
|
||||||
|
|
||||||
@ -2516,14 +2644,18 @@ DOT_MULTI_TARGETS = YES
|
|||||||
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
|
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
|
||||||
# explaining the meaning of the various boxes and arrows in the dot generated
|
# explaining the meaning of the various boxes and arrows in the dot generated
|
||||||
# graphs.
|
# graphs.
|
||||||
|
# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
|
||||||
|
# graphical representation for inheritance and collaboration diagrams is used.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|
||||||
GENERATE_LEGEND = YES
|
GENERATE_LEGEND = YES
|
||||||
|
|
||||||
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
|
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
|
||||||
# files that are used to generate the various graphs.
|
# files that are used to generate the various graphs.
|
||||||
|
#
|
||||||
|
# Note: This setting is not only used for dot files but also for msc temporary
|
||||||
|
# files.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
|
||||||
|
|
||||||
DOT_CLEANUP = YES
|
DOT_CLEANUP = YES
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
includes:
|
includes:
|
||||||
- tests/phpstan/configs/actual-problems.neon
|
- tests/phpstan/configs/actual-problems.neon
|
||||||
- tests/phpstan/configs/check-explicit-mixed-baseline.neon
|
|
||||||
- tests/phpstan/configs/gc-hacks.neon
|
- tests/phpstan/configs/gc-hacks.neon
|
||||||
- tests/phpstan/configs/impossible-generics.neon
|
- tests/phpstan/configs/impossible-generics.neon
|
||||||
- tests/phpstan/configs/l7-baseline.neon
|
|
||||||
- tests/phpstan/configs/l8-baseline.neon
|
|
||||||
- tests/phpstan/configs/php-bugs.neon
|
- tests/phpstan/configs/php-bugs.neon
|
||||||
- tests/phpstan/configs/phpstan-bugs.neon
|
- tests/phpstan/configs/phpstan-bugs.neon
|
||||||
- tests/phpstan/configs/pthreads-bugs.neon
|
|
||||||
- tests/phpstan/configs/runtime-type-checks.neon
|
- tests/phpstan/configs/runtime-type-checks.neon
|
||||||
- tests/phpstan/configs/spl-fixed-array-sucks.neon
|
- tests/phpstan/configs/spl-fixed-array-sucks.neon
|
||||||
- vendor/phpstan/phpstan-phpunit/extension.neon
|
- vendor/phpstan/phpstan-phpunit/extension.neon
|
||||||
@ -16,11 +12,11 @@ includes:
|
|||||||
|
|
||||||
rules:
|
rules:
|
||||||
- pocketmine\phpstan\rules\DisallowEnumComparisonRule
|
- pocketmine\phpstan\rules\DisallowEnumComparisonRule
|
||||||
|
- pocketmine\phpstan\rules\UnsafeForeachArrayOfStringRule
|
||||||
# - pocketmine\phpstan\rules\ThreadedSupportedTypesRule
|
# - pocketmine\phpstan\rules\ThreadedSupportedTypesRule
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
level: 8
|
level: 9
|
||||||
checkExplicitMixed: true
|
|
||||||
checkMissingCallableSignature: true
|
checkMissingCallableSignature: true
|
||||||
treatPhpDocTypesAsCertain: false
|
treatPhpDocTypesAsCertain: false
|
||||||
bootstrapFiles:
|
bootstrapFiles:
|
||||||
@ -38,6 +34,9 @@ parameters:
|
|||||||
- tests/phpunit
|
- tests/phpunit
|
||||||
- tests/plugins/TesterPlugin
|
- tests/plugins/TesterPlugin
|
||||||
- tools
|
- tools
|
||||||
|
excludePaths:
|
||||||
|
analyseAndScan:
|
||||||
|
- build/php
|
||||||
dynamicConstantNames:
|
dynamicConstantNames:
|
||||||
- pocketmine\VersionInfo::IS_DEVELOPMENT_BUILD
|
- pocketmine\VersionInfo::IS_DEVELOPMENT_BUILD
|
||||||
- pocketmine\DEBUG
|
- pocketmine\DEBUG
|
||||||
@ -54,5 +53,5 @@ parameters:
|
|||||||
#variadics don't work for this - mixed probably shouldn't work either, but for now it does
|
#variadics don't work for this - mixed probably shouldn't work either, but for now it does
|
||||||
#what we actually need is something that accepts an infinite number of parameters, but in the absence of that,
|
#what we actually need is something that accepts an infinite number of parameters, but in the absence of that,
|
||||||
#we'll just fill it with 10 - it's very unlikely to encounter a callable with 10 parameters anyway.
|
#we'll just fill it with 10 - it's very unlikely to encounter a callable with 10 parameters anyway.
|
||||||
anyCallable: 'callable(mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed) : mixed'
|
anyCallable: 'callable(never, never, never, never, never, never, never, never, never, never) : mixed'
|
||||||
anyClosure: '\Closure(mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed) : mixed'
|
anyClosure: '\Closure(never, never, never, never, never, never, never, never, never, never) : mixed'
|
||||||
|
@ -1,4 +1,691 @@
|
|||||||
{
|
{
|
||||||
|
"-2": -2,
|
||||||
|
"-3": -3,
|
||||||
|
"-4": -4,
|
||||||
|
"-5": -5,
|
||||||
|
"-6": -6,
|
||||||
|
"-7": -7,
|
||||||
|
"-8": -8,
|
||||||
|
"-9": -9,
|
||||||
|
"-10": -10,
|
||||||
|
"-11": -11,
|
||||||
|
"-12": -12,
|
||||||
|
"-13": -13,
|
||||||
|
"-14": -14,
|
||||||
|
"-15": -15,
|
||||||
|
"-16": -16,
|
||||||
|
"-17": -17,
|
||||||
|
"-18": -18,
|
||||||
|
"-19": -19,
|
||||||
|
"-20": -20,
|
||||||
|
"-21": -21,
|
||||||
|
"-22": -22,
|
||||||
|
"-23": -23,
|
||||||
|
"-24": -24,
|
||||||
|
"-25": -25,
|
||||||
|
"-26": -26,
|
||||||
|
"-27": -27,
|
||||||
|
"-28": -28,
|
||||||
|
"-29": -29,
|
||||||
|
"-30": -30,
|
||||||
|
"-31": -31,
|
||||||
|
"-32": -32,
|
||||||
|
"-33": -33,
|
||||||
|
"-34": -34,
|
||||||
|
"-35": -35,
|
||||||
|
"-36": -36,
|
||||||
|
"-37": -37,
|
||||||
|
"-38": -38,
|
||||||
|
"-39": -39,
|
||||||
|
"-40": -40,
|
||||||
|
"-41": -41,
|
||||||
|
"-42": -42,
|
||||||
|
"-43": -43,
|
||||||
|
"-44": -44,
|
||||||
|
"-45": -45,
|
||||||
|
"-46": -46,
|
||||||
|
"-47": -47,
|
||||||
|
"-48": -48,
|
||||||
|
"-49": -49,
|
||||||
|
"-50": -50,
|
||||||
|
"-51": -51,
|
||||||
|
"-52": -52,
|
||||||
|
"-53": -53,
|
||||||
|
"-54": -54,
|
||||||
|
"-55": -55,
|
||||||
|
"-56": -56,
|
||||||
|
"-57": -57,
|
||||||
|
"-58": -58,
|
||||||
|
"-59": -59,
|
||||||
|
"-60": -60,
|
||||||
|
"-61": -61,
|
||||||
|
"-62": -62,
|
||||||
|
"-63": -63,
|
||||||
|
"-64": -64,
|
||||||
|
"-65": -65,
|
||||||
|
"-66": -66,
|
||||||
|
"-67": -67,
|
||||||
|
"-68": -68,
|
||||||
|
"-69": -69,
|
||||||
|
"-70": -70,
|
||||||
|
"-71": -71,
|
||||||
|
"-72": -72,
|
||||||
|
"-73": -73,
|
||||||
|
"-74": -74,
|
||||||
|
"-75": -75,
|
||||||
|
"-76": -76,
|
||||||
|
"-77": -77,
|
||||||
|
"-78": -78,
|
||||||
|
"-79": -79,
|
||||||
|
"-80": -80,
|
||||||
|
"-81": -81,
|
||||||
|
"-82": -82,
|
||||||
|
"-83": -83,
|
||||||
|
"-84": -84,
|
||||||
|
"-85": -85,
|
||||||
|
"-86": -86,
|
||||||
|
"-87": -87,
|
||||||
|
"-88": -88,
|
||||||
|
"-89": -89,
|
||||||
|
"-90": -90,
|
||||||
|
"-91": -91,
|
||||||
|
"-92": -92,
|
||||||
|
"-93": -93,
|
||||||
|
"-94": -94,
|
||||||
|
"-95": -95,
|
||||||
|
"-96": -96,
|
||||||
|
"-97": -97,
|
||||||
|
"-98": -98,
|
||||||
|
"-99": -99,
|
||||||
|
"-100": -100,
|
||||||
|
"-101": -101,
|
||||||
|
"-102": -102,
|
||||||
|
"-103": -103,
|
||||||
|
"-104": -104,
|
||||||
|
"-105": -105,
|
||||||
|
"-106": -106,
|
||||||
|
"-107": -107,
|
||||||
|
"-108": -108,
|
||||||
|
"-109": -109,
|
||||||
|
"-110": -110,
|
||||||
|
"-111": -111,
|
||||||
|
"-112": -112,
|
||||||
|
"-113": -113,
|
||||||
|
"-114": -114,
|
||||||
|
"-115": -115,
|
||||||
|
"-116": -116,
|
||||||
|
"-117": -117,
|
||||||
|
"-118": -118,
|
||||||
|
"-119": -119,
|
||||||
|
"-120": -120,
|
||||||
|
"-121": -121,
|
||||||
|
"-122": -122,
|
||||||
|
"-123": -123,
|
||||||
|
"-124": -124,
|
||||||
|
"-125": -125,
|
||||||
|
"-126": -126,
|
||||||
|
"-127": -127,
|
||||||
|
"-128": -128,
|
||||||
|
"-129": -129,
|
||||||
|
"-130": -130,
|
||||||
|
"-131": -131,
|
||||||
|
"-132": -132,
|
||||||
|
"-133": -133,
|
||||||
|
"-134": -134,
|
||||||
|
"-135": -135,
|
||||||
|
"-136": -136,
|
||||||
|
"-137": -137,
|
||||||
|
"-138": -138,
|
||||||
|
"-139": -139,
|
||||||
|
"-140": -140,
|
||||||
|
"-141": -141,
|
||||||
|
"-142": -142,
|
||||||
|
"-143": -143,
|
||||||
|
"-144": -144,
|
||||||
|
"-145": -145,
|
||||||
|
"-146": -146,
|
||||||
|
"-147": -147,
|
||||||
|
"-148": -148,
|
||||||
|
"-149": -149,
|
||||||
|
"-150": -150,
|
||||||
|
"-151": -151,
|
||||||
|
"-152": -152,
|
||||||
|
"-153": -153,
|
||||||
|
"-154": -154,
|
||||||
|
"-155": -155,
|
||||||
|
"-156": -156,
|
||||||
|
"-157": -157,
|
||||||
|
"-159": -159,
|
||||||
|
"-160": -160,
|
||||||
|
"-161": -161,
|
||||||
|
"-162": -162,
|
||||||
|
"-163": -163,
|
||||||
|
"-164": -164,
|
||||||
|
"-165": -165,
|
||||||
|
"-166": -166,
|
||||||
|
"-167": -167,
|
||||||
|
"-168": -168,
|
||||||
|
"-169": -169,
|
||||||
|
"-170": -170,
|
||||||
|
"-171": -171,
|
||||||
|
"-172": -172,
|
||||||
|
"-173": -173,
|
||||||
|
"-174": -174,
|
||||||
|
"-175": -175,
|
||||||
|
"-176": -176,
|
||||||
|
"-177": -177,
|
||||||
|
"-178": -178,
|
||||||
|
"-179": -179,
|
||||||
|
"-180": -180,
|
||||||
|
"-181": -181,
|
||||||
|
"-182": -182,
|
||||||
|
"-183": -183,
|
||||||
|
"-184": -184,
|
||||||
|
"-185": -185,
|
||||||
|
"-186": -186,
|
||||||
|
"-187": -187,
|
||||||
|
"-188": -188,
|
||||||
|
"-189": -189,
|
||||||
|
"-190": -190,
|
||||||
|
"-191": -191,
|
||||||
|
"-192": -192,
|
||||||
|
"-193": -193,
|
||||||
|
"-194": -194,
|
||||||
|
"-195": -195,
|
||||||
|
"-196": -196,
|
||||||
|
"-197": -197,
|
||||||
|
"-198": -198,
|
||||||
|
"-199": -199,
|
||||||
|
"-200": -200,
|
||||||
|
"-201": -201,
|
||||||
|
"-202": -202,
|
||||||
|
"-203": -203,
|
||||||
|
"-204": -204,
|
||||||
|
"-206": -206,
|
||||||
|
"-207": -207,
|
||||||
|
"-208": -208,
|
||||||
|
"-209": -209,
|
||||||
|
"-210": -210,
|
||||||
|
"-211": -211,
|
||||||
|
"-213": -213,
|
||||||
|
"-214": -214,
|
||||||
|
"0": 0,
|
||||||
|
"1": 1,
|
||||||
|
"2": 2,
|
||||||
|
"3": 3,
|
||||||
|
"4": 4,
|
||||||
|
"5": 5,
|
||||||
|
"6": 6,
|
||||||
|
"7": 7,
|
||||||
|
"8": 8,
|
||||||
|
"9": 9,
|
||||||
|
"10": 10,
|
||||||
|
"11": 11,
|
||||||
|
"12": 12,
|
||||||
|
"13": 13,
|
||||||
|
"14": 14,
|
||||||
|
"15": 15,
|
||||||
|
"16": 16,
|
||||||
|
"17": 17,
|
||||||
|
"18": 18,
|
||||||
|
"19": 19,
|
||||||
|
"20": 20,
|
||||||
|
"21": 21,
|
||||||
|
"22": 22,
|
||||||
|
"23": 23,
|
||||||
|
"24": 24,
|
||||||
|
"25": 25,
|
||||||
|
"26": 26,
|
||||||
|
"27": 27,
|
||||||
|
"28": 28,
|
||||||
|
"29": 29,
|
||||||
|
"30": 30,
|
||||||
|
"31": 31,
|
||||||
|
"32": 32,
|
||||||
|
"33": 33,
|
||||||
|
"34": 34,
|
||||||
|
"35": 35,
|
||||||
|
"36": 36,
|
||||||
|
"37": 37,
|
||||||
|
"38": 38,
|
||||||
|
"39": 39,
|
||||||
|
"40": 40,
|
||||||
|
"41": 41,
|
||||||
|
"42": 42,
|
||||||
|
"43": 43,
|
||||||
|
"44": 44,
|
||||||
|
"45": 45,
|
||||||
|
"46": 46,
|
||||||
|
"47": 47,
|
||||||
|
"48": 48,
|
||||||
|
"49": 49,
|
||||||
|
"50": 50,
|
||||||
|
"51": 51,
|
||||||
|
"52": 52,
|
||||||
|
"53": 53,
|
||||||
|
"54": 54,
|
||||||
|
"55": 55,
|
||||||
|
"56": 56,
|
||||||
|
"57": 57,
|
||||||
|
"58": 58,
|
||||||
|
"59": 59,
|
||||||
|
"60": 60,
|
||||||
|
"61": 61,
|
||||||
|
"62": 62,
|
||||||
|
"63": 63,
|
||||||
|
"64": 64,
|
||||||
|
"65": 65,
|
||||||
|
"66": 66,
|
||||||
|
"67": 67,
|
||||||
|
"68": 68,
|
||||||
|
"69": 69,
|
||||||
|
"70": 70,
|
||||||
|
"71": 71,
|
||||||
|
"72": 72,
|
||||||
|
"73": 73,
|
||||||
|
"74": 74,
|
||||||
|
"75": 75,
|
||||||
|
"76": 76,
|
||||||
|
"77": 77,
|
||||||
|
"78": 78,
|
||||||
|
"79": 79,
|
||||||
|
"80": 80,
|
||||||
|
"81": 81,
|
||||||
|
"82": 82,
|
||||||
|
"83": 83,
|
||||||
|
"84": 84,
|
||||||
|
"85": 85,
|
||||||
|
"86": 86,
|
||||||
|
"87": 87,
|
||||||
|
"88": 88,
|
||||||
|
"89": 89,
|
||||||
|
"90": 90,
|
||||||
|
"91": 91,
|
||||||
|
"92": 92,
|
||||||
|
"93": 93,
|
||||||
|
"94": 94,
|
||||||
|
"95": 95,
|
||||||
|
"96": 96,
|
||||||
|
"97": 97,
|
||||||
|
"98": 98,
|
||||||
|
"99": 99,
|
||||||
|
"100": 100,
|
||||||
|
"101": 101,
|
||||||
|
"102": 102,
|
||||||
|
"103": 103,
|
||||||
|
"104": 104,
|
||||||
|
"105": 105,
|
||||||
|
"106": 106,
|
||||||
|
"107": 107,
|
||||||
|
"108": 108,
|
||||||
|
"109": 109,
|
||||||
|
"110": 110,
|
||||||
|
"111": 111,
|
||||||
|
"112": 112,
|
||||||
|
"113": 113,
|
||||||
|
"114": 114,
|
||||||
|
"115": 115,
|
||||||
|
"116": 116,
|
||||||
|
"117": 117,
|
||||||
|
"118": 118,
|
||||||
|
"119": 119,
|
||||||
|
"120": 120,
|
||||||
|
"121": 121,
|
||||||
|
"122": 122,
|
||||||
|
"123": 123,
|
||||||
|
"124": 124,
|
||||||
|
"125": 125,
|
||||||
|
"126": 126,
|
||||||
|
"127": 127,
|
||||||
|
"128": 128,
|
||||||
|
"129": 129,
|
||||||
|
"130": 130,
|
||||||
|
"131": 131,
|
||||||
|
"132": 132,
|
||||||
|
"133": 133,
|
||||||
|
"134": 134,
|
||||||
|
"135": 135,
|
||||||
|
"136": 136,
|
||||||
|
"137": 137,
|
||||||
|
"138": 138,
|
||||||
|
"139": 139,
|
||||||
|
"140": 140,
|
||||||
|
"141": 141,
|
||||||
|
"142": 142,
|
||||||
|
"143": 143,
|
||||||
|
"144": 144,
|
||||||
|
"145": 145,
|
||||||
|
"146": 146,
|
||||||
|
"147": 147,
|
||||||
|
"148": 148,
|
||||||
|
"149": 149,
|
||||||
|
"150": 150,
|
||||||
|
"151": 151,
|
||||||
|
"152": 152,
|
||||||
|
"153": 153,
|
||||||
|
"154": 154,
|
||||||
|
"155": 155,
|
||||||
|
"156": 156,
|
||||||
|
"157": 157,
|
||||||
|
"158": 158,
|
||||||
|
"159": 159,
|
||||||
|
"160": 160,
|
||||||
|
"161": 161,
|
||||||
|
"162": 162,
|
||||||
|
"163": 163,
|
||||||
|
"164": 164,
|
||||||
|
"165": 165,
|
||||||
|
"166": 166,
|
||||||
|
"167": 167,
|
||||||
|
"168": 168,
|
||||||
|
"169": 169,
|
||||||
|
"170": 170,
|
||||||
|
"171": 171,
|
||||||
|
"172": 172,
|
||||||
|
"173": 173,
|
||||||
|
"174": 174,
|
||||||
|
"175": 175,
|
||||||
|
"176": 176,
|
||||||
|
"177": 177,
|
||||||
|
"178": 178,
|
||||||
|
"179": 179,
|
||||||
|
"180": 180,
|
||||||
|
"181": 181,
|
||||||
|
"182": 182,
|
||||||
|
"183": 183,
|
||||||
|
"184": 184,
|
||||||
|
"185": 185,
|
||||||
|
"186": 186,
|
||||||
|
"187": 187,
|
||||||
|
"188": 188,
|
||||||
|
"189": 189,
|
||||||
|
"190": 190,
|
||||||
|
"191": 191,
|
||||||
|
"192": 192,
|
||||||
|
"193": 193,
|
||||||
|
"194": 194,
|
||||||
|
"195": 195,
|
||||||
|
"196": 196,
|
||||||
|
"197": 197,
|
||||||
|
"198": 198,
|
||||||
|
"199": 199,
|
||||||
|
"200": 200,
|
||||||
|
"201": 201,
|
||||||
|
"202": 202,
|
||||||
|
"203": 203,
|
||||||
|
"204": 204,
|
||||||
|
"205": 205,
|
||||||
|
"206": 206,
|
||||||
|
"207": 207,
|
||||||
|
"208": 208,
|
||||||
|
"209": 209,
|
||||||
|
"213": 213,
|
||||||
|
"214": 214,
|
||||||
|
"215": 215,
|
||||||
|
"216": 216,
|
||||||
|
"218": 218,
|
||||||
|
"219": 219,
|
||||||
|
"220": 220,
|
||||||
|
"221": 221,
|
||||||
|
"222": 222,
|
||||||
|
"223": 223,
|
||||||
|
"224": 224,
|
||||||
|
"225": 225,
|
||||||
|
"226": 226,
|
||||||
|
"227": 227,
|
||||||
|
"228": 228,
|
||||||
|
"229": 229,
|
||||||
|
"231": 231,
|
||||||
|
"232": 232,
|
||||||
|
"233": 233,
|
||||||
|
"234": 234,
|
||||||
|
"235": 235,
|
||||||
|
"236": 236,
|
||||||
|
"237": 237,
|
||||||
|
"238": 238,
|
||||||
|
"239": 239,
|
||||||
|
"240": 240,
|
||||||
|
"241": 241,
|
||||||
|
"243": 243,
|
||||||
|
"244": 244,
|
||||||
|
"245": 245,
|
||||||
|
"246": 246,
|
||||||
|
"247": 247,
|
||||||
|
"248": 248,
|
||||||
|
"249": 249,
|
||||||
|
"250": 250,
|
||||||
|
"251": 251,
|
||||||
|
"252": 252,
|
||||||
|
"253": 253,
|
||||||
|
"254": 254,
|
||||||
|
"255": 255,
|
||||||
|
"256": 256,
|
||||||
|
"257": 257,
|
||||||
|
"258": 258,
|
||||||
|
"259": 259,
|
||||||
|
"260": 260,
|
||||||
|
"261": 261,
|
||||||
|
"262": 262,
|
||||||
|
"263": 263,
|
||||||
|
"264": 264,
|
||||||
|
"265": 265,
|
||||||
|
"266": 266,
|
||||||
|
"267": 267,
|
||||||
|
"268": 268,
|
||||||
|
"269": 269,
|
||||||
|
"270": 270,
|
||||||
|
"271": 271,
|
||||||
|
"272": 272,
|
||||||
|
"273": 273,
|
||||||
|
"274": 274,
|
||||||
|
"275": 275,
|
||||||
|
"276": 276,
|
||||||
|
"277": 277,
|
||||||
|
"278": 278,
|
||||||
|
"279": 279,
|
||||||
|
"280": 280,
|
||||||
|
"281": 281,
|
||||||
|
"282": 282,
|
||||||
|
"283": 283,
|
||||||
|
"284": 284,
|
||||||
|
"285": 285,
|
||||||
|
"286": 286,
|
||||||
|
"287": 287,
|
||||||
|
"288": 288,
|
||||||
|
"289": 289,
|
||||||
|
"290": 290,
|
||||||
|
"291": 291,
|
||||||
|
"292": 292,
|
||||||
|
"293": 293,
|
||||||
|
"294": 294,
|
||||||
|
"295": 295,
|
||||||
|
"296": 296,
|
||||||
|
"297": 297,
|
||||||
|
"298": 298,
|
||||||
|
"299": 299,
|
||||||
|
"300": 300,
|
||||||
|
"301": 301,
|
||||||
|
"302": 302,
|
||||||
|
"303": 303,
|
||||||
|
"304": 304,
|
||||||
|
"305": 305,
|
||||||
|
"306": 306,
|
||||||
|
"307": 307,
|
||||||
|
"308": 308,
|
||||||
|
"309": 309,
|
||||||
|
"310": 310,
|
||||||
|
"311": 311,
|
||||||
|
"312": 312,
|
||||||
|
"313": 313,
|
||||||
|
"314": 314,
|
||||||
|
"315": 315,
|
||||||
|
"316": 316,
|
||||||
|
"317": 317,
|
||||||
|
"318": 318,
|
||||||
|
"319": 319,
|
||||||
|
"320": 320,
|
||||||
|
"321": 321,
|
||||||
|
"322": 322,
|
||||||
|
"323": 323,
|
||||||
|
"324": 324,
|
||||||
|
"325": 325,
|
||||||
|
"328": 328,
|
||||||
|
"329": 329,
|
||||||
|
"330": 330,
|
||||||
|
"331": 331,
|
||||||
|
"332": 332,
|
||||||
|
"333": 333,
|
||||||
|
"334": 334,
|
||||||
|
"335": 335,
|
||||||
|
"336": 336,
|
||||||
|
"337": 337,
|
||||||
|
"338": 338,
|
||||||
|
"339": 339,
|
||||||
|
"340": 340,
|
||||||
|
"341": 341,
|
||||||
|
"342": 342,
|
||||||
|
"344": 344,
|
||||||
|
"345": 345,
|
||||||
|
"346": 346,
|
||||||
|
"347": 347,
|
||||||
|
"348": 348,
|
||||||
|
"349": 349,
|
||||||
|
"350": 350,
|
||||||
|
"351": 351,
|
||||||
|
"352": 352,
|
||||||
|
"353": 353,
|
||||||
|
"354": 354,
|
||||||
|
"355": 355,
|
||||||
|
"356": 356,
|
||||||
|
"357": 357,
|
||||||
|
"358": 358,
|
||||||
|
"359": 359,
|
||||||
|
"360": 360,
|
||||||
|
"361": 361,
|
||||||
|
"362": 362,
|
||||||
|
"363": 363,
|
||||||
|
"364": 364,
|
||||||
|
"365": 365,
|
||||||
|
"366": 366,
|
||||||
|
"367": 367,
|
||||||
|
"368": 368,
|
||||||
|
"369": 369,
|
||||||
|
"370": 370,
|
||||||
|
"371": 371,
|
||||||
|
"372": 372,
|
||||||
|
"373": 373,
|
||||||
|
"374": 374,
|
||||||
|
"375": 375,
|
||||||
|
"376": 376,
|
||||||
|
"377": 377,
|
||||||
|
"378": 378,
|
||||||
|
"379": 379,
|
||||||
|
"380": 380,
|
||||||
|
"381": 381,
|
||||||
|
"382": 382,
|
||||||
|
"383": 383,
|
||||||
|
"384": 384,
|
||||||
|
"385": 385,
|
||||||
|
"386": 386,
|
||||||
|
"387": 387,
|
||||||
|
"388": 388,
|
||||||
|
"389": 389,
|
||||||
|
"390": 390,
|
||||||
|
"391": 391,
|
||||||
|
"392": 392,
|
||||||
|
"393": 393,
|
||||||
|
"394": 394,
|
||||||
|
"395": 395,
|
||||||
|
"396": 396,
|
||||||
|
"397": 397,
|
||||||
|
"398": 398,
|
||||||
|
"399": 399,
|
||||||
|
"400": 400,
|
||||||
|
"401": 401,
|
||||||
|
"402": 402,
|
||||||
|
"403": 403,
|
||||||
|
"404": 404,
|
||||||
|
"405": 405,
|
||||||
|
"406": 406,
|
||||||
|
"407": 407,
|
||||||
|
"408": 408,
|
||||||
|
"409": 409,
|
||||||
|
"410": 410,
|
||||||
|
"411": 411,
|
||||||
|
"412": 412,
|
||||||
|
"413": 413,
|
||||||
|
"414": 414,
|
||||||
|
"415": 415,
|
||||||
|
"416": 416,
|
||||||
|
"417": 417,
|
||||||
|
"418": 418,
|
||||||
|
"419": 419,
|
||||||
|
"420": 420,
|
||||||
|
"421": 421,
|
||||||
|
"422": 422,
|
||||||
|
"423": 423,
|
||||||
|
"424": 424,
|
||||||
|
"425": 425,
|
||||||
|
"426": 426,
|
||||||
|
"427": 427,
|
||||||
|
"428": 428,
|
||||||
|
"429": 429,
|
||||||
|
"430": 430,
|
||||||
|
"431": 431,
|
||||||
|
"432": 432,
|
||||||
|
"433": 433,
|
||||||
|
"434": 434,
|
||||||
|
"437": 437,
|
||||||
|
"438": 438,
|
||||||
|
"441": 441,
|
||||||
|
"442": 442,
|
||||||
|
"443": 443,
|
||||||
|
"444": 444,
|
||||||
|
"445": 445,
|
||||||
|
"446": 446,
|
||||||
|
"447": 447,
|
||||||
|
"448": 448,
|
||||||
|
"449": 449,
|
||||||
|
"450": 450,
|
||||||
|
"451": 451,
|
||||||
|
"452": 452,
|
||||||
|
"453": 453,
|
||||||
|
"455": 455,
|
||||||
|
"457": 457,
|
||||||
|
"458": 458,
|
||||||
|
"459": 459,
|
||||||
|
"460": 460,
|
||||||
|
"461": 461,
|
||||||
|
"462": 462,
|
||||||
|
"463": 463,
|
||||||
|
"464": 464,
|
||||||
|
"465": 465,
|
||||||
|
"466": 466,
|
||||||
|
"467": 467,
|
||||||
|
"468": 468,
|
||||||
|
"469": 469,
|
||||||
|
"470": 470,
|
||||||
|
"471": 471,
|
||||||
|
"472": 472,
|
||||||
|
"473": 473,
|
||||||
|
"474": 474,
|
||||||
|
"475": 475,
|
||||||
|
"476": 476,
|
||||||
|
"477": 477,
|
||||||
|
"499": 499,
|
||||||
|
"500": 500,
|
||||||
|
"501": 501,
|
||||||
|
"502": 502,
|
||||||
|
"503": 503,
|
||||||
|
"504": 504,
|
||||||
|
"505": 505,
|
||||||
|
"506": 506,
|
||||||
|
"507": 507,
|
||||||
|
"508": 508,
|
||||||
|
"509": 509,
|
||||||
|
"510": 510,
|
||||||
|
"511": 511,
|
||||||
|
"513": 513,
|
||||||
"acacia_button": -140,
|
"acacia_button": -140,
|
||||||
"acacia_door": 430,
|
"acacia_door": 430,
|
||||||
"acacia_door_block": 196,
|
"acacia_door_block": 196,
|
||||||
@ -226,27 +913,16 @@
|
|||||||
"egg": 344,
|
"egg": 344,
|
||||||
"element_0": 36,
|
"element_0": 36,
|
||||||
"element_1": -12,
|
"element_1": -12,
|
||||||
|
"element_2": -13,
|
||||||
|
"element_3": -14,
|
||||||
|
"element_4": -15,
|
||||||
|
"element_5": -16,
|
||||||
|
"element_6": -17,
|
||||||
|
"element_7": -18,
|
||||||
|
"element_8": -19,
|
||||||
|
"element_9": -20,
|
||||||
"element_10": -21,
|
"element_10": -21,
|
||||||
"element_100": -111,
|
|
||||||
"element_101": -112,
|
|
||||||
"element_102": -113,
|
|
||||||
"element_103": -114,
|
|
||||||
"element_104": -115,
|
|
||||||
"element_105": -116,
|
|
||||||
"element_106": -117,
|
|
||||||
"element_107": -118,
|
|
||||||
"element_108": -119,
|
|
||||||
"element_109": -120,
|
|
||||||
"element_11": -22,
|
"element_11": -22,
|
||||||
"element_110": -121,
|
|
||||||
"element_111": -122,
|
|
||||||
"element_112": -123,
|
|
||||||
"element_113": -124,
|
|
||||||
"element_114": -125,
|
|
||||||
"element_115": -126,
|
|
||||||
"element_116": -127,
|
|
||||||
"element_117": -128,
|
|
||||||
"element_118": -129,
|
|
||||||
"element_12": -23,
|
"element_12": -23,
|
||||||
"element_13": -24,
|
"element_13": -24,
|
||||||
"element_14": -25,
|
"element_14": -25,
|
||||||
@ -255,7 +931,6 @@
|
|||||||
"element_17": -28,
|
"element_17": -28,
|
||||||
"element_18": -29,
|
"element_18": -29,
|
||||||
"element_19": -30,
|
"element_19": -30,
|
||||||
"element_2": -13,
|
|
||||||
"element_20": -31,
|
"element_20": -31,
|
||||||
"element_21": -32,
|
"element_21": -32,
|
||||||
"element_22": -33,
|
"element_22": -33,
|
||||||
@ -266,7 +941,6 @@
|
|||||||
"element_27": -38,
|
"element_27": -38,
|
||||||
"element_28": -39,
|
"element_28": -39,
|
||||||
"element_29": -40,
|
"element_29": -40,
|
||||||
"element_3": -14,
|
|
||||||
"element_30": -41,
|
"element_30": -41,
|
||||||
"element_31": -42,
|
"element_31": -42,
|
||||||
"element_32": -43,
|
"element_32": -43,
|
||||||
@ -277,7 +951,6 @@
|
|||||||
"element_37": -48,
|
"element_37": -48,
|
||||||
"element_38": -49,
|
"element_38": -49,
|
||||||
"element_39": -50,
|
"element_39": -50,
|
||||||
"element_4": -15,
|
|
||||||
"element_40": -51,
|
"element_40": -51,
|
||||||
"element_41": -52,
|
"element_41": -52,
|
||||||
"element_42": -53,
|
"element_42": -53,
|
||||||
@ -288,7 +961,6 @@
|
|||||||
"element_47": -58,
|
"element_47": -58,
|
||||||
"element_48": -59,
|
"element_48": -59,
|
||||||
"element_49": -60,
|
"element_49": -60,
|
||||||
"element_5": -16,
|
|
||||||
"element_50": -61,
|
"element_50": -61,
|
||||||
"element_51": -62,
|
"element_51": -62,
|
||||||
"element_52": -63,
|
"element_52": -63,
|
||||||
@ -299,7 +971,6 @@
|
|||||||
"element_57": -68,
|
"element_57": -68,
|
||||||
"element_58": -69,
|
"element_58": -69,
|
||||||
"element_59": -70,
|
"element_59": -70,
|
||||||
"element_6": -17,
|
|
||||||
"element_60": -71,
|
"element_60": -71,
|
||||||
"element_61": -72,
|
"element_61": -72,
|
||||||
"element_62": -73,
|
"element_62": -73,
|
||||||
@ -310,7 +981,6 @@
|
|||||||
"element_67": -78,
|
"element_67": -78,
|
||||||
"element_68": -79,
|
"element_68": -79,
|
||||||
"element_69": -80,
|
"element_69": -80,
|
||||||
"element_7": -18,
|
|
||||||
"element_70": -81,
|
"element_70": -81,
|
||||||
"element_71": -82,
|
"element_71": -82,
|
||||||
"element_72": -83,
|
"element_72": -83,
|
||||||
@ -321,7 +991,6 @@
|
|||||||
"element_77": -88,
|
"element_77": -88,
|
||||||
"element_78": -89,
|
"element_78": -89,
|
||||||
"element_79": -90,
|
"element_79": -90,
|
||||||
"element_8": -19,
|
|
||||||
"element_80": -91,
|
"element_80": -91,
|
||||||
"element_81": -92,
|
"element_81": -92,
|
||||||
"element_82": -93,
|
"element_82": -93,
|
||||||
@ -332,7 +1001,6 @@
|
|||||||
"element_87": -98,
|
"element_87": -98,
|
||||||
"element_88": -99,
|
"element_88": -99,
|
||||||
"element_89": -100,
|
"element_89": -100,
|
||||||
"element_9": -20,
|
|
||||||
"element_90": -101,
|
"element_90": -101,
|
||||||
"element_91": -102,
|
"element_91": -102,
|
||||||
"element_92": -103,
|
"element_92": -103,
|
||||||
@ -343,6 +1011,25 @@
|
|||||||
"element_97": -108,
|
"element_97": -108,
|
||||||
"element_98": -109,
|
"element_98": -109,
|
||||||
"element_99": -110,
|
"element_99": -110,
|
||||||
|
"element_100": -111,
|
||||||
|
"element_101": -112,
|
||||||
|
"element_102": -113,
|
||||||
|
"element_103": -114,
|
||||||
|
"element_104": -115,
|
||||||
|
"element_105": -116,
|
||||||
|
"element_106": -117,
|
||||||
|
"element_107": -118,
|
||||||
|
"element_108": -119,
|
||||||
|
"element_109": -120,
|
||||||
|
"element_110": -121,
|
||||||
|
"element_111": -122,
|
||||||
|
"element_112": -123,
|
||||||
|
"element_113": -124,
|
||||||
|
"element_114": -125,
|
||||||
|
"element_115": -126,
|
||||||
|
"element_116": -127,
|
||||||
|
"element_117": -128,
|
||||||
|
"element_118": -129,
|
||||||
"elytra": 444,
|
"elytra": 444,
|
||||||
"emerald": 388,
|
"emerald": 388,
|
||||||
"emerald_block": 133,
|
"emerald_block": 133,
|
||||||
@ -532,8 +1219,8 @@
|
|||||||
"leather_pants": 300,
|
"leather_pants": 300,
|
||||||
"leather_tunic": 299,
|
"leather_tunic": 299,
|
||||||
"leave": 18,
|
"leave": 18,
|
||||||
"leaves": 18,
|
|
||||||
"leave2": 161,
|
"leave2": 161,
|
||||||
|
"leaves": 18,
|
||||||
"leaves2": 161,
|
"leaves2": 161,
|
||||||
"lectern": -194,
|
"lectern": -194,
|
||||||
"lever": 69,
|
"lever": 69,
|
||||||
|
Submodule resources/locale deleted from 4a322da43e
@ -108,7 +108,7 @@ player:
|
|||||||
verify-xuid: true
|
verify-xuid: true
|
||||||
|
|
||||||
level-settings:
|
level-settings:
|
||||||
#The default format that levels will use when created
|
#The default format that worlds will use when created
|
||||||
default-format: leveldb
|
default-format: leveldb
|
||||||
|
|
||||||
chunk-sending:
|
chunk-sending:
|
||||||
@ -128,7 +128,9 @@ chunk-ticking:
|
|||||||
blocks-per-subchunk-per-tick: 3
|
blocks-per-subchunk-per-tick: 3
|
||||||
#IDs of blocks not to perform random ticking on.
|
#IDs of blocks not to perform random ticking on.
|
||||||
disable-block-ticking:
|
disable-block-ticking:
|
||||||
#- 2 # grass
|
#- grass
|
||||||
|
#- ice
|
||||||
|
#- fire
|
||||||
|
|
||||||
chunk-generation:
|
chunk-generation:
|
||||||
#Max. amount of chunks in the waiting queue to be populated
|
#Max. amount of chunks in the waiting queue to be populated
|
||||||
@ -171,12 +173,39 @@ console:
|
|||||||
title-tick: true
|
title-tick: true
|
||||||
|
|
||||||
aliases:
|
aliases:
|
||||||
#Examples:
|
##This section allows you to add, remove or remap command aliases.
|
||||||
#showtheversion: version
|
##A single alias can call one or more other commands (or aliases).
|
||||||
|
##Aliases defined here will override any command aliases declared by plugins or PocketMine-MP itself.
|
||||||
|
|
||||||
|
##To remove an alias, set it to [], like so (note that prefixed aliases like "pocketmine:stop" will remain and can't
|
||||||
|
##be removed):
|
||||||
|
#stop: []
|
||||||
|
|
||||||
|
##Commands are not removed, only their aliases. You can still refer to a command using its full (prefixed)
|
||||||
|
##name, even if all its aliases are overwritten. The full name is usually something like "pocketmine:commandname" or
|
||||||
|
##"pluginname:commandname".
|
||||||
|
#abort: [pocketmine:stop]
|
||||||
|
|
||||||
|
##To add an alias, list the command(s) that it calls:
|
||||||
|
#showtheversion: [version]
|
||||||
#savestop: [save-all, stop]
|
#savestop: [save-all, stop]
|
||||||
|
|
||||||
|
##To invoke another command with arguments, use $1 to pass the first argument, $2 for the second etc:
|
||||||
|
#giveadmin: [op $1] ## `giveadmin alex` -> `op alex`
|
||||||
|
#kill: [suicide, say "I tried to kill $1"] ## `kill alex` -> `suicide` + `say "I tried to kill alex"`
|
||||||
|
#giverandom: [give $1 $2, say "Someone has just received a $2!"] ## `giverandom alex diamond` -> `give alex diamond` + `say "Someone has just received a diamond!"`
|
||||||
|
|
||||||
|
##To make arguments mandatory (so that the command fails if they are not provided), use $$, e.g. $$1, $$2:
|
||||||
|
#makeadmin: [op $$1] ## `makeadmin alex` -> `op alex`, `makeadmin` with no arguments = error
|
||||||
|
|
||||||
|
##To pass through a range of arguments, put a - (hyphen) after the index:
|
||||||
|
#tpalias: [tp $1-] ## `tpalias 256 70 256` -> `tp 256 70 256` - this passes arguments 1 and everything after it to the `tp` command
|
||||||
|
|
||||||
|
##To change an existing command alias and make it do something else:
|
||||||
|
#tp: [suicide]
|
||||||
|
|
||||||
worlds:
|
worlds:
|
||||||
#These settings will override the generator set in server.properties and allows loading multiple levels
|
#These settings will override the generator set in server.properties and allows loading multiple worlds
|
||||||
#Example:
|
#Example:
|
||||||
#world:
|
#world:
|
||||||
# seed: 404
|
# seed: 404
|
||||||
|
Submodule resources/vanilla deleted from 19569dd729
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -35,3 +35,6 @@ define('pocketmine\_CORE_CONSTANTS_INCLUDED', true);
|
|||||||
|
|
||||||
define('pocketmine\PATH', dirname(__DIR__) . '/');
|
define('pocketmine\PATH', dirname(__DIR__) . '/');
|
||||||
define('pocketmine\RESOURCE_PATH', dirname(__DIR__) . '/resources/');
|
define('pocketmine\RESOURCE_PATH', dirname(__DIR__) . '/resources/');
|
||||||
|
define('pocketmine\BEDROCK_DATA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-data/');
|
||||||
|
define('pocketmine\LOCALE_DATA_PATH', dirname(__DIR__) . '/vendor/pocketmine/locale-data/');
|
||||||
|
define('pocketmine\COMPOSER_AUTOLOADER_PATH', dirname(__DIR__) . '/vendor/autoload.php');
|
||||||
|
@ -1,379 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* ____ _ _ __ __ _ __ __ ____
|
|
||||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
|
||||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
|
||||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
|
||||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* @author PocketMine Team
|
|
||||||
* @link http://www.pocketmine.net/
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace pocketmine;
|
|
||||||
|
|
||||||
use Composer\InstalledVersions;
|
|
||||||
use pocketmine\errorhandler\ErrorTypeToStringMap;
|
|
||||||
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
|
||||||
use pocketmine\plugin\PluginBase;
|
|
||||||
use pocketmine\plugin\PluginManager;
|
|
||||||
use pocketmine\utils\AssumptionFailedError;
|
|
||||||
use pocketmine\utils\Filesystem;
|
|
||||||
use pocketmine\utils\Utils;
|
|
||||||
use Webmozart\PathUtil\Path;
|
|
||||||
use function base64_encode;
|
|
||||||
use function date;
|
|
||||||
use function error_get_last;
|
|
||||||
use function fclose;
|
|
||||||
use function file;
|
|
||||||
use function file_exists;
|
|
||||||
use function file_get_contents;
|
|
||||||
use function fopen;
|
|
||||||
use function fwrite;
|
|
||||||
use function get_loaded_extensions;
|
|
||||||
use function implode;
|
|
||||||
use function is_dir;
|
|
||||||
use function is_resource;
|
|
||||||
use function json_encode;
|
|
||||||
use function json_last_error_msg;
|
|
||||||
use function ksort;
|
|
||||||
use function max;
|
|
||||||
use function mb_strtoupper;
|
|
||||||
use function microtime;
|
|
||||||
use function mkdir;
|
|
||||||
use function ob_end_clean;
|
|
||||||
use function ob_get_contents;
|
|
||||||
use function ob_start;
|
|
||||||
use function php_uname;
|
|
||||||
use function phpinfo;
|
|
||||||
use function phpversion;
|
|
||||||
use function preg_replace;
|
|
||||||
use function sprintf;
|
|
||||||
use function str_split;
|
|
||||||
use function strpos;
|
|
||||||
use function substr;
|
|
||||||
use function zend_version;
|
|
||||||
use function zlib_encode;
|
|
||||||
use const FILE_IGNORE_NEW_LINES;
|
|
||||||
use const JSON_UNESCAPED_SLASHES;
|
|
||||||
use const PHP_EOL;
|
|
||||||
use const PHP_OS;
|
|
||||||
use const SORT_STRING;
|
|
||||||
|
|
||||||
class CrashDump{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crashdump data format version, used by the crash archive to decide how to decode the crashdump
|
|
||||||
* This should be incremented when backwards incompatible changes are introduced, such as fields being removed or
|
|
||||||
* having their content changed, version format changing, etc.
|
|
||||||
* It is not necessary to increase this when adding new fields.
|
|
||||||
*/
|
|
||||||
private const FORMAT_VERSION = 4;
|
|
||||||
|
|
||||||
private const PLUGIN_INVOLVEMENT_NONE = "none";
|
|
||||||
private const PLUGIN_INVOLVEMENT_DIRECT = "direct";
|
|
||||||
private const PLUGIN_INVOLVEMENT_INDIRECT = "indirect";
|
|
||||||
|
|
||||||
/** @var Server */
|
|
||||||
private $server;
|
|
||||||
/** @var resource */
|
|
||||||
private $fp;
|
|
||||||
/** @var float */
|
|
||||||
private $time;
|
|
||||||
/**
|
|
||||||
* @var mixed[]
|
|
||||||
* @phpstan-var array<string, mixed>
|
|
||||||
*/
|
|
||||||
private $data = [];
|
|
||||||
/** @var string */
|
|
||||||
private $encodedData = "";
|
|
||||||
/** @var string */
|
|
||||||
private $path;
|
|
||||||
|
|
||||||
public function __construct(Server $server){
|
|
||||||
$this->time = microtime(true);
|
|
||||||
$this->server = $server;
|
|
||||||
|
|
||||||
$crashPath = Path::join($this->server->getDataPath(), "crashdumps");
|
|
||||||
if(!is_dir($crashPath)){
|
|
||||||
mkdir($crashPath);
|
|
||||||
}
|
|
||||||
$this->path = Path::join($crashPath, date("D_M_j-H.i.s-T_Y", (int) $this->time) . ".log");
|
|
||||||
$fp = @fopen($this->path, "wb");
|
|
||||||
if(!is_resource($fp)){
|
|
||||||
throw new \RuntimeException("Could not create Crash Dump");
|
|
||||||
}
|
|
||||||
$this->fp = $fp;
|
|
||||||
$this->data["format_version"] = self::FORMAT_VERSION;
|
|
||||||
$this->data["time"] = $this->time;
|
|
||||||
$this->data["uptime"] = $this->time - $this->server->getStartTime();
|
|
||||||
$this->addLine($this->server->getName() . " Crash Dump " . date("D M j H:i:s T Y", (int) $this->time));
|
|
||||||
$this->addLine();
|
|
||||||
$this->baseCrash();
|
|
||||||
$this->generalData();
|
|
||||||
$this->pluginsData();
|
|
||||||
|
|
||||||
$this->extraData();
|
|
||||||
|
|
||||||
$this->encodeData();
|
|
||||||
|
|
||||||
fclose($this->fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPath() : string{
|
|
||||||
return $this->path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getEncodedData() : string{
|
|
||||||
return $this->encodedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return mixed[]
|
|
||||||
* @phpstan-return array<string, mixed>
|
|
||||||
*/
|
|
||||||
public function getData() : array{
|
|
||||||
return $this->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function encodeData() : void{
|
|
||||||
$this->addLine();
|
|
||||||
$this->addLine("----------------------REPORT THE DATA BELOW THIS LINE-----------------------");
|
|
||||||
$this->addLine();
|
|
||||||
$this->addLine("===BEGIN CRASH DUMP===");
|
|
||||||
$json = json_encode($this->data, JSON_UNESCAPED_SLASHES);
|
|
||||||
if($json === false){
|
|
||||||
throw new \RuntimeException("Failed to encode crashdump JSON: " . json_last_error_msg());
|
|
||||||
}
|
|
||||||
$zlibEncoded = zlib_encode($json, ZLIB_ENCODING_DEFLATE, 9);
|
|
||||||
if($zlibEncoded === false) throw new AssumptionFailedError("ZLIB compression failed");
|
|
||||||
$this->encodedData = $zlibEncoded;
|
|
||||||
foreach(str_split(base64_encode($this->encodedData), 76) as $line){
|
|
||||||
$this->addLine($line);
|
|
||||||
}
|
|
||||||
$this->addLine("===END CRASH DUMP===");
|
|
||||||
}
|
|
||||||
|
|
||||||
private function pluginsData() : void{
|
|
||||||
if($this->server->getPluginManager() instanceof PluginManager){
|
|
||||||
$this->addLine();
|
|
||||||
$this->addLine("Loaded plugins:");
|
|
||||||
$this->data["plugins"] = [];
|
|
||||||
$plugins = $this->server->getPluginManager()->getPlugins();
|
|
||||||
ksort($plugins, SORT_STRING);
|
|
||||||
foreach($plugins as $p){
|
|
||||||
$d = $p->getDescription();
|
|
||||||
$this->data["plugins"][$d->getName()] = [
|
|
||||||
"name" => $d->getName(),
|
|
||||||
"version" => $d->getVersion(),
|
|
||||||
"authors" => $d->getAuthors(),
|
|
||||||
"api" => $d->getCompatibleApis(),
|
|
||||||
"enabled" => $p->isEnabled(),
|
|
||||||
"depends" => $d->getDepend(),
|
|
||||||
"softDepends" => $d->getSoftDepend(),
|
|
||||||
"main" => $d->getMain(),
|
|
||||||
"load" => mb_strtoupper($d->getOrder()->name()),
|
|
||||||
"website" => $d->getWebsite()
|
|
||||||
];
|
|
||||||
$this->addLine($d->getName() . " " . $d->getVersion() . " by " . implode(", ", $d->getAuthors()) . " for API(s) " . implode(", ", $d->getCompatibleApis()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function extraData() : void{
|
|
||||||
global $argv;
|
|
||||||
|
|
||||||
if($this->server->getConfigGroup()->getPropertyBool("auto-report.send-settings", true)){
|
|
||||||
$this->data["parameters"] = (array) $argv;
|
|
||||||
if(($serverDotProperties = @file_get_contents(Path::join($this->server->getDataPath(), "server.properties"))) !== false){
|
|
||||||
$this->data["server.properties"] = preg_replace("#^rcon\\.password=(.*)$#m", "rcon.password=******", $serverDotProperties);
|
|
||||||
}else{
|
|
||||||
$this->data["server.properties"] = $serverDotProperties;
|
|
||||||
}
|
|
||||||
if(($pocketmineDotYml = @file_get_contents(Path::join($this->server->getDataPath(), "pocketmine.yml"))) !== false){
|
|
||||||
$this->data["pocketmine.yml"] = $pocketmineDotYml;
|
|
||||||
}else{
|
|
||||||
$this->data["pocketmine.yml"] = "";
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
$this->data["pocketmine.yml"] = "";
|
|
||||||
$this->data["server.properties"] = "";
|
|
||||||
$this->data["parameters"] = [];
|
|
||||||
}
|
|
||||||
$extensions = [];
|
|
||||||
foreach(get_loaded_extensions() as $ext){
|
|
||||||
$extensions[$ext] = phpversion($ext);
|
|
||||||
}
|
|
||||||
$this->data["extensions"] = $extensions;
|
|
||||||
|
|
||||||
if($this->server->getConfigGroup()->getPropertyBool("auto-report.send-phpinfo", true)){
|
|
||||||
ob_start();
|
|
||||||
phpinfo();
|
|
||||||
$this->data["phpinfo"] = ob_get_contents();
|
|
||||||
ob_end_clean();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function baseCrash() : void{
|
|
||||||
global $lastExceptionError, $lastError;
|
|
||||||
|
|
||||||
if(isset($lastExceptionError)){
|
|
||||||
$error = $lastExceptionError;
|
|
||||||
}else{
|
|
||||||
$error = error_get_last();
|
|
||||||
if($error === null){
|
|
||||||
throw new \RuntimeException("Crash error information missing - did something use exit()?");
|
|
||||||
}
|
|
||||||
$error["trace"] = Utils::currentTrace(3); //Skipping CrashDump->baseCrash, CrashDump->construct, Server->crashDump
|
|
||||||
$error["fullFile"] = $error["file"];
|
|
||||||
$error["file"] = Filesystem::cleanPath($error["file"]);
|
|
||||||
try{
|
|
||||||
$error["type"] = ErrorTypeToStringMap::get($error["type"]);
|
|
||||||
}catch(\InvalidArgumentException $e){
|
|
||||||
//pass
|
|
||||||
}
|
|
||||||
if(($pos = strpos($error["message"], "\n")) !== false){
|
|
||||||
$error["message"] = substr($error["message"], 0, $pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($lastError)){
|
|
||||||
if(isset($lastError["trace"])){
|
|
||||||
$lastError["trace"] = Utils::printableTrace($lastError["trace"]);
|
|
||||||
}
|
|
||||||
$this->data["lastError"] = $lastError;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->data["error"] = $error;
|
|
||||||
unset($this->data["error"]["fullFile"]);
|
|
||||||
unset($this->data["error"]["trace"]);
|
|
||||||
$this->addLine("Error: " . $error["message"]);
|
|
||||||
$this->addLine("File: " . $error["file"]);
|
|
||||||
$this->addLine("Line: " . $error["line"]);
|
|
||||||
$this->addLine("Type: " . $error["type"]);
|
|
||||||
|
|
||||||
$this->data["plugin_involvement"] = self::PLUGIN_INVOLVEMENT_NONE;
|
|
||||||
if(!$this->determinePluginFromFile($error["fullFile"], true)){ //fatal errors won't leave any stack trace
|
|
||||||
foreach($error["trace"] as $frame){
|
|
||||||
if(!isset($frame["file"])){
|
|
||||||
continue; //PHP core
|
|
||||||
}
|
|
||||||
if($this->determinePluginFromFile($frame["file"], false)){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->addLine();
|
|
||||||
$this->addLine("Code:");
|
|
||||||
$this->data["code"] = [];
|
|
||||||
|
|
||||||
if($this->server->getConfigGroup()->getPropertyBool("auto-report.send-code", true) and file_exists($error["fullFile"])){
|
|
||||||
$file = @file($error["fullFile"], FILE_IGNORE_NEW_LINES);
|
|
||||||
if($file !== false){
|
|
||||||
for($l = max(0, $error["line"] - 10); $l < $error["line"] + 10 and isset($file[$l]); ++$l){
|
|
||||||
$this->addLine("[" . ($l + 1) . "] " . $file[$l]);
|
|
||||||
$this->data["code"][$l + 1] = $file[$l];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->addLine();
|
|
||||||
$this->addLine("Backtrace:");
|
|
||||||
foreach(($this->data["trace"] = Utils::printableTrace($error["trace"])) as $line){
|
|
||||||
$this->addLine($line);
|
|
||||||
}
|
|
||||||
$this->addLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function determinePluginFromFile(string $filePath, bool $crashFrame) : bool{
|
|
||||||
$frameCleanPath = Filesystem::cleanPath($filePath);
|
|
||||||
if(strpos($frameCleanPath, Filesystem::CLEAN_PATH_SRC_PREFIX) !== 0){
|
|
||||||
$this->addLine();
|
|
||||||
if($crashFrame){
|
|
||||||
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
|
|
||||||
$this->data["plugin_involvement"] = self::PLUGIN_INVOLVEMENT_DIRECT;
|
|
||||||
}else{
|
|
||||||
$this->addLine("A PLUGIN WAS INVOLVED IN THIS CRASH");
|
|
||||||
$this->data["plugin_involvement"] = self::PLUGIN_INVOLVEMENT_INDIRECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(file_exists($filePath)){
|
|
||||||
$reflection = new \ReflectionClass(PluginBase::class);
|
|
||||||
$file = $reflection->getProperty("file");
|
|
||||||
$file->setAccessible(true);
|
|
||||||
foreach($this->server->getPluginManager()->getPlugins() as $plugin){
|
|
||||||
$filePath = Filesystem::cleanPath($file->getValue($plugin));
|
|
||||||
if(strpos($frameCleanPath, $filePath) === 0){
|
|
||||||
$this->data["plugin"] = $plugin->getName();
|
|
||||||
$this->addLine("BAD PLUGIN: " . $plugin->getDescription()->getFullName());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function generalData() : void{
|
|
||||||
$version = VersionInfo::VERSION();
|
|
||||||
$composerLibraries = [];
|
|
||||||
foreach(InstalledVersions::getInstalledPackages() as $package){
|
|
||||||
$composerLibraries[$package] = sprintf(
|
|
||||||
"%s@%s",
|
|
||||||
InstalledVersions::getPrettyVersion($package) ?? "unknown",
|
|
||||||
InstalledVersions::getReference($package) ?? "unknown"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->data["general"] = [];
|
|
||||||
$this->data["general"]["name"] = $this->server->getName();
|
|
||||||
$this->data["general"]["base_version"] = VersionInfo::BASE_VERSION;
|
|
||||||
$this->data["general"]["build"] = VersionInfo::BUILD_NUMBER;
|
|
||||||
$this->data["general"]["is_dev"] = VersionInfo::IS_DEVELOPMENT_BUILD;
|
|
||||||
$this->data["general"]["protocol"] = ProtocolInfo::CURRENT_PROTOCOL;
|
|
||||||
$this->data["general"]["git"] = VersionInfo::GIT_HASH();
|
|
||||||
$this->data["general"]["uname"] = php_uname("a");
|
|
||||||
$this->data["general"]["php"] = phpversion();
|
|
||||||
$this->data["general"]["zend"] = zend_version();
|
|
||||||
$this->data["general"]["php_os"] = PHP_OS;
|
|
||||||
$this->data["general"]["os"] = Utils::getOS();
|
|
||||||
$this->data["general"]["composer_libraries"] = $composerLibraries;
|
|
||||||
$this->addLine($this->server->getName() . " version: " . $version->getFullVersion(true) . " [Protocol " . ProtocolInfo::CURRENT_PROTOCOL . "]");
|
|
||||||
$this->addLine("Git commit: " . VersionInfo::GIT_HASH());
|
|
||||||
$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());
|
|
||||||
$this->addLine("Composer libraries: ");
|
|
||||||
foreach($composerLibraries as $library => $libraryVersion){
|
|
||||||
$this->addLine("- $library $libraryVersion");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $line
|
|
||||||
*/
|
|
||||||
public function addLine($line = "") : void{
|
|
||||||
fwrite($this->fp, $line . PHP_EOL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $str
|
|
||||||
*/
|
|
||||||
public function add($str) : void{
|
|
||||||
fwrite($this->fp, $str);
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,17 +17,17 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine;
|
namespace pocketmine;
|
||||||
|
|
||||||
use pocketmine\event\server\LowMemoryEvent;
|
use pocketmine\event\server\LowMemoryEvent;
|
||||||
|
use pocketmine\network\mcpe\cache\ChunkCache;
|
||||||
use pocketmine\scheduler\DumpWorkerMemoryTask;
|
use pocketmine\scheduler\DumpWorkerMemoryTask;
|
||||||
use pocketmine\scheduler\GarbageCollectionTask;
|
use pocketmine\scheduler\GarbageCollectionTask;
|
||||||
use pocketmine\timings\Timings;
|
use pocketmine\timings\Timings;
|
||||||
use pocketmine\utils\AssumptionFailedError;
|
|
||||||
use pocketmine\utils\Process;
|
use pocketmine\utils\Process;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
use Webmozart\PathUtil\Path;
|
use Webmozart\PathUtil\Path;
|
||||||
@ -64,13 +64,11 @@ use function sprintf;
|
|||||||
use function strlen;
|
use function strlen;
|
||||||
use function substr;
|
use function substr;
|
||||||
use const JSON_PRETTY_PRINT;
|
use const JSON_PRETTY_PRINT;
|
||||||
|
use const JSON_THROW_ON_ERROR;
|
||||||
use const JSON_UNESCAPED_SLASHES;
|
use const JSON_UNESCAPED_SLASHES;
|
||||||
use const SORT_NUMERIC;
|
use const SORT_NUMERIC;
|
||||||
|
|
||||||
class MemoryManager{
|
class MemoryManager{
|
||||||
|
|
||||||
private Server $server;
|
|
||||||
|
|
||||||
private int $memoryLimit;
|
private int $memoryLimit;
|
||||||
private int $globalMemoryLimit;
|
private int $globalMemoryLimit;
|
||||||
private int $checkRate;
|
private int $checkRate;
|
||||||
@ -97,8 +95,9 @@ class MemoryManager{
|
|||||||
|
|
||||||
private \Logger $logger;
|
private \Logger $logger;
|
||||||
|
|
||||||
public function __construct(Server $server){
|
public function __construct(
|
||||||
$this->server = $server;
|
private Server $server
|
||||||
|
){
|
||||||
$this->logger = new \PrefixedLogger($server->getLogger(), "Memory Manager");
|
$this->logger = new \PrefixedLogger($server->getLogger(), "Memory Manager");
|
||||||
|
|
||||||
$this->init($server->getConfigGroup());
|
$this->init($server->getConfigGroup());
|
||||||
@ -167,14 +166,14 @@ class MemoryManager{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function canUseChunkCache() : bool{
|
public function canUseChunkCache() : bool{
|
||||||
return !$this->lowMemory or !$this->lowMemDisableChunkCache;
|
return !$this->lowMemory || !$this->lowMemDisableChunkCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the allowed chunk radius based on the current memory usage.
|
* Returns the allowed chunk radius based on the current memory usage.
|
||||||
*/
|
*/
|
||||||
public function getViewDistance(int $distance) : int{
|
public function getViewDistance(int $distance) : int{
|
||||||
return ($this->lowMemory and $this->lowMemChunkRadiusOverride > 0) ? min($this->lowMemChunkRadiusOverride, $distance) : $distance;
|
return ($this->lowMemory && $this->lowMemChunkRadiusOverride > 0) ? min($this->lowMemChunkRadiusOverride, $distance) : $distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -187,6 +186,7 @@ class MemoryManager{
|
|||||||
foreach($this->server->getWorldManager()->getWorlds() as $world){
|
foreach($this->server->getWorldManager()->getWorlds() as $world){
|
||||||
$world->clearCache(true);
|
$world->clearCache(true);
|
||||||
}
|
}
|
||||||
|
ChunkCache::pruneCaches();
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->lowMemChunkGC){
|
if($this->lowMemChunkGC){
|
||||||
@ -212,18 +212,18 @@ class MemoryManager{
|
|||||||
public function check() : void{
|
public function check() : void{
|
||||||
Timings::$memoryManager->startTiming();
|
Timings::$memoryManager->startTiming();
|
||||||
|
|
||||||
if(($this->memoryLimit > 0 or $this->globalMemoryLimit > 0) and ++$this->checkTicker >= $this->checkRate){
|
if(($this->memoryLimit > 0 || $this->globalMemoryLimit > 0) && ++$this->checkTicker >= $this->checkRate){
|
||||||
$this->checkTicker = 0;
|
$this->checkTicker = 0;
|
||||||
$memory = Process::getAdvancedMemoryUsage();
|
$memory = Process::getAdvancedMemoryUsage();
|
||||||
$trigger = false;
|
$trigger = false;
|
||||||
if($this->memoryLimit > 0 and $memory[0] > $this->memoryLimit){
|
if($this->memoryLimit > 0 && $memory[0] > $this->memoryLimit){
|
||||||
$trigger = 0;
|
$trigger = 0;
|
||||||
}elseif($this->globalMemoryLimit > 0 and $memory[1] > $this->globalMemoryLimit){
|
}elseif($this->globalMemoryLimit > 0 && $memory[1] > $this->globalMemoryLimit){
|
||||||
$trigger = 1;
|
$trigger = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($trigger !== false){
|
if($trigger !== false){
|
||||||
if($this->lowMemory and $this->continuousTrigger){
|
if($this->lowMemory && $this->continuousTrigger){
|
||||||
if(++$this->continuousTriggerTicker >= $this->continuousTriggerRate){
|
if(++$this->continuousTriggerTicker >= $this->continuousTriggerRate){
|
||||||
$this->continuousTriggerTicker = 0;
|
$this->continuousTriggerTicker = 0;
|
||||||
$this->trigger($memory[$trigger], $this->memoryLimit, $trigger > 0, ++$this->continuousTriggerCount);
|
$this->trigger($memory[$trigger], $this->memoryLimit, $trigger > 0, ++$this->continuousTriggerCount);
|
||||||
@ -238,7 +238,7 @@ class MemoryManager{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->garbageCollectionPeriod > 0 and ++$this->garbageCollectionTicker >= $this->garbageCollectionPeriod){
|
if($this->garbageCollectionPeriod > 0 && ++$this->garbageCollectionTicker >= $this->garbageCollectionPeriod){
|
||||||
$this->garbageCollectionTicker = 0;
|
$this->garbageCollectionTicker = 0;
|
||||||
$this->triggerGarbageCollector();
|
$this->triggerGarbageCollector();
|
||||||
}
|
}
|
||||||
@ -289,8 +289,7 @@ class MemoryManager{
|
|||||||
* @param mixed $startingObject
|
* @param mixed $startingObject
|
||||||
*/
|
*/
|
||||||
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger) : void{
|
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger) : void{
|
||||||
$hardLimit = ini_get('memory_limit');
|
$hardLimit = Utils::assumeNotFalse(ini_get('memory_limit'), "memory_limit INI directive should always exist");
|
||||||
if($hardLimit === false) throw new AssumptionFailedError("memory_limit INI directive should always exist");
|
|
||||||
ini_set('memory_limit', '-1');
|
ini_set('memory_limit', '-1');
|
||||||
gc_disable();
|
gc_disable();
|
||||||
|
|
||||||
@ -298,7 +297,7 @@ class MemoryManager{
|
|||||||
mkdir($outputFolder, 0777, true);
|
mkdir($outputFolder, 0777, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$obData = fopen(Path::join($outputFolder, "objects.js"), "wb+");
|
$obData = Utils::assumeNotFalse(fopen(Path::join($outputFolder, "objects.js"), "wb+"));
|
||||||
|
|
||||||
$objects = [];
|
$objects = [];
|
||||||
|
|
||||||
@ -316,13 +315,16 @@ class MemoryManager{
|
|||||||
$reflection = new \ReflectionClass($className);
|
$reflection = new \ReflectionClass($className);
|
||||||
$staticProperties[$className] = [];
|
$staticProperties[$className] = [];
|
||||||
foreach($reflection->getProperties() as $property){
|
foreach($reflection->getProperties() as $property){
|
||||||
if(!$property->isStatic() or $property->getDeclaringClass()->getName() !== $className){
|
if(!$property->isStatic() || $property->getDeclaringClass()->getName() !== $className){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$property->isPublic()){
|
if(!$property->isPublic()){
|
||||||
$property->setAccessible(true);
|
$property->setAccessible(true);
|
||||||
}
|
}
|
||||||
|
if(!$property->isInitialized()){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$staticCount++;
|
$staticCount++;
|
||||||
$staticProperties[$className][$property->getName()] = self::continueDump($property->getValue(), $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
$staticProperties[$className][$property->getName()] = self::continueDump($property->getValue(), $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||||
@ -347,10 +349,9 @@ class MemoryManager{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file_put_contents(Path::join($outputFolder, "staticProperties.js"), json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
file_put_contents(Path::join($outputFolder, "staticProperties.js"), json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
|
||||||
$logger->info("Wrote $staticCount static properties");
|
$logger->info("Wrote $staticCount static properties");
|
||||||
|
|
||||||
if(isset($GLOBALS)){ //This might be null if we're on a different thread
|
|
||||||
$globalVariables = [];
|
$globalVariables = [];
|
||||||
$globalCount = 0;
|
$globalCount = 0;
|
||||||
|
|
||||||
@ -366,7 +367,7 @@ class MemoryManager{
|
|||||||
'_SESSION' => true
|
'_SESSION' => true
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach($GLOBALS as $varName => $value){
|
foreach(Utils::stringifyKeys($GLOBALS) as $varName => $value){
|
||||||
if(isset($ignoredGlobals[$varName])){
|
if(isset($ignoredGlobals[$varName])){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -375,9 +376,8 @@ class MemoryManager{
|
|||||||
$globalVariables[$varName] = self::continueDump($value, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
$globalVariables[$varName] = self::continueDump($value, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
file_put_contents(Path::join($outputFolder, "globalVariables.js"), json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
file_put_contents(Path::join($outputFolder, "globalVariables.js"), json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
|
||||||
$logger->info("Wrote $globalCount global variables");
|
$logger->info("Wrote $globalCount global variables");
|
||||||
}
|
|
||||||
|
|
||||||
foreach(get_defined_functions()["user"] as $function){
|
foreach(get_defined_functions()["user"] as $function){
|
||||||
$reflect = new \ReflectionFunction($function);
|
$reflect = new \ReflectionFunction($function);
|
||||||
@ -391,7 +391,7 @@ class MemoryManager{
|
|||||||
$functionStaticVarsCount += count($vars);
|
$functionStaticVarsCount += count($vars);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_put_contents(Path::join($outputFolder, 'functionStaticVars.js'), json_encode($functionStaticVars, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
file_put_contents(Path::join($outputFolder, 'functionStaticVars.js'), json_encode($functionStaticVars, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
|
||||||
$logger->info("Wrote $functionStaticVarsCount function static variables");
|
$logger->info("Wrote $functionStaticVarsCount function static variables");
|
||||||
|
|
||||||
$data = self::continueDump($startingObject, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
$data = self::continueDump($startingObject, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||||
@ -448,13 +448,16 @@ class MemoryManager{
|
|||||||
if(!$property->isPublic()){
|
if(!$property->isPublic()){
|
||||||
$property->setAccessible(true);
|
$property->setAccessible(true);
|
||||||
}
|
}
|
||||||
|
if(!$property->isInitialized($object)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$info["properties"][$name] = self::continueDump($property->getValue($object), $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
$info["properties"][$name] = self::continueDump($property->getValue($object), $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fwrite($obData, json_encode($info, JSON_UNESCAPED_SLASHES) . "\n");
|
fwrite($obData, json_encode($info, JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR) . "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
}while($continue);
|
}while($continue);
|
||||||
@ -463,11 +466,11 @@ class MemoryManager{
|
|||||||
|
|
||||||
fclose($obData);
|
fclose($obData);
|
||||||
|
|
||||||
file_put_contents(Path::join($outputFolder, "serverEntry.js"), json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
file_put_contents(Path::join($outputFolder, "serverEntry.js"), json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
|
||||||
file_put_contents(Path::join($outputFolder, "referenceCounts.js"), json_encode($refCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
file_put_contents(Path::join($outputFolder, "referenceCounts.js"), json_encode($refCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
|
||||||
|
|
||||||
arsort($instanceCounts, SORT_NUMERIC);
|
arsort($instanceCounts, SORT_NUMERIC);
|
||||||
file_put_contents(Path::join($outputFolder, "instanceCounts.js"), json_encode($instanceCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
file_put_contents(Path::join($outputFolder, "instanceCounts.js"), json_encode($instanceCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
|
||||||
|
|
||||||
$logger->info("Finished!");
|
$logger->info("Finished!");
|
||||||
|
|
||||||
@ -503,8 +506,13 @@ class MemoryManager{
|
|||||||
return "(error) ARRAY RECURSION LIMIT REACHED";
|
return "(error) ARRAY RECURSION LIMIT REACHED";
|
||||||
}
|
}
|
||||||
$data = [];
|
$data = [];
|
||||||
|
$numeric = 0;
|
||||||
foreach($from as $key => $value){
|
foreach($from as $key => $value){
|
||||||
$data[$key] = self::continueDump($value, $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize);
|
$data[$numeric] = [
|
||||||
|
"k" => self::continueDump($key, $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize),
|
||||||
|
"v" => self::continueDump($value, $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize),
|
||||||
|
];
|
||||||
|
$numeric++;
|
||||||
}
|
}
|
||||||
}elseif(is_string($from)){
|
}elseif(is_string($from)){
|
||||||
$data = "(string) len(" . strlen($from) . ") " . substr(Utils::printable($from), 0, $maxStringSize);
|
$data = "(string) len(" . strlen($from) . ") " . substr(Utils::printable($from), 0, $maxStringSize);
|
||||||
|
@ -32,13 +32,16 @@ namespace pocketmine {
|
|||||||
use pocketmine\utils\ServerKiller;
|
use pocketmine\utils\ServerKiller;
|
||||||
use pocketmine\utils\Terminal;
|
use pocketmine\utils\Terminal;
|
||||||
use pocketmine\utils\Timezone;
|
use pocketmine\utils\Timezone;
|
||||||
|
use pocketmine\utils\Utils;
|
||||||
use pocketmine\wizard\SetupWizard;
|
use pocketmine\wizard\SetupWizard;
|
||||||
use Webmozart\PathUtil\Path;
|
use Webmozart\PathUtil\Path;
|
||||||
|
use function defined;
|
||||||
use function extension_loaded;
|
use function extension_loaded;
|
||||||
|
use function getcwd;
|
||||||
use function phpversion;
|
use function phpversion;
|
||||||
use function preg_match;
|
use function preg_match;
|
||||||
use function preg_quote;
|
use function preg_quote;
|
||||||
use function strpos;
|
use function realpath;
|
||||||
use function version_compare;
|
use function version_compare;
|
||||||
|
|
||||||
require_once __DIR__ . '/VersionInfo.php';
|
require_once __DIR__ . '/VersionInfo.php';
|
||||||
@ -111,21 +114,22 @@ namespace pocketmine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(extension_loaded("pthreads")){
|
if(($pthreads_version = phpversion("pthreads")) !== false){
|
||||||
$pthreads_version = phpversion("pthreads");
|
|
||||||
if(substr_count($pthreads_version, ".") < 2){
|
if(substr_count($pthreads_version, ".") < 2){
|
||||||
$pthreads_version = "0.$pthreads_version";
|
$pthreads_version = "0.$pthreads_version";
|
||||||
}
|
}
|
||||||
if(version_compare($pthreads_version, "3.2.0") < 0){
|
if(version_compare($pthreads_version, "4.0.0") < 0 || version_compare($pthreads_version, "5.0.0") > 0){
|
||||||
$messages[] = "pthreads >= 3.2.0 is required, while you have $pthreads_version.";
|
$messages[] = "pthreads ^4.0.0 is required, while you have $pthreads_version.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(extension_loaded("leveldb")){
|
if(($leveldb_version = phpversion("leveldb")) !== false){
|
||||||
$leveldb_version = phpversion("leveldb");
|
|
||||||
if(version_compare($leveldb_version, "0.2.1") < 0){
|
if(version_compare($leveldb_version, "0.2.1") < 0){
|
||||||
$messages[] = "php-leveldb >= 0.2.1 is required, while you have $leveldb_version.";
|
$messages[] = "php-leveldb >= 0.2.1 is required, while you have $leveldb_version.";
|
||||||
}
|
}
|
||||||
|
if(!defined('LEVELDB_ZLIB_RAW_COMPRESSION')){
|
||||||
|
$messages[] = "Given version of php-leveldb doesn't support ZLIB_RAW compression (use https://github.com/pmmp/php-leveldb)";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$chunkutils2_version = phpversion("chunkutils2");
|
$chunkutils2_version = phpversion("chunkutils2");
|
||||||
@ -142,6 +146,10 @@ namespace pocketmine {
|
|||||||
$messages[] = "The native PocketMine extension is no longer supported.";
|
$messages[] = "The native PocketMine extension is no longer supported.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!defined('AF_INET6')){
|
||||||
|
$messages[] = "IPv6 support is required, but your PHP binary was built without IPv6 support.";
|
||||||
|
}
|
||||||
|
|
||||||
return $messages;
|
return $messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,6 +213,8 @@ JIT_WARNING
|
|||||||
}
|
}
|
||||||
critical_error("PHP binary used: " . $binary);
|
critical_error("PHP binary used: " . $binary);
|
||||||
critical_error("Loaded php.ini: " . (($file = php_ini_loaded_file()) !== false ? $file : "none"));
|
critical_error("Loaded php.ini: " . (($file = php_ini_loaded_file()) !== false ? $file : "none"));
|
||||||
|
$phprc = getenv("PHPRC");
|
||||||
|
critical_error("Value of PHPRC environment variable: " . ($phprc === false ? "" : $phprc));
|
||||||
critical_error("Please recompile PHP with the needed configuration, or refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html.");
|
critical_error("Please recompile PHP with the needed configuration, or refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html.");
|
||||||
echo PHP_EOL;
|
echo PHP_EOL;
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -214,20 +224,13 @@ JIT_WARNING
|
|||||||
error_reporting(-1);
|
error_reporting(-1);
|
||||||
set_ini_entries();
|
set_ini_entries();
|
||||||
|
|
||||||
$opts = getopt("", ["bootstrap:"]);
|
|
||||||
if(isset($opts["bootstrap"])){
|
|
||||||
$bootstrap = ($real = realpath($opts["bootstrap"])) !== false ? $real : $opts["bootstrap"];
|
|
||||||
}else{
|
|
||||||
$bootstrap = dirname(__FILE__, 2) . '/vendor/autoload.php';
|
$bootstrap = dirname(__FILE__, 2) . '/vendor/autoload.php';
|
||||||
}
|
if(!is_file($bootstrap)){
|
||||||
|
|
||||||
if($bootstrap === false or !is_file($bootstrap)){
|
|
||||||
critical_error("Composer autoloader not found at " . $bootstrap);
|
critical_error("Composer autoloader not found at " . $bootstrap);
|
||||||
critical_error("Please install/update Composer dependencies or use provided builds.");
|
critical_error("Please install/update Composer dependencies or use provided builds.");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
|
require_once($bootstrap);
|
||||||
require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH);
|
|
||||||
|
|
||||||
$composerGitHash = InstalledVersions::getReference('pocketmine/pocketmine-mp');
|
$composerGitHash = InstalledVersions::getReference('pocketmine/pocketmine-mp');
|
||||||
if($composerGitHash !== null){
|
if($composerGitHash !== null){
|
||||||
@ -250,8 +253,9 @@ JIT_WARNING
|
|||||||
|
|
||||||
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]);
|
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]);
|
||||||
|
|
||||||
$dataPath = isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR;
|
$cwd = Utils::assumeNotFalse(realpath(Utils::assumeNotFalse(getcwd())));
|
||||||
$pluginPath = isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR;
|
$dataPath = isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : $cwd . DIRECTORY_SEPARATOR;
|
||||||
|
$pluginPath = isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : $cwd . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR;
|
||||||
Filesystem::addCleanedPath($pluginPath, Filesystem::CLEAN_PATH_PLUGINS_PREFIX);
|
Filesystem::addCleanedPath($pluginPath, Filesystem::CLEAN_PATH_PLUGINS_PREFIX);
|
||||||
|
|
||||||
if(!file_exists($dataPath)){
|
if(!file_exists($dataPath)){
|
||||||
@ -283,7 +287,7 @@ JIT_WARNING
|
|||||||
|
|
||||||
$exitCode = 0;
|
$exitCode = 0;
|
||||||
do{
|
do{
|
||||||
if(!file_exists(Path::join($dataPath, "server.properties")) and !isset($opts["no-wizard"])){
|
if(!file_exists(Path::join($dataPath, "server.properties")) && !isset($opts["no-wizard"])){
|
||||||
$installer = new SetupWizard($dataPath);
|
$installer = new SetupWizard($dataPath);
|
||||||
if(!$installer->run()){
|
if(!$installer->run()){
|
||||||
$exitCode = -1;
|
$exitCode = -1;
|
||||||
@ -307,7 +311,7 @@ JIT_WARNING
|
|||||||
|
|
||||||
if(ThreadManager::getInstance()->stopAll() > 0){
|
if(ThreadManager::getInstance()->stopAll() > 0){
|
||||||
$logger->debug("Some threads could not be stopped, performing a force-kill");
|
$logger->debug("Some threads could not be stopped, performing a force-kill");
|
||||||
Process::kill(Process::pid());
|
Process::kill(Process::pid(), true);
|
||||||
}
|
}
|
||||||
}while(false);
|
}while(false);
|
||||||
|
|
||||||
|
492
src/Server.php
492
src/Server.php
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -34,12 +34,14 @@ use pocketmine\console\ConsoleCommandSender;
|
|||||||
use pocketmine\console\ConsoleReaderThread;
|
use pocketmine\console\ConsoleReaderThread;
|
||||||
use pocketmine\crafting\CraftingManager;
|
use pocketmine\crafting\CraftingManager;
|
||||||
use pocketmine\crafting\CraftingManagerFromDataHelper;
|
use pocketmine\crafting\CraftingManagerFromDataHelper;
|
||||||
use pocketmine\data\java\GameModeIdMap;
|
use pocketmine\crash\CrashDump;
|
||||||
|
use pocketmine\crash\CrashDumpRenderer;
|
||||||
use pocketmine\entity\EntityDataHelper;
|
use pocketmine\entity\EntityDataHelper;
|
||||||
use pocketmine\entity\Location;
|
use pocketmine\entity\Location;
|
||||||
use pocketmine\event\HandlerListManager;
|
use pocketmine\event\HandlerListManager;
|
||||||
use pocketmine\event\player\PlayerCreationEvent;
|
use pocketmine\event\player\PlayerCreationEvent;
|
||||||
use pocketmine\event\player\PlayerDataSaveEvent;
|
use pocketmine\event\player\PlayerDataSaveEvent;
|
||||||
|
use pocketmine\event\player\PlayerLoginEvent;
|
||||||
use pocketmine\event\server\CommandEvent;
|
use pocketmine\event\server\CommandEvent;
|
||||||
use pocketmine\event\server\DataPacketSendEvent;
|
use pocketmine\event\server\DataPacketSendEvent;
|
||||||
use pocketmine\event\server\QueryRegenerateEvent;
|
use pocketmine\event\server\QueryRegenerateEvent;
|
||||||
@ -63,6 +65,7 @@ use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
|||||||
use pocketmine\network\mcpe\protocol\serializer\PacketBatch;
|
use pocketmine\network\mcpe\protocol\serializer\PacketBatch;
|
||||||
use pocketmine\network\mcpe\raklib\RakLibInterface;
|
use pocketmine\network\mcpe\raklib\RakLibInterface;
|
||||||
use pocketmine\network\Network;
|
use pocketmine\network\Network;
|
||||||
|
use pocketmine\network\NetworkInterfaceStartException;
|
||||||
use pocketmine\network\query\DedicatedQueryNetworkInterface;
|
use pocketmine\network\query\DedicatedQueryNetworkInterface;
|
||||||
use pocketmine\network\query\QueryHandler;
|
use pocketmine\network\query\QueryHandler;
|
||||||
use pocketmine\network\query\QueryInfo;
|
use pocketmine\network\query\QueryInfo;
|
||||||
@ -80,6 +83,8 @@ use pocketmine\plugin\PluginGraylist;
|
|||||||
use pocketmine\plugin\PluginManager;
|
use pocketmine\plugin\PluginManager;
|
||||||
use pocketmine\plugin\PluginOwned;
|
use pocketmine\plugin\PluginOwned;
|
||||||
use pocketmine\plugin\ScriptPluginLoader;
|
use pocketmine\plugin\ScriptPluginLoader;
|
||||||
|
use pocketmine\promise\Promise;
|
||||||
|
use pocketmine\promise\PromiseResolver;
|
||||||
use pocketmine\resourcepacks\ResourcePackManager;
|
use pocketmine\resourcepacks\ResourcePackManager;
|
||||||
use pocketmine\scheduler\AsyncPool;
|
use pocketmine\scheduler\AsyncPool;
|
||||||
use pocketmine\snooze\SleeperHandler;
|
use pocketmine\snooze\SleeperHandler;
|
||||||
@ -96,7 +101,7 @@ use pocketmine\utils\MainLogger;
|
|||||||
use pocketmine\utils\NotCloneable;
|
use pocketmine\utils\NotCloneable;
|
||||||
use pocketmine\utils\NotSerializable;
|
use pocketmine\utils\NotSerializable;
|
||||||
use pocketmine\utils\Process;
|
use pocketmine\utils\Process;
|
||||||
use pocketmine\utils\Promise;
|
use pocketmine\utils\SignalHandler;
|
||||||
use pocketmine\utils\Terminal;
|
use pocketmine\utils\Terminal;
|
||||||
use pocketmine\utils\TextFormat;
|
use pocketmine\utils\TextFormat;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
@ -105,26 +110,30 @@ use pocketmine\world\format\io\WorldProviderManager;
|
|||||||
use pocketmine\world\format\io\WritableWorldProviderManagerEntry;
|
use pocketmine\world\format\io\WritableWorldProviderManagerEntry;
|
||||||
use pocketmine\world\generator\Generator;
|
use pocketmine\world\generator\Generator;
|
||||||
use pocketmine\world\generator\GeneratorManager;
|
use pocketmine\world\generator\GeneratorManager;
|
||||||
|
use pocketmine\world\generator\InvalidGeneratorOptionsException;
|
||||||
use pocketmine\world\World;
|
use pocketmine\world\World;
|
||||||
use pocketmine\world\WorldCreationOptions;
|
use pocketmine\world\WorldCreationOptions;
|
||||||
use pocketmine\world\WorldManager;
|
use pocketmine\world\WorldManager;
|
||||||
use Ramsey\Uuid\UuidInterface;
|
use Ramsey\Uuid\UuidInterface;
|
||||||
use Webmozart\PathUtil\Path;
|
use Webmozart\PathUtil\Path;
|
||||||
use function array_shift;
|
|
||||||
use function array_sum;
|
use function array_sum;
|
||||||
use function base64_encode;
|
use function base64_encode;
|
||||||
use function cli_set_process_title;
|
use function cli_set_process_title;
|
||||||
use function copy;
|
use function copy;
|
||||||
use function count;
|
use function count;
|
||||||
use function explode;
|
use function date;
|
||||||
|
use function fclose;
|
||||||
use function file_exists;
|
use function file_exists;
|
||||||
use function file_get_contents;
|
use function file_get_contents;
|
||||||
use function file_put_contents;
|
use function file_put_contents;
|
||||||
use function filemtime;
|
use function filemtime;
|
||||||
|
use function fopen;
|
||||||
use function get_class;
|
use function get_class;
|
||||||
use function implode;
|
|
||||||
use function ini_set;
|
use function ini_set;
|
||||||
use function is_array;
|
use function is_array;
|
||||||
|
use function is_dir;
|
||||||
|
use function is_object;
|
||||||
|
use function is_resource;
|
||||||
use function is_string;
|
use function is_string;
|
||||||
use function json_decode;
|
use function json_decode;
|
||||||
use function max;
|
use function max;
|
||||||
@ -169,6 +178,12 @@ class Server{
|
|||||||
public const BROADCAST_CHANNEL_ADMINISTRATIVE = "pocketmine.broadcast.admin";
|
public const BROADCAST_CHANNEL_ADMINISTRATIVE = "pocketmine.broadcast.admin";
|
||||||
public const BROADCAST_CHANNEL_USERS = "pocketmine.broadcast.user";
|
public const BROADCAST_CHANNEL_USERS = "pocketmine.broadcast.user";
|
||||||
|
|
||||||
|
public const DEFAULT_SERVER_NAME = VersionInfo::NAME . " Server";
|
||||||
|
public const DEFAULT_MAX_PLAYERS = 20;
|
||||||
|
public const DEFAULT_PORT_IPV4 = 19132;
|
||||||
|
public const DEFAULT_PORT_IPV6 = 19133;
|
||||||
|
public const DEFAULT_MAX_VIEW_DISTANCE = 16;
|
||||||
|
|
||||||
private static ?Server $instance = null;
|
private static ?Server $instance = null;
|
||||||
|
|
||||||
private SleeperHandler $tickSleeper;
|
private SleeperHandler $tickSleeper;
|
||||||
@ -208,8 +223,6 @@ class Server{
|
|||||||
|
|
||||||
private int $sendUsageTicker = 0;
|
private int $sendUsageTicker = 0;
|
||||||
|
|
||||||
private \AttachableThreadedLogger $logger;
|
|
||||||
|
|
||||||
private MemoryManager $memoryManager;
|
private MemoryManager $memoryManager;
|
||||||
|
|
||||||
private ConsoleReaderThread $console;
|
private ConsoleReaderThread $console;
|
||||||
@ -234,7 +247,6 @@ class Server{
|
|||||||
|
|
||||||
private UuidInterface $serverID;
|
private UuidInterface $serverID;
|
||||||
|
|
||||||
private \DynamicClassLoader $autoloader;
|
|
||||||
private string $dataPath;
|
private string $dataPath;
|
||||||
private string $pluginPath;
|
private string $pluginPath;
|
||||||
|
|
||||||
@ -251,6 +263,8 @@ class Server{
|
|||||||
/** @var Player[] */
|
/** @var Player[] */
|
||||||
private array $playerList = [];
|
private array $playerList = [];
|
||||||
|
|
||||||
|
private SignalHandler $signalHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var CommandSender[][]
|
* @var CommandSender[][]
|
||||||
* @phpstan-var array<string, array<int, CommandSender>>
|
* @phpstan-var array<string, array<int, CommandSender>>
|
||||||
@ -313,11 +327,15 @@ class Server{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getPort() : int{
|
public function getPort() : int{
|
||||||
return $this->configGroup->getConfigInt("server-port", 19132);
|
return $this->configGroup->getConfigInt("server-port", self::DEFAULT_PORT_IPV4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPortV6() : int{
|
||||||
|
return $this->configGroup->getConfigInt("server-portv6", self::DEFAULT_PORT_IPV6);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getViewDistance() : int{
|
public function getViewDistance() : int{
|
||||||
return max(2, $this->configGroup->getConfigInt("view-distance", 8));
|
return max(2, $this->configGroup->getConfigInt("view-distance", self::DEFAULT_MAX_VIEW_DISTANCE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -332,12 +350,17 @@ class Server{
|
|||||||
return $str !== "" ? $str : "0.0.0.0";
|
return $str !== "" ? $str : "0.0.0.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getIpV6() : string{
|
||||||
|
$str = $this->configGroup->getConfigString("server-ipv6");
|
||||||
|
return $str !== "" ? $str : "::";
|
||||||
|
}
|
||||||
|
|
||||||
public function getServerUniqueId() : UuidInterface{
|
public function getServerUniqueId() : UuidInterface{
|
||||||
return $this->serverID;
|
return $this->serverID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getGamemode() : GameMode{
|
public function getGamemode() : GameMode{
|
||||||
return GameModeIdMap::getInstance()->fromId($this->configGroup->getConfigInt("gamemode", 0)) ?? GameMode::SURVIVAL();
|
return GameMode::fromString($this->configGroup->getConfigString("gamemode", GameMode::SURVIVAL()->name())) ?? GameMode::SURVIVAL();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getForceGamemode() : bool{
|
public function getForceGamemode() : bool{
|
||||||
@ -360,7 +383,7 @@ class Server{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getMotd() : string{
|
public function getMotd() : string{
|
||||||
return $this->configGroup->getConfigString("motd", VersionInfo::NAME . " Server");
|
return $this->configGroup->getConfigString("motd", self::DEFAULT_SERVER_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLoader() : \DynamicClassLoader{
|
public function getLoader() : \DynamicClassLoader{
|
||||||
@ -517,9 +540,10 @@ class Server{
|
|||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
Timings::$syncPlayerDataSave->time(function() use ($name, $ev) : void{
|
Timings::$syncPlayerDataSave->time(function() use ($name, $ev) : void{
|
||||||
$nbt = new BigEndianNbtSerializer();
|
$nbt = new BigEndianNbtSerializer();
|
||||||
|
$contents = Utils::assumeNotFalse(zlib_encode($nbt->write(new TreeRoot($ev->getSaveData())), ZLIB_ENCODING_GZIP), "zlib_encode() failed unexpectedly");
|
||||||
try{
|
try{
|
||||||
file_put_contents($this->getPlayerDataPath($name), zlib_encode($nbt->write(new TreeRoot($ev->getSaveData())), ZLIB_ENCODING_GZIP));
|
Filesystem::safeFilePutContents($this->getPlayerDataPath($name), $contents);
|
||||||
}catch(\ErrorException $e){
|
}catch(\RuntimeException $e){
|
||||||
$this->logger->critical($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_data_saveError($name, $e->getMessage())));
|
$this->logger->critical($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_data_saveError($name, $e->getMessage())));
|
||||||
$this->logger->logException($e);
|
$this->logger->logException($e);
|
||||||
}
|
}
|
||||||
@ -535,7 +559,7 @@ class Server{
|
|||||||
$ev->call();
|
$ev->call();
|
||||||
$class = $ev->getPlayerClass();
|
$class = $ev->getPlayerClass();
|
||||||
|
|
||||||
if($offlinePlayerData !== null and ($world = $this->worldManager->getWorldByName($offlinePlayerData->getString("Level", ""))) !== null){
|
if($offlinePlayerData !== null && ($world = $this->worldManager->getWorldByName($offlinePlayerData->getString("Level", ""))) !== null){
|
||||||
$playerPos = EntityDataHelper::parseLocation($offlinePlayerData, $world);
|
$playerPos = EntityDataHelper::parseLocation($offlinePlayerData, $world);
|
||||||
$spawn = $playerPos->asVector3();
|
$spawn = $playerPos->asVector3();
|
||||||
}else{
|
}else{
|
||||||
@ -546,11 +570,11 @@ class Server{
|
|||||||
$playerPos = null;
|
$playerPos = null;
|
||||||
$spawn = $world->getSpawnLocation();
|
$spawn = $world->getSpawnLocation();
|
||||||
}
|
}
|
||||||
$playerPromise = new Promise();
|
$playerPromiseResolver = new PromiseResolver();
|
||||||
$world->requestChunkPopulation($spawn->getFloorX() >> Chunk::COORD_BIT_SIZE, $spawn->getFloorZ() >> Chunk::COORD_BIT_SIZE, null)->onCompletion(
|
$world->requestChunkPopulation($spawn->getFloorX() >> Chunk::COORD_BIT_SIZE, $spawn->getFloorZ() >> Chunk::COORD_BIT_SIZE, null)->onCompletion(
|
||||||
function() use ($playerPromise, $class, $session, $playerInfo, $authenticated, $world, $playerPos, $spawn, $offlinePlayerData) : void{
|
function() use ($playerPromiseResolver, $class, $session, $playerInfo, $authenticated, $world, $playerPos, $spawn, $offlinePlayerData) : void{
|
||||||
if(!$session->isConnected()){
|
if(!$session->isConnected()){
|
||||||
$playerPromise->reject();
|
$playerPromiseResolver->reject();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,16 +594,16 @@ class Server{
|
|||||||
if(!$player->hasPlayedBefore()){
|
if(!$player->hasPlayedBefore()){
|
||||||
$player->onGround = true; //TODO: this hack is needed for new players in-air ticks - they don't get detected as on-ground until they move
|
$player->onGround = true; //TODO: this hack is needed for new players in-air ticks - they don't get detected as on-ground until they move
|
||||||
}
|
}
|
||||||
$playerPromise->resolve($player);
|
$playerPromiseResolver->resolve($player);
|
||||||
},
|
},
|
||||||
static function() use ($playerPromise, $session) : void{
|
static function() use ($playerPromiseResolver, $session) : void{
|
||||||
if($session->isConnected()){
|
if($session->isConnected()){
|
||||||
$session->disconnect("Spawn terrain generation failed");
|
$session->disconnect("Spawn terrain generation failed");
|
||||||
}
|
}
|
||||||
$playerPromise->reject();
|
$playerPromiseResolver->reject();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return $playerPromise;
|
return $playerPromiseResolver->getPromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -670,7 +694,13 @@ class Server{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function removeOp(string $name) : void{
|
public function removeOp(string $name) : void{
|
||||||
$this->operators->remove(strtolower($name));
|
$lowercaseName = strtolower($name);
|
||||||
|
foreach($this->operators->getAll() as $operatorName => $_){
|
||||||
|
$operatorName = (string) $operatorName;
|
||||||
|
if($lowercaseName === strtolower($operatorName)){
|
||||||
|
$this->operators->remove($operatorName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(($player = $this->getPlayerExact($name)) !== null){
|
if(($player = $this->getPlayerExact($name)) !== null){
|
||||||
$player->unsetBasePermission(DefaultPermissions::ROOT_OPERATOR);
|
$player->unsetBasePermission(DefaultPermissions::ROOT_OPERATOR);
|
||||||
@ -689,7 +719,7 @@ class Server{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function isWhitelisted(string $name) : bool{
|
public function isWhitelisted(string $name) : bool{
|
||||||
return !$this->hasWhitelist() or $this->operators->exists($name, true) or $this->whitelist->exists($name, true);
|
return !$this->hasWhitelist() || $this->operators->exists($name, true) || $this->whitelist->exists($name, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isOp(string $name) : bool{
|
public function isOp(string $name) : bool{
|
||||||
@ -733,16 +763,24 @@ class Server{
|
|||||||
return self::$instance;
|
return self::$instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __construct(\DynamicClassLoader $autoloader, \AttachableThreadedLogger $logger, string $dataPath, string $pluginPath){
|
public function __construct(
|
||||||
|
private \DynamicClassLoader $autoloader,
|
||||||
|
private \AttachableThreadedLogger $logger,
|
||||||
|
string $dataPath,
|
||||||
|
string $pluginPath
|
||||||
|
){
|
||||||
if(self::$instance !== null){
|
if(self::$instance !== null){
|
||||||
throw new \InvalidStateException("Only one server instance can exist at once");
|
throw new \LogicException("Only one server instance can exist at once");
|
||||||
}
|
}
|
||||||
self::$instance = $this;
|
self::$instance = $this;
|
||||||
$this->startTime = microtime(true);
|
$this->startTime = microtime(true);
|
||||||
|
|
||||||
$this->tickSleeper = new SleeperHandler();
|
$this->tickSleeper = new SleeperHandler();
|
||||||
$this->autoloader = $autoloader;
|
|
||||||
$this->logger = $logger;
|
$this->signalHandler = new SignalHandler(function() : void{
|
||||||
|
$this->logger->info("Received signal interrupt, stopping the server");
|
||||||
|
$this->shutdown();
|
||||||
|
});
|
||||||
|
|
||||||
try{
|
try{
|
||||||
foreach([
|
foreach([
|
||||||
@ -762,7 +800,7 @@ class Server{
|
|||||||
$this->logger->info("Loading server configuration");
|
$this->logger->info("Loading server configuration");
|
||||||
$pocketmineYmlPath = Path::join($this->dataPath, "pocketmine.yml");
|
$pocketmineYmlPath = Path::join($this->dataPath, "pocketmine.yml");
|
||||||
if(!file_exists($pocketmineYmlPath)){
|
if(!file_exists($pocketmineYmlPath)){
|
||||||
$content = file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, "pocketmine.yml"));
|
$content = Utils::assumeNotFalse(file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, "pocketmine.yml")), "Missing required resource file");
|
||||||
if(VersionInfo::IS_DEVELOPMENT_BUILD){
|
if(VersionInfo::IS_DEVELOPMENT_BUILD){
|
||||||
$content = str_replace("preferred-channel: stable", "preferred-channel: beta", $content);
|
$content = str_replace("preferred-channel: stable", "preferred-channel: beta", $content);
|
||||||
}
|
}
|
||||||
@ -772,11 +810,13 @@ class Server{
|
|||||||
$this->configGroup = new ServerConfigGroup(
|
$this->configGroup = new ServerConfigGroup(
|
||||||
new Config($pocketmineYmlPath, Config::YAML, []),
|
new Config($pocketmineYmlPath, Config::YAML, []),
|
||||||
new Config(Path::join($this->dataPath, "server.properties"), Config::PROPERTIES, [
|
new Config(Path::join($this->dataPath, "server.properties"), Config::PROPERTIES, [
|
||||||
"motd" => VersionInfo::NAME . " Server",
|
"motd" => self::DEFAULT_SERVER_NAME,
|
||||||
"server-port" => 19132,
|
"server-port" => self::DEFAULT_PORT_IPV4,
|
||||||
|
"server-portv6" => self::DEFAULT_PORT_IPV6,
|
||||||
|
"enable-ipv6" => true,
|
||||||
"white-list" => false,
|
"white-list" => false,
|
||||||
"max-players" => 20,
|
"max-players" => self::DEFAULT_MAX_PLAYERS,
|
||||||
"gamemode" => 0,
|
"gamemode" => GameMode::SURVIVAL()->name(),
|
||||||
"force-gamemode" => false,
|
"force-gamemode" => false,
|
||||||
"hardcore" => false,
|
"hardcore" => false,
|
||||||
"pvp" => true,
|
"pvp" => true,
|
||||||
@ -787,7 +827,7 @@ class Server{
|
|||||||
"level-type" => "DEFAULT",
|
"level-type" => "DEFAULT",
|
||||||
"enable-query" => true,
|
"enable-query" => true,
|
||||||
"auto-save" => true,
|
"auto-save" => true,
|
||||||
"view-distance" => 8,
|
"view-distance" => self::DEFAULT_MAX_VIEW_DISTANCE,
|
||||||
"xbox-auth" => true,
|
"xbox-auth" => true,
|
||||||
"language" => "eng"
|
"language" => "eng"
|
||||||
])
|
])
|
||||||
@ -821,7 +861,7 @@ class Server{
|
|||||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error3()));
|
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error3()));
|
||||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error4("settings.enable-dev-builds")));
|
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error4("settings.enable-dev-builds")));
|
||||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error5("https://github.com/pmmp/PocketMine-MP/releases")));
|
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error5("https://github.com/pmmp/PocketMine-MP/releases")));
|
||||||
$this->forceShutdown();
|
$this->forceShutdownExit();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -856,7 +896,7 @@ class Server{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$netCompressionLevel = $this->configGroup->getPropertyInt("network.compression-level", 6);
|
$netCompressionLevel = $this->configGroup->getPropertyInt("network.compression-level", 6);
|
||||||
if($netCompressionLevel < 1 or $netCompressionLevel > 9){
|
if($netCompressionLevel < 1 || $netCompressionLevel > 9){
|
||||||
$this->logger->warning("Invalid network compression level $netCompressionLevel set, setting to default 6");
|
$this->logger->warning("Invalid network compression level $netCompressionLevel set, setting to default 6");
|
||||||
$netCompressionLevel = 6;
|
$netCompressionLevel = 6;
|
||||||
}
|
}
|
||||||
@ -873,7 +913,7 @@ class Server{
|
|||||||
|
|
||||||
$bannedTxt = Path::join($this->dataPath, "banned.txt");
|
$bannedTxt = Path::join($this->dataPath, "banned.txt");
|
||||||
$bannedPlayersTxt = Path::join($this->dataPath, "banned-players.txt");
|
$bannedPlayersTxt = Path::join($this->dataPath, "banned-players.txt");
|
||||||
if(file_exists($bannedTxt) and !file_exists($bannedPlayersTxt)){
|
if(file_exists($bannedTxt) && !file_exists($bannedPlayersTxt)){
|
||||||
@rename($bannedTxt, $bannedPlayersTxt);
|
@rename($bannedTxt, $bannedPlayersTxt);
|
||||||
}
|
}
|
||||||
@touch($bannedPlayersTxt);
|
@touch($bannedPlayersTxt);
|
||||||
@ -884,7 +924,7 @@ class Server{
|
|||||||
$this->banByIP = new BanList($bannedIpsTxt);
|
$this->banByIP = new BanList($bannedIpsTxt);
|
||||||
$this->banByIP->load();
|
$this->banByIP->load();
|
||||||
|
|
||||||
$this->maxPlayers = $this->configGroup->getConfigInt("max-players", 20);
|
$this->maxPlayers = $this->configGroup->getConfigInt("max-players", self::DEFAULT_MAX_PLAYERS);
|
||||||
|
|
||||||
$this->onlineMode = $this->configGroup->getConfigBool("xbox-auth", true);
|
$this->onlineMode = $this->configGroup->getConfigBool("xbox-auth", true);
|
||||||
if($this->onlineMode){
|
if($this->onlineMode){
|
||||||
@ -895,7 +935,7 @@ class Server{
|
|||||||
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_authProperty_disabled()));
|
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_authProperty_disabled()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->configGroup->getConfigBool("hardcore", false) and $this->getDifficulty() < World::DIFFICULTY_HARD){
|
if($this->configGroup->getConfigBool("hardcore", false) && $this->getDifficulty() < World::DIFFICULTY_HARD){
|
||||||
$this->configGroup->setConfigInt("difficulty", World::DIFFICULTY_HARD);
|
$this->configGroup->setConfigInt("difficulty", World::DIFFICULTY_HARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -923,7 +963,7 @@ class Server{
|
|||||||
|
|
||||||
$this->commandMap = new SimpleCommandMap($this);
|
$this->commandMap = new SimpleCommandMap($this);
|
||||||
|
|
||||||
$this->craftingManager = CraftingManagerFromDataHelper::make(Path::join(\pocketmine\RESOURCE_PATH, "vanilla", "recipes.json"));
|
$this->craftingManager = CraftingManagerFromDataHelper::make(Path::join(\pocketmine\BEDROCK_DATA_PATH, "recipes.json"));
|
||||||
|
|
||||||
$this->resourceManager = new ResourcePackManager(Path::join($this->getDataPath(), "resource_packs"), $this->logger);
|
$this->resourceManager = new ResourcePackManager(Path::join($this->getDataPath(), "resource_packs"), $this->logger);
|
||||||
|
|
||||||
@ -936,7 +976,7 @@ class Server{
|
|||||||
$pluginGraylist = PluginGraylist::fromArray(yaml_parse(file_get_contents($graylistFile)));
|
$pluginGraylist = PluginGraylist::fromArray(yaml_parse(file_get_contents($graylistFile)));
|
||||||
}catch(\InvalidArgumentException $e){
|
}catch(\InvalidArgumentException $e){
|
||||||
$this->logger->emergency("Failed to load $graylistFile: " . $e->getMessage());
|
$this->logger->emergency("Failed to load $graylistFile: " . $e->getMessage());
|
||||||
$this->forceShutdown();
|
$this->forceShutdownExit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$this->pluginManager = new PluginManager($this, $this->configGroup->getPropertyBool("plugins.legacy-data-dir", true) ? null : Path::join($this->getDataPath(), "plugin_data"), $pluginGraylist);
|
$this->pluginManager = new PluginManager($this, $this->configGroup->getPropertyBool("plugins.legacy-data-dir", true) ? null : Path::join($this->getDataPath(), "plugin_data"), $pluginGraylist);
|
||||||
@ -945,7 +985,7 @@ class Server{
|
|||||||
|
|
||||||
$providerManager = new WorldProviderManager();
|
$providerManager = new WorldProviderManager();
|
||||||
if(
|
if(
|
||||||
($format = $providerManager->getProviderByName($formatName = $this->configGroup->getPropertyString("level-settings.default-format", ""))) !== null and
|
($format = $providerManager->getProviderByName($formatName = $this->configGroup->getPropertyString("level-settings.default-format", ""))) !== null &&
|
||||||
$format instanceof WritableWorldProviderManagerEntry
|
$format instanceof WritableWorldProviderManagerEntry
|
||||||
){
|
){
|
||||||
$providerManager->setDefault($format);
|
$providerManager->setDefault($format);
|
||||||
@ -963,94 +1003,36 @@ class Server{
|
|||||||
|
|
||||||
register_shutdown_function([$this, "crashDump"]);
|
register_shutdown_function([$this, "crashDump"]);
|
||||||
|
|
||||||
$this->pluginManager->loadPlugins($this->pluginPath);
|
$loadErrorCount = 0;
|
||||||
$this->enablePlugins(PluginEnableOrder::STARTUP());
|
$this->pluginManager->loadPlugins($this->pluginPath, $loadErrorCount);
|
||||||
|
if($loadErrorCount > 0){
|
||||||
foreach((array) $this->configGroup->getProperty("worlds", []) as $name => $options){
|
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_plugin_someLoadErrors()));
|
||||||
if($options === null){
|
$this->forceShutdownExit();
|
||||||
$options = [];
|
|
||||||
}elseif(!is_array($options)){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(!$this->worldManager->loadWorld($name, true)){
|
|
||||||
$creationOptions = WorldCreationOptions::create();
|
|
||||||
//TODO: error checking
|
|
||||||
|
|
||||||
if(isset($options["generator"])){
|
|
||||||
$generatorOptions = explode(":", $options["generator"]);
|
|
||||||
$creationOptions->setGeneratorClass(GeneratorManager::getInstance()->getGenerator(array_shift($generatorOptions)));
|
|
||||||
if(count($generatorOptions) > 0){
|
|
||||||
$creationOptions->setGeneratorOptions(implode(":", $generatorOptions));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(isset($options["difficulty"]) && is_string($options["difficulty"])){
|
|
||||||
$creationOptions->setDifficulty(World::getDifficultyFromString($options["difficulty"]));
|
|
||||||
}
|
|
||||||
if(isset($options["preset"]) && is_string($options["preset"])){
|
|
||||||
$creationOptions->setGeneratorOptions($options["preset"]);
|
|
||||||
}
|
|
||||||
if(isset($options["seed"])){
|
|
||||||
$convertedSeed = Generator::convertSeed((string) ($options["seed"] ?? ""));
|
|
||||||
if($convertedSeed !== null){
|
|
||||||
$creationOptions->setSeed($convertedSeed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->worldManager->generateWorld($name, $creationOptions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if($this->worldManager->getDefaultWorld() === null){
|
|
||||||
$default = $this->configGroup->getConfigString("level-name", "world");
|
|
||||||
if(trim($default) == ""){
|
|
||||||
$this->getLogger()->warning("level-name cannot be null, using default");
|
|
||||||
$default = "world";
|
|
||||||
$this->configGroup->setConfigString("level-name", "world");
|
|
||||||
}
|
|
||||||
if(!$this->worldManager->loadWorld($default, true)){
|
|
||||||
$creationOptions = WorldCreationOptions::create()
|
|
||||||
->setGeneratorClass(GeneratorManager::getInstance()->getGenerator($this->configGroup->getConfigString("level-type")))
|
|
||||||
->setGeneratorOptions($this->configGroup->getConfigString("generator-settings"));
|
|
||||||
$convertedSeed = Generator::convertSeed($this->configGroup->getConfigString("level-seed"));
|
|
||||||
if($convertedSeed !== null){
|
|
||||||
$creationOptions->setSeed($convertedSeed);
|
|
||||||
}
|
|
||||||
$this->worldManager->generateWorld($default, $creationOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
$world = $this->worldManager->getWorldByName($default);
|
|
||||||
if($world === null){
|
|
||||||
$this->getLogger()->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_level_defaultError()));
|
|
||||||
$this->forceShutdown();
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$this->worldManager->setDefaultWorld($world);
|
if(!$this->enablePlugins(PluginEnableOrder::STARTUP())){
|
||||||
|
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_plugin_someEnableErrors()));
|
||||||
|
$this->forceShutdownExit();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->enablePlugins(PluginEnableOrder::POSTWORLD());
|
if(!$this->startupPrepareWorlds()){
|
||||||
|
$this->forceShutdownExit();
|
||||||
$useQuery = $this->configGroup->getConfigBool("enable-query", true);
|
return;
|
||||||
if(!$this->network->registerInterface(new RakLibInterface($this)) && $useQuery){
|
|
||||||
//RakLib would normally handle the transport for Query packets
|
|
||||||
//if it's not registered we need to make sure Query still works
|
|
||||||
$this->network->registerInterface(new DedicatedQueryNetworkInterface($this->getIp(), $this->getPort(), new \PrefixedLogger($this->logger, "Dedicated Query Interface")));
|
|
||||||
}
|
|
||||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_networkStart($this->getIp(), (string) $this->getPort())));
|
|
||||||
|
|
||||||
if($useQuery){
|
|
||||||
$this->network->registerRawPacketHandler(new QueryHandler($this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($this->getIPBans()->getEntries() as $entry){
|
if(!$this->enablePlugins(PluginEnableOrder::POSTWORLD())){
|
||||||
$this->network->blockAddress($entry->getName(), -1);
|
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_plugin_someEnableErrors()));
|
||||||
|
$this->forceShutdownExit();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->configGroup->getPropertyBool("network.upnp-forwarding", false)){
|
if(!$this->startupPrepareNetworkInterfaces()){
|
||||||
$this->network->registerInterface(new UPnPNetworkInterface($this->logger, Internet::getInternalIP(), $this->getPort()));
|
$this->forceShutdownExit();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->configGroup->getPropertyBool("settings.send-usage", true)){
|
if($this->configGroup->getPropertyBool("anonymous-statistics.enabled", true)){
|
||||||
$this->sendUsageTicker = 6000;
|
$this->sendUsageTicker = 6000;
|
||||||
$this->sendUsage(SendUsageTask::TYPE_OPEN);
|
$this->sendUsage(SendUsageTask::TYPE_OPEN);
|
||||||
}
|
}
|
||||||
@ -1085,6 +1067,169 @@ class Server{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function startupPrepareWorlds() : bool{
|
||||||
|
$getGenerator = function(string $generatorName, string $generatorOptions, string $worldName) : ?string{
|
||||||
|
$generatorEntry = GeneratorManager::getInstance()->getGenerator($generatorName);
|
||||||
|
if($generatorEntry === null){
|
||||||
|
$this->logger->error($this->language->translate(KnownTranslationFactory::pocketmine_level_generationError(
|
||||||
|
$worldName,
|
||||||
|
KnownTranslationFactory::pocketmine_level_unknownGenerator($generatorName)
|
||||||
|
)));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
$generatorEntry->validateGeneratorOptions($generatorOptions);
|
||||||
|
}catch(InvalidGeneratorOptionsException $e){
|
||||||
|
$this->logger->error($this->language->translate(KnownTranslationFactory::pocketmine_level_generationError(
|
||||||
|
$worldName,
|
||||||
|
KnownTranslationFactory::pocketmine_level_invalidGeneratorOptions($generatorOptions, $generatorName, $e->getMessage())
|
||||||
|
)));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return $generatorEntry->getGeneratorClass();
|
||||||
|
};
|
||||||
|
|
||||||
|
$anyWorldFailedToLoad = false;
|
||||||
|
|
||||||
|
foreach((array) $this->configGroup->getProperty("worlds", []) as $name => $options){
|
||||||
|
if($options === null){
|
||||||
|
$options = [];
|
||||||
|
}elseif(!is_array($options)){
|
||||||
|
//TODO: this probably should be an error
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(!$this->worldManager->loadWorld($name, true)){
|
||||||
|
if($this->worldManager->isWorldGenerated($name)){
|
||||||
|
//allow checking if other worlds are loadable, so the user gets all the errors in one go
|
||||||
|
$anyWorldFailedToLoad = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$creationOptions = WorldCreationOptions::create();
|
||||||
|
//TODO: error checking
|
||||||
|
|
||||||
|
$generatorName = $options["generator"] ?? "default";
|
||||||
|
$generatorOptions = isset($options["preset"]) && is_string($options["preset"]) ? $options["preset"] : "";
|
||||||
|
|
||||||
|
$generatorClass = $getGenerator($generatorName, $generatorOptions, $name);
|
||||||
|
if($generatorClass === null){
|
||||||
|
$anyWorldFailedToLoad = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$creationOptions->setGeneratorClass($generatorClass);
|
||||||
|
$creationOptions->setGeneratorOptions($generatorOptions);
|
||||||
|
|
||||||
|
$creationOptions->setDifficulty($this->getDifficulty());
|
||||||
|
if(isset($options["difficulty"]) && is_string($options["difficulty"])){
|
||||||
|
$creationOptions->setDifficulty(World::getDifficultyFromString($options["difficulty"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset($options["seed"])){
|
||||||
|
$convertedSeed = Generator::convertSeed((string) ($options["seed"] ?? ""));
|
||||||
|
if($convertedSeed !== null){
|
||||||
|
$creationOptions->setSeed($convertedSeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->worldManager->generateWorld($name, $creationOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->worldManager->getDefaultWorld() === null){
|
||||||
|
$default = $this->configGroup->getConfigString("level-name", "world");
|
||||||
|
if(trim($default) == ""){
|
||||||
|
$this->getLogger()->warning("level-name cannot be null, using default");
|
||||||
|
$default = "world";
|
||||||
|
$this->configGroup->setConfigString("level-name", "world");
|
||||||
|
}
|
||||||
|
if(!$this->worldManager->loadWorld($default, true)){
|
||||||
|
if($this->worldManager->isWorldGenerated($default)){
|
||||||
|
$this->getLogger()->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_level_defaultError()));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$generatorName = $this->configGroup->getConfigString("level-type");
|
||||||
|
$generatorOptions = $this->configGroup->getConfigString("generator-settings");
|
||||||
|
$generatorClass = $getGenerator($generatorName, $generatorOptions, $default);
|
||||||
|
|
||||||
|
if($generatorClass === null){
|
||||||
|
$this->getLogger()->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_level_defaultError()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$creationOptions = WorldCreationOptions::create()
|
||||||
|
->setGeneratorClass($generatorClass)
|
||||||
|
->setGeneratorOptions($generatorOptions);
|
||||||
|
$convertedSeed = Generator::convertSeed($this->configGroup->getConfigString("level-seed"));
|
||||||
|
if($convertedSeed !== null){
|
||||||
|
$creationOptions->setSeed($convertedSeed);
|
||||||
|
}
|
||||||
|
$creationOptions->setDifficulty($this->getDifficulty());
|
||||||
|
$this->worldManager->generateWorld($default, $creationOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
$world = $this->worldManager->getWorldByName($default);
|
||||||
|
if($world === null){
|
||||||
|
throw new AssumptionFailedError("We just loaded/generated the default world, so it must exist");
|
||||||
|
}
|
||||||
|
$this->worldManager->setDefaultWorld($world);
|
||||||
|
}
|
||||||
|
|
||||||
|
return !$anyWorldFailedToLoad;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function startupPrepareConnectableNetworkInterfaces(string $ip, int $port, bool $ipV6, bool $useQuery) : bool{
|
||||||
|
$prettyIp = $ipV6 ? "[$ip]" : $ip;
|
||||||
|
try{
|
||||||
|
$rakLibRegistered = $this->network->registerInterface(new RakLibInterface($this, $ip, $port, $ipV6));
|
||||||
|
}catch(NetworkInterfaceStartException $e){
|
||||||
|
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_networkStartFailed(
|
||||||
|
$ip,
|
||||||
|
(string) $port,
|
||||||
|
$e->getMessage()
|
||||||
|
)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if($rakLibRegistered){
|
||||||
|
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_networkStart($prettyIp, (string) $port)));
|
||||||
|
}
|
||||||
|
if($useQuery){
|
||||||
|
if(!$rakLibRegistered){
|
||||||
|
//RakLib would normally handle the transport for Query packets
|
||||||
|
//if it's not registered we need to make sure Query still works
|
||||||
|
$this->network->registerInterface(new DedicatedQueryNetworkInterface($ip, $port, $ipV6, new \PrefixedLogger($this->logger, "Dedicated Query Interface")));
|
||||||
|
}
|
||||||
|
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_query_running($prettyIp, (string) $port)));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function startupPrepareNetworkInterfaces() : bool{
|
||||||
|
$useQuery = $this->configGroup->getConfigBool("enable-query", true);
|
||||||
|
|
||||||
|
if(
|
||||||
|
!$this->startupPrepareConnectableNetworkInterfaces($this->getIp(), $this->getPort(), false, $useQuery) ||
|
||||||
|
(
|
||||||
|
$this->configGroup->getConfigBool("enable-ipv6", true) &&
|
||||||
|
!$this->startupPrepareConnectableNetworkInterfaces($this->getIpV6(), $this->getPortV6(), true, $useQuery)
|
||||||
|
)
|
||||||
|
){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($useQuery){
|
||||||
|
$this->network->registerRawPacketHandler(new QueryHandler($this));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($this->getIPBans()->getEntries() as $entry){
|
||||||
|
$this->network->blockAddress($entry->getName(), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->configGroup->getPropertyBool("network.upnp-forwarding", false)){
|
||||||
|
$this->network->registerInterface(new UPnPNetworkInterface($this->logger, Internet::getInternalIP(), $this->getPort()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscribes to a particular message broadcast channel.
|
* Subscribes to a particular message broadcast channel.
|
||||||
* The channel ID can be any arbitrary string.
|
* The channel ID can be any arbitrary string.
|
||||||
@ -1109,7 +1254,7 @@ class Server{
|
|||||||
* Unsubscribes from all broadcast channels.
|
* Unsubscribes from all broadcast channels.
|
||||||
*/
|
*/
|
||||||
public function unsubscribeFromAllBroadcastChannels(CommandSender $subscriber) : void{
|
public function unsubscribeFromAllBroadcastChannels(CommandSender $subscriber) : void{
|
||||||
foreach($this->broadcastSubscribers as $channelId => $recipients){
|
foreach(Utils::stringifyKeys($this->broadcastSubscribers) as $channelId => $recipients){
|
||||||
$this->unsubscribeFromBroadcastChannel($channelId, $subscriber);
|
$this->unsubscribeFromBroadcastChannel($channelId, $subscriber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1267,16 +1412,21 @@ class Server{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enablePlugins(PluginEnableOrder $type) : void{
|
public function enablePlugins(PluginEnableOrder $type) : bool{
|
||||||
|
$allSuccess = true;
|
||||||
foreach($this->pluginManager->getPlugins() as $plugin){
|
foreach($this->pluginManager->getPlugins() as $plugin){
|
||||||
if(!$plugin->isEnabled() and $plugin->getDescription()->getOrder()->equals($type)){
|
if(!$plugin->isEnabled() && $plugin->getDescription()->getOrder()->equals($type)){
|
||||||
$this->pluginManager->enablePlugin($plugin);
|
if(!$this->pluginManager->enablePlugin($plugin)){
|
||||||
|
$allSuccess = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($type->equals(PluginEnableOrder::POSTWORLD())){
|
if($type->equals(PluginEnableOrder::POSTWORLD())){
|
||||||
$this->commandMap->registerServerAliases();
|
$this->commandMap->registerServerAliases();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $allSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1293,20 +1443,22 @@ class Server{
|
|||||||
$commandLine = $ev->getCommand();
|
$commandLine = $ev->getCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->commandMap->dispatch($sender, $commandLine)){
|
return $this->commandMap->dispatch($sender, $commandLine);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$sender->sendMessage(KnownTranslationFactory::commands_generic_notFound()->prefix(TextFormat::RED));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shuts the server down correctly
|
* Shuts the server down correctly
|
||||||
*/
|
*/
|
||||||
public function shutdown() : void{
|
public function shutdown() : void{
|
||||||
|
if($this->isRunning){
|
||||||
$this->isRunning = false;
|
$this->isRunning = false;
|
||||||
|
$this->signalHandler->unregister();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function forceShutdownExit() : void{
|
||||||
|
$this->forceShutdown();
|
||||||
|
Process::kill(Process::pid(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function forceShutdown() : void{
|
public function forceShutdown() : void{
|
||||||
@ -1318,6 +1470,9 @@ class Server{
|
|||||||
echo "\x1b]0;\x07";
|
echo "\x1b]0;\x07";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($this->isRunning){
|
||||||
|
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_forcingShutdown()));
|
||||||
|
}
|
||||||
try{
|
try{
|
||||||
if(!$this->isRunning()){
|
if(!$this->isRunning()){
|
||||||
$this->sendUsage(SendUsageTask::TYPE_CLOSE);
|
$this->sendUsage(SendUsageTask::TYPE_CLOSE);
|
||||||
@ -1371,7 +1526,7 @@ class Server{
|
|||||||
}catch(\Throwable $e){
|
}catch(\Throwable $e){
|
||||||
$this->logger->logException($e);
|
$this->logger->logException($e);
|
||||||
$this->logger->emergency("Crashed while crashing, killing process");
|
$this->logger->emergency("Crashed while crashing, killing process");
|
||||||
@Process::kill(Process::pid());
|
@Process::kill(Process::pid(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1416,6 +1571,25 @@ class Server{
|
|||||||
$this->crashDump();
|
$this->crashDump();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function writeCrashDumpFile(CrashDump $dump) : string{
|
||||||
|
$crashFolder = Path::join($this->getDataPath(), "crashdumps");
|
||||||
|
if(!is_dir($crashFolder)){
|
||||||
|
mkdir($crashFolder);
|
||||||
|
}
|
||||||
|
$crashDumpPath = Path::join($crashFolder, date("D_M_j-H.i.s-T_Y", (int) $dump->getData()->time) . ".log");
|
||||||
|
|
||||||
|
$fp = @fopen($crashDumpPath, "wb");
|
||||||
|
if(!is_resource($fp)){
|
||||||
|
throw new \RuntimeException("Unable to open new file to generate crashdump");
|
||||||
|
}
|
||||||
|
$writer = new CrashDumpRenderer($fp, $dump->getData());
|
||||||
|
$writer->renderHumanReadable();
|
||||||
|
$dump->encodeData($writer);
|
||||||
|
|
||||||
|
fclose($fp);
|
||||||
|
return $crashDumpPath;
|
||||||
|
}
|
||||||
|
|
||||||
public function crashDump() : void{
|
public function crashDump() : void{
|
||||||
while(@ob_end_flush()){}
|
while(@ob_end_flush()){}
|
||||||
if(!$this->isRunning){
|
if(!$this->isRunning){
|
||||||
@ -1430,34 +1604,37 @@ class Server{
|
|||||||
ini_set("memory_limit", '-1'); //Fix error dump not dumped on memory problems
|
ini_set("memory_limit", '-1'); //Fix error dump not dumped on memory problems
|
||||||
try{
|
try{
|
||||||
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_create()));
|
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_create()));
|
||||||
$dump = new CrashDump($this);
|
$dump = new CrashDump($this, $this->pluginManager ?? null);
|
||||||
|
|
||||||
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_submit($dump->getPath())));
|
$crashDumpPath = $this->writeCrashDumpFile($dump);
|
||||||
|
|
||||||
|
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_submit($crashDumpPath)));
|
||||||
|
|
||||||
if($this->configGroup->getPropertyBool("auto-report.enabled", true)){
|
if($this->configGroup->getPropertyBool("auto-report.enabled", true)){
|
||||||
$report = true;
|
$report = true;
|
||||||
|
|
||||||
$stamp = Path::join($this->getDataPath(), "crashdumps", ".last_crash");
|
$stamp = Path::join($this->getDataPath(), "crashdumps", ".last_crash");
|
||||||
$crashInterval = 120; //2 minutes
|
$crashInterval = 120; //2 minutes
|
||||||
if(file_exists($stamp) and !($report = (filemtime($stamp) + $crashInterval < time()))){
|
if(($lastReportTime = @filemtime($stamp)) !== false && $lastReportTime + $crashInterval >= time()){
|
||||||
|
$report = false;
|
||||||
$this->logger->debug("Not sending crashdump due to last crash less than $crashInterval seconds ago");
|
$this->logger->debug("Not sending crashdump due to last crash less than $crashInterval seconds ago");
|
||||||
}
|
}
|
||||||
@touch($stamp); //update file timestamp
|
@touch($stamp); //update file timestamp
|
||||||
|
|
||||||
$plugin = $dump->getData()["plugin"];
|
$plugin = $dump->getData()->plugin;
|
||||||
if(is_string($plugin)){
|
if($plugin !== ""){
|
||||||
$p = $this->pluginManager->getPlugin($plugin);
|
$p = $this->pluginManager->getPlugin($plugin);
|
||||||
if($p instanceof Plugin and !($p->getPluginLoader() instanceof PharPluginLoader)){
|
if($p instanceof Plugin && !($p->getPluginLoader() instanceof PharPluginLoader)){
|
||||||
$this->logger->debug("Not sending crashdump due to caused by non-phar plugin");
|
$this->logger->debug("Not sending crashdump due to caused by non-phar plugin");
|
||||||
$report = false;
|
$report = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($dump->getData()["error"]["type"] === \ParseError::class){
|
if($dump->getData()->error["type"] === \ParseError::class){
|
||||||
$report = false;
|
$report = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strrpos(VersionInfo::GIT_HASH(), "-dirty") !== false or VersionInfo::GIT_HASH() === str_repeat("00", 20)){
|
if(strrpos(VersionInfo::GIT_HASH(), "-dirty") !== false || VersionInfo::GIT_HASH() === str_repeat("00", 20)){
|
||||||
$this->logger->debug("Not sending crashdump due to locally modified");
|
$this->logger->debug("Not sending crashdump due to locally modified");
|
||||||
$report = false; //Don't send crashdumps for locally modified builds
|
$report = false; //Don't send crashdumps for locally modified builds
|
||||||
}
|
}
|
||||||
@ -1472,8 +1649,8 @@ class Server{
|
|||||||
"reportPaste" => base64_encode($dump->getEncodedData())
|
"reportPaste" => base64_encode($dump->getEncodedData())
|
||||||
], 10, [], $postUrlError);
|
], 10, [], $postUrlError);
|
||||||
|
|
||||||
if($reply !== null and ($data = json_decode($reply->getBody())) !== null){
|
if($reply !== null && is_object($data = json_decode($reply->getBody()))){
|
||||||
if(isset($data->crashId) and isset($data->crashUrl)){
|
if(isset($data->crashId) && isset($data->crashUrl)){
|
||||||
$reportId = $data->crashId;
|
$reportId = $data->crashId;
|
||||||
$reportUrl = $data->crashUrl;
|
$reportUrl = $data->crashUrl;
|
||||||
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_archive($reportUrl, (string) $reportId)));
|
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_archive($reportUrl, (string) $reportId)));
|
||||||
@ -1501,7 +1678,7 @@ class Server{
|
|||||||
echo "--- Waiting $spacing seconds to throttle automatic restart (you can kill the process safely now) ---" . PHP_EOL;
|
echo "--- Waiting $spacing seconds to throttle automatic restart (you can kill the process safely now) ---" . PHP_EOL;
|
||||||
sleep($spacing);
|
sleep($spacing);
|
||||||
}
|
}
|
||||||
@Process::kill(Process::pid());
|
@Process::kill(Process::pid(), true);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1527,7 +1704,28 @@ class Server{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addOnlinePlayer(Player $player) : void{
|
public function addOnlinePlayer(Player $player) : bool{
|
||||||
|
$ev = new PlayerLoginEvent($player, "Plugin reason");
|
||||||
|
$ev->call();
|
||||||
|
if($ev->isCancelled() || !$player->isConnected()){
|
||||||
|
$player->disconnect($ev->getKickMessage());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$session = $player->getNetworkSession();
|
||||||
|
$position = $player->getPosition();
|
||||||
|
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_player_logIn(
|
||||||
|
TextFormat::AQUA . $player->getName() . TextFormat::WHITE,
|
||||||
|
$session->getIp(),
|
||||||
|
(string) $session->getPort(),
|
||||||
|
(string) $player->getId(),
|
||||||
|
$position->getWorld()->getDisplayName(),
|
||||||
|
(string) round($position->x, 4),
|
||||||
|
(string) round($position->y, 4),
|
||||||
|
(string) round($position->z, 4)
|
||||||
|
)));
|
||||||
|
|
||||||
foreach($this->playerList as $p){
|
foreach($this->playerList as $p){
|
||||||
$p->getNetworkSession()->onPlayerAdded($player);
|
$p->getNetworkSession()->onPlayerAdded($player);
|
||||||
}
|
}
|
||||||
@ -1537,6 +1735,8 @@ class Server{
|
|||||||
if($this->sendUsageTicker > 0){
|
if($this->sendUsageTicker > 0){
|
||||||
$this->uniquePlayers[$rawUUID] = $rawUUID;
|
$this->uniquePlayers[$rawUUID] = $rawUUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function removeOnlinePlayer(Player $player) : void{
|
public function removeOnlinePlayer(Player $player) : void{
|
||||||
@ -1636,7 +1836,7 @@ class Server{
|
|||||||
$this->network->getBandwidthTracker()->rotateAverageHistory();
|
$this->network->getBandwidthTracker()->rotateAverageHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->sendUsageTicker > 0 and --$this->sendUsageTicker === 0){
|
if($this->sendUsageTicker > 0 && --$this->sendUsageTicker === 0){
|
||||||
$this->sendUsageTicker = 6000;
|
$this->sendUsageTicker = 6000;
|
||||||
$this->sendUsage(SendUsageTask::TYPE_STATUS);
|
$this->sendUsage(SendUsageTask::TYPE_STATUS);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -27,25 +27,21 @@ use pocketmine\utils\Config;
|
|||||||
use function array_key_exists;
|
use function array_key_exists;
|
||||||
use function getopt;
|
use function getopt;
|
||||||
use function is_bool;
|
use function is_bool;
|
||||||
|
use function is_int;
|
||||||
|
use function is_string;
|
||||||
use function strtolower;
|
use function strtolower;
|
||||||
|
|
||||||
final class ServerConfigGroup{
|
final class ServerConfigGroup{
|
||||||
|
|
||||||
/** @var Config */
|
|
||||||
private $pocketmineYml;
|
|
||||||
/** @var Config */
|
|
||||||
private $serverProperties;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var mixed[]
|
* @var mixed[]
|
||||||
* @phpstan-var array<string, mixed>
|
* @phpstan-var array<string, mixed>
|
||||||
*/
|
*/
|
||||||
private $propertyCache = [];
|
private array $propertyCache = [];
|
||||||
|
|
||||||
public function __construct(Config $pocketmineYml, Config $serverProperties){
|
public function __construct(
|
||||||
$this->pocketmineYml = $pocketmineYml;
|
private Config $pocketmineYml,
|
||||||
$this->serverProperties = $serverProperties;
|
private Config $serverProperties
|
||||||
}
|
){}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed $defaultValue
|
* @param mixed $defaultValue
|
||||||
@ -110,10 +106,13 @@ final class ServerConfigGroup{
|
|||||||
}else{
|
}else{
|
||||||
$value = $this->serverProperties->exists($variable) ? $this->serverProperties->get($variable) : $defaultValue;
|
$value = $this->serverProperties->exists($variable) ? $this->serverProperties->get($variable) : $defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_bool($value)){
|
if(is_bool($value)){
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
if(is_int($value)){
|
||||||
|
return $value !== 0;
|
||||||
|
}
|
||||||
|
if(is_string($value)){
|
||||||
switch(strtolower($value)){
|
switch(strtolower($value)){
|
||||||
case "on":
|
case "on":
|
||||||
case "true":
|
case "true":
|
||||||
@ -121,6 +120,7 @@ final class ServerConfigGroup{
|
|||||||
case "yes":
|
case "yes":
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -25,21 +25,21 @@ namespace pocketmine;
|
|||||||
|
|
||||||
use pocketmine\utils\Git;
|
use pocketmine\utils\Git;
|
||||||
use pocketmine\utils\VersionString;
|
use pocketmine\utils\VersionString;
|
||||||
|
use function is_array;
|
||||||
|
use function is_int;
|
||||||
use function str_repeat;
|
use function str_repeat;
|
||||||
|
|
||||||
final class VersionInfo{
|
final class VersionInfo{
|
||||||
public const NAME = "PocketMine-MP";
|
public const NAME = "PocketMine-MP";
|
||||||
public const BASE_VERSION = "4.0.0-BETA3";
|
public const BASE_VERSION = "4.5.0";
|
||||||
public const IS_DEVELOPMENT_BUILD = false;
|
public const IS_DEVELOPMENT_BUILD = false;
|
||||||
public const BUILD_NUMBER = 0;
|
public const BUILD_CHANNEL = "stable";
|
||||||
public const BUILD_CHANNEL = "beta";
|
|
||||||
|
|
||||||
private function __construct(){
|
private function __construct(){
|
||||||
//NOOP
|
//NOOP
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var string|null */
|
private static ?string $gitHash = null;
|
||||||
private static $gitHash = null;
|
|
||||||
|
|
||||||
public static function GIT_HASH() : string{
|
public static function GIT_HASH() : string{
|
||||||
if(self::$gitHash === null){
|
if(self::$gitHash === null){
|
||||||
@ -61,12 +61,28 @@ final class VersionInfo{
|
|||||||
return self::$gitHash;
|
return self::$gitHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var VersionString|null */
|
private static ?int $buildNumber = null;
|
||||||
private static $fullVersion = null;
|
|
||||||
|
public static function BUILD_NUMBER() : int{
|
||||||
|
if(self::$buildNumber === null){
|
||||||
|
self::$buildNumber = 0;
|
||||||
|
if(\Phar::running(true) !== ""){
|
||||||
|
$phar = new \Phar(\Phar::running(false));
|
||||||
|
$meta = $phar->getMetadata();
|
||||||
|
if(is_array($meta) && isset($meta["build"]) && is_int($meta["build"])){
|
||||||
|
self::$buildNumber = $meta["build"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$buildNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ?VersionString $fullVersion = null;
|
||||||
|
|
||||||
public static function VERSION() : VersionString{
|
public static function VERSION() : VersionString{
|
||||||
if(self::$fullVersion === null){
|
if(self::$fullVersion === null){
|
||||||
self::$fullVersion = new VersionString(self::BASE_VERSION, self::IS_DEVELOPMENT_BUILD, self::BUILD_NUMBER);
|
self::$fullVersion = new VersionString(self::BASE_VERSION, self::IS_DEVELOPMENT_BUILD, self::BUILD_NUMBER());
|
||||||
}
|
}
|
||||||
return self::$fullVersion;
|
return self::$fullVersion;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,22 +17,16 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Air block
|
* Air block
|
||||||
*/
|
*/
|
||||||
class Air extends Transparent{
|
class Air extends Flowable{
|
||||||
|
|
||||||
public function canBeFlowedInto() : bool{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function canBeReplaced() : bool{
|
public function canBeReplaced() : bool{
|
||||||
return true;
|
return true;
|
||||||
@ -41,15 +35,4 @@ class Air extends Transparent{
|
|||||||
public function canBePlaced() : bool{
|
public function canBePlaced() : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isSolid() : bool{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return AxisAlignedBB[]
|
|
||||||
*/
|
|
||||||
protected function recalculateCollisionBoxes() : array{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -28,6 +28,7 @@ use pocketmine\block\utils\BlockDataSerializer;
|
|||||||
use pocketmine\block\utils\Fallable;
|
use pocketmine\block\utils\Fallable;
|
||||||
use pocketmine\block\utils\FallableTrait;
|
use pocketmine\block\utils\FallableTrait;
|
||||||
use pocketmine\block\utils\HorizontalFacingTrait;
|
use pocketmine\block\utils\HorizontalFacingTrait;
|
||||||
|
use pocketmine\block\utils\SupportType;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Facing;
|
use pocketmine\math\Facing;
|
||||||
@ -39,7 +40,11 @@ class Anvil extends Transparent implements Fallable{
|
|||||||
use FallableTrait;
|
use FallableTrait;
|
||||||
use HorizontalFacingTrait;
|
use HorizontalFacingTrait;
|
||||||
|
|
||||||
private int $damage = 0;
|
public const UNDAMAGED = 0;
|
||||||
|
public const SLIGHTLY_DAMAGED = 1;
|
||||||
|
public const VERY_DAMAGED = 2;
|
||||||
|
|
||||||
|
private int $damage = self::UNDAMAGED;
|
||||||
|
|
||||||
protected function writeStateToMeta() : int{
|
protected function writeStateToMeta() : int{
|
||||||
return BlockDataSerializer::writeLegacyHorizontalFacing($this->facing) | ($this->damage << 2);
|
return BlockDataSerializer::writeLegacyHorizontalFacing($this->facing) | ($this->damage << 2);
|
||||||
@ -47,7 +52,7 @@ class Anvil extends Transparent implements Fallable{
|
|||||||
|
|
||||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||||
$this->facing = BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x3);
|
$this->facing = BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x3);
|
||||||
$this->damage = BlockDataSerializer::readBoundedInt("damage", $stateMeta >> 2, 0, 2);
|
$this->damage = BlockDataSerializer::readBoundedInt("damage", $stateMeta >> 2, self::UNDAMAGED, self::VERY_DAMAGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStateBitmask() : int{
|
public function getStateBitmask() : int{
|
||||||
@ -62,8 +67,8 @@ class Anvil extends Transparent implements Fallable{
|
|||||||
|
|
||||||
/** @return $this */
|
/** @return $this */
|
||||||
public function setDamage(int $damage) : self{
|
public function setDamage(int $damage) : self{
|
||||||
if($damage < 0 || $damage > 2){
|
if($damage < self::UNDAMAGED || $damage > self::VERY_DAMAGED){
|
||||||
throw new \InvalidArgumentException("Damage must be in range 0-2");
|
throw new \InvalidArgumentException("Damage must be in range " . self::UNDAMAGED . " ... " . self::VERY_DAMAGED);
|
||||||
}
|
}
|
||||||
$this->damage = $damage;
|
$this->damage = $damage;
|
||||||
return $this;
|
return $this;
|
||||||
@ -76,6 +81,10 @@ class Anvil extends Transparent implements Fallable{
|
|||||||
return [AxisAlignedBB::one()->squash(Facing::axis(Facing::rotateY($this->facing, false)), 1 / 8)];
|
return [AxisAlignedBB::one()->squash(Facing::axis(Facing::rotateY($this->facing, false)), 1 / 8)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
|
|
||||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
if($player instanceof Player){
|
if($player instanceof Player){
|
||||||
$player->setCurrentWindow(new AnvilInventory($this->position));
|
$player->setCurrentWindow(new AnvilInventory($this->position));
|
||||||
|
@ -17,13 +17,14 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\utils\BlockDataSerializer;
|
use pocketmine\block\utils\BlockDataSerializer;
|
||||||
|
use pocketmine\block\utils\SupportType;
|
||||||
use pocketmine\event\block\StructureGrowEvent;
|
use pocketmine\event\block\StructureGrowEvent;
|
||||||
use pocketmine\item\Bamboo as ItemBamboo;
|
use pocketmine\item\Bamboo as ItemBamboo;
|
||||||
use pocketmine\item\Fertilizer;
|
use pocketmine\item\Fertilizer;
|
||||||
@ -100,6 +101,10 @@ class Bamboo extends Transparent{
|
|||||||
return [AxisAlignedBB::one()->trim(Facing::SOUTH, $inset)->trim(Facing::EAST, $inset)];
|
return [AxisAlignedBB::one()->trim(Facing::SOUTH, $inset)->trim(Facing::EAST, $inset)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
|
|
||||||
private static function getOffsetSeed(int $x, int $y, int $z) : int{
|
private static function getOffsetSeed(int $x, int $y, int $z) : int{
|
||||||
$p1 = gmp_mul($z, 0x6ebfff5);
|
$p1 = gmp_mul($z, 0x6ebfff5);
|
||||||
$p2 = gmp_mul($x, 0x2fc20f);
|
$p2 = gmp_mul($x, 0x2fc20f);
|
||||||
@ -115,7 +120,7 @@ class Bamboo extends Transparent{
|
|||||||
return 12 + (self::getOffsetSeed($x, 0, $z) % 5);
|
return 12 + (self::getOffsetSeed($x, 0, $z) % 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPositionOffset() : ?Vector3{
|
public function getModelPositionOffset() : ?Vector3{
|
||||||
$seed = self::getOffsetSeed($this->position->getFloorX(), 0, $this->position->getFloorZ());
|
$seed = self::getOffsetSeed($this->position->getFloorX(), 0, $this->position->getFloorZ());
|
||||||
$retX = (($seed % 12) + 1) / 16;
|
$retX = (($seed % 12) + 1) / 16;
|
||||||
$retZ = ((($seed >> 8) % 12) + 1) / 16;
|
$retZ = ((($seed >> 8) % 12) + 1) / 16;
|
||||||
@ -145,12 +150,12 @@ class Bamboo extends Transparent{
|
|||||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
if($item instanceof Fertilizer){
|
if($item instanceof Fertilizer){
|
||||||
$top = $this->seekToTop();
|
$top = $this->seekToTop();
|
||||||
if($top->grow(self::getMaxHeight($top->position->getFloorX(), $top->position->getFloorZ()), mt_rand(1, 2))){
|
if($top->grow(self::getMaxHeight($top->position->getFloorX(), $top->position->getFloorZ()), mt_rand(1, 2), $player)){
|
||||||
$item->pop();
|
$item->pop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}elseif($item instanceof ItemBamboo){
|
}elseif($item instanceof ItemBamboo){
|
||||||
if($this->seekToTop()->grow(PHP_INT_MAX, 1)){
|
if($this->seekToTop()->grow(PHP_INT_MAX, 1, $player)){
|
||||||
$item->pop();
|
$item->pop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -160,12 +165,12 @@ class Bamboo extends Transparent{
|
|||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
$below = $this->position->getWorld()->getBlock($this->position->down());
|
$below = $this->position->getWorld()->getBlock($this->position->down());
|
||||||
if(!$this->canBeSupportedBy($below) and !$below->isSameType($this)){
|
if(!$this->canBeSupportedBy($below) && !$below->isSameType($this)){
|
||||||
$this->position->getWorld()->useBreakOn($this->position);
|
$this->position->getWorld()->useBreakOn($this->position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function grow(int $maxHeight, int $growAmount) : bool{
|
private function grow(int $maxHeight, int $growAmount, ?Player $player) : bool{
|
||||||
$world = $this->position->getWorld();
|
$world = $this->position->getWorld();
|
||||||
if(!$world->getBlock($this->position->up())->canBeReplaced()){
|
if(!$world->getBlock($this->position->up())->canBeReplaced()){
|
||||||
return false;
|
return false;
|
||||||
@ -212,7 +217,7 @@ class Bamboo extends Transparent{
|
|||||||
$tx->addBlock($this->position->subtract(0, $idx - $growAmount, 0), $newBlock);
|
$tx->addBlock($this->position->subtract(0, $idx - $growAmount, 0), $newBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
$ev = new StructureGrowEvent($this, $tx);
|
$ev = new StructureGrowEvent($this, $tx, $player);
|
||||||
$ev->call();
|
$ev->call();
|
||||||
if($ev->isCancelled()){
|
if($ev->isCancelled()){
|
||||||
return false;
|
return false;
|
||||||
@ -229,7 +234,7 @@ class Bamboo extends Transparent{
|
|||||||
$world = $this->position->getWorld();
|
$world = $this->position->getWorld();
|
||||||
if($this->ready){
|
if($this->ready){
|
||||||
$this->ready = false;
|
$this->ready = false;
|
||||||
if($world->getFullLight($this->position) < 9 || !$this->grow(self::getMaxHeight($this->position->getFloorX(), $this->position->getFloorZ()), 1)){
|
if($world->getFullLight($this->position) < 9 || !$this->grow(self::getMaxHeight($this->position->getFloorX(), $this->position->getFloorZ()), 1, null)){
|
||||||
$world->setBlock($this->position, $this);
|
$world->setBlock($this->position, $this);
|
||||||
}
|
}
|
||||||
}elseif($world->getBlock($this->position->up())->canBeReplaced()){
|
}elseif($world->getBlock($this->position->up())->canBeReplaced()){
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -36,14 +36,14 @@ final class BambooSapling extends Flowable{
|
|||||||
private bool $ready = false;
|
private bool $ready = false;
|
||||||
|
|
||||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||||
$this->ready = ($stateMeta & BlockLegacyMetadata::SAPLING_FLAG_READY) !== 0;
|
$this->ready = ($stateMeta & BlockLegacyMetadata::BAMBOO_SAPLING_FLAG_READY) !== 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function writeStateToMeta() : int{
|
protected function writeStateToMeta() : int{
|
||||||
return $this->ready ? BlockLegacyMetadata::SAPLING_FLAG_READY : 0;
|
return $this->ready ? BlockLegacyMetadata::BAMBOO_SAPLING_FLAG_READY : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStateBitmask() : int{ return 0b1000; }
|
public function getStateBitmask() : int{ return 0b1; }
|
||||||
|
|
||||||
public function isReady() : bool{ return $this->ready; }
|
public function isReady() : bool{ return $this->ready; }
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ final class BambooSapling extends Flowable{
|
|||||||
|
|
||||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
if($item instanceof Fertilizer || $item instanceof ItemBamboo){
|
if($item instanceof Fertilizer || $item instanceof ItemBamboo){
|
||||||
if($this->grow()){
|
if($this->grow($player)){
|
||||||
$item->pop();
|
$item->pop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@ final class BambooSapling extends Flowable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function grow() : bool{
|
private function grow(?Player $player) : bool{
|
||||||
$world = $this->position->getWorld();
|
$world = $this->position->getWorld();
|
||||||
if(!$world->getBlock($this->position->up())->canBeReplaced()){
|
if(!$world->getBlock($this->position->up())->canBeReplaced()){
|
||||||
return false;
|
return false;
|
||||||
@ -98,7 +98,7 @@ final class BambooSapling extends Flowable{
|
|||||||
$tx->addBlock($this->position, $bamboo)
|
$tx->addBlock($this->position, $bamboo)
|
||||||
->addBlock($this->position->up(), (clone $bamboo)->setLeafSize(Bamboo::SMALL_LEAVES));
|
->addBlock($this->position->up(), (clone $bamboo)->setLeafSize(Bamboo::SMALL_LEAVES));
|
||||||
|
|
||||||
$ev = new StructureGrowEvent($this, $tx);
|
$ev = new StructureGrowEvent($this, $tx, $player);
|
||||||
$ev->call();
|
$ev->call();
|
||||||
if($ev->isCancelled()){
|
if($ev->isCancelled()){
|
||||||
return false;
|
return false;
|
||||||
@ -115,7 +115,7 @@ final class BambooSapling extends Flowable{
|
|||||||
$world = $this->position->getWorld();
|
$world = $this->position->getWorld();
|
||||||
if($this->ready){
|
if($this->ready){
|
||||||
$this->ready = false;
|
$this->ready = false;
|
||||||
if($world->getFullLight($this->position) < 9 || !$this->grow()){
|
if($world->getFullLight($this->position) < 9 || !$this->grow(null)){
|
||||||
$world->setBlock($this->position, $this);
|
$world->setBlock($this->position, $this);
|
||||||
}
|
}
|
||||||
}elseif($world->getBlock($this->position->up())->canBeReplaced()){
|
}elseif($world->getBlock($this->position->up())->canBeReplaced()){
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -27,6 +27,7 @@ use pocketmine\block\tile\Banner as TileBanner;
|
|||||||
use pocketmine\block\utils\BannerPatternLayer;
|
use pocketmine\block\utils\BannerPatternLayer;
|
||||||
use pocketmine\block\utils\ColoredTrait;
|
use pocketmine\block\utils\ColoredTrait;
|
||||||
use pocketmine\block\utils\DyeColor;
|
use pocketmine\block\utils\DyeColor;
|
||||||
|
use pocketmine\block\utils\SupportType;
|
||||||
use pocketmine\data\bedrock\DyeColorIdMap;
|
use pocketmine\data\bedrock\DyeColorIdMap;
|
||||||
use pocketmine\item\Banner as ItemBanner;
|
use pocketmine\item\Banner as ItemBanner;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
@ -107,6 +108,10 @@ abstract class BaseBanner extends Transparent{
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
|
|
||||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
if($item instanceof ItemBanner){
|
if($item instanceof ItemBanner){
|
||||||
$this->color = $item->getColor();
|
$this->color = $item->getColor();
|
||||||
@ -130,7 +135,7 @@ abstract class BaseBanner extends Transparent{
|
|||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
$drop = $this->asItem();
|
$drop = $this->asItem();
|
||||||
if($drop instanceof ItemBanner and count($this->patterns) > 0){
|
if($drop instanceof ItemBanner && count($this->patterns) > 0){
|
||||||
$drop->setPatterns($this->patterns);
|
$drop->setPatterns($this->patterns);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +144,7 @@ abstract class BaseBanner extends Transparent{
|
|||||||
|
|
||||||
public function getPickedItem(bool $addUserData = false) : Item{
|
public function getPickedItem(bool $addUserData = false) : Item{
|
||||||
$result = $this->asItem();
|
$result = $this->asItem();
|
||||||
if($addUserData and $result instanceof ItemBanner and count($this->patterns) > 0){
|
if($addUserData && $result instanceof ItemBanner && count($this->patterns) > 0){
|
||||||
$result->setPatterns($this->patterns);
|
$result->setPatterns($this->patterns);
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
|
@ -17,41 +17,25 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\utils\CoralType;
|
use pocketmine\block\utils\CoralType;
|
||||||
|
use pocketmine\block\utils\CoralTypeTrait;
|
||||||
|
use pocketmine\block\utils\SupportType;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
|
|
||||||
abstract class BaseCoral extends Transparent{
|
abstract class BaseCoral extends Transparent{
|
||||||
|
use CoralTypeTrait;
|
||||||
protected CoralType $coralType;
|
|
||||||
protected bool $dead = false;
|
|
||||||
|
|
||||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
|
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
|
||||||
parent::__construct($idInfo, $name, $breakInfo);
|
parent::__construct($idInfo, $name, $breakInfo);
|
||||||
$this->coralType = CoralType::TUBE();
|
$this->coralType = CoralType::TUBE();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCoralType() : CoralType{ return $this->coralType; }
|
|
||||||
|
|
||||||
/** @return $this */
|
|
||||||
public function setCoralType(CoralType $coralType) : self{
|
|
||||||
$this->coralType = $coralType;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isDead() : bool{ return $this->dead; }
|
|
||||||
|
|
||||||
/** @return $this */
|
|
||||||
public function setDead(bool $dead) : self{
|
|
||||||
$this->dead = $dead;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if(!$this->dead){
|
if(!$this->dead){
|
||||||
$world = $this->position->getWorld();
|
$world = $this->position->getWorld();
|
||||||
@ -82,4 +66,8 @@ abstract class BaseCoral extends Transparent{
|
|||||||
public function isSolid() : bool{ return false; }
|
public function isSolid() : bool{ return false; }
|
||||||
|
|
||||||
protected function recalculateCollisionBoxes() : array{ return []; }
|
protected function recalculateCollisionBoxes() : array{ return []; }
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ use function in_array;
|
|||||||
abstract class BaseRail extends Flowable{
|
abstract class BaseRail extends Flowable{
|
||||||
|
|
||||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
if(!$blockReplace->getSide(Facing::DOWN)->isTransparent()){
|
if($blockReplace->getSide(Facing::DOWN)->getSupportType(Facing::UP)->hasEdgeSupport()){
|
||||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ abstract class BaseRail extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(
|
if(
|
||||||
$other instanceof BaseRail and
|
$other instanceof BaseRail &&
|
||||||
in_array($otherConnection, $other->getCurrentShapeConnections(), true)
|
in_array($otherConnection, $other->getCurrentShapeConnections(), true)
|
||||||
){
|
){
|
||||||
$connections[] = $connection;
|
$connections[] = $connection;
|
||||||
@ -179,7 +179,7 @@ abstract class BaseRail extends Flowable{
|
|||||||
$otherSide |= RailConnectionInfo::FLAG_ASCEND;
|
$otherSide |= RailConnectionInfo::FLAG_ASCEND;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!($other instanceof BaseRail) or count($otherConnections = $other->getConnectedDirections()) >= 2){
|
if(!($other instanceof BaseRail) || count($otherConnections = $other->getConnectedDirections()) >= 2){
|
||||||
//we can only connect to a rail that has less than 2 connections
|
//we can only connect to a rail that has less than 2 connections
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -220,11 +220,11 @@ abstract class BaseRail extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if($this->getSide(Facing::DOWN)->isTransparent()){
|
if(!$this->getSide(Facing::DOWN)->getSupportType(Facing::UP)->hasEdgeSupport()){
|
||||||
$this->position->getWorld()->useBreakOn($this->position);
|
$this->position->getWorld()->useBreakOn($this->position);
|
||||||
}else{
|
}else{
|
||||||
foreach($this->getCurrentShapeConnections() as $connection){
|
foreach($this->getCurrentShapeConnections() as $connection){
|
||||||
if(($connection & RailConnectionInfo::FLAG_ASCEND) !== 0 and $this->getSide($connection & ~RailConnectionInfo::FLAG_ASCEND)->isTransparent()){
|
if(($connection & RailConnectionInfo::FLAG_ASCEND) !== 0 && !$this->getSide($connection & ~RailConnectionInfo::FLAG_ASCEND)->getSupportType(Facing::UP)->hasEdgeSupport()){
|
||||||
$this->position->getWorld()->useBreakOn($this->position);
|
$this->position->getWorld()->useBreakOn($this->position);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\block\tile\Sign as TileSign;
|
use pocketmine\block\tile\Sign as TileSign;
|
||||||
use pocketmine\block\utils\SignText;
|
use pocketmine\block\utils\SignText;
|
||||||
|
use pocketmine\block\utils\SupportType;
|
||||||
use pocketmine\event\block\SignChangeEvent;
|
use pocketmine\event\block\SignChangeEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
@ -37,8 +38,6 @@ use function assert;
|
|||||||
use function strlen;
|
use function strlen;
|
||||||
|
|
||||||
abstract class BaseSign extends Transparent{
|
abstract class BaseSign extends Transparent{
|
||||||
//TODO: conditionally useless properties, find a way to fix
|
|
||||||
|
|
||||||
protected SignText $text;
|
protected SignText $text;
|
||||||
protected ?int $editorEntityRuntimeId = null;
|
protected ?int $editorEntityRuntimeId = null;
|
||||||
|
|
||||||
@ -79,6 +78,10 @@ abstract class BaseSign extends Transparent{
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
|
|
||||||
abstract protected function getSupportingFace() : int;
|
abstract protected function getSupportingFace() : int;
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -28,6 +28,7 @@ use pocketmine\block\utils\BlockDataSerializer;
|
|||||||
use pocketmine\block\utils\ColoredTrait;
|
use pocketmine\block\utils\ColoredTrait;
|
||||||
use pocketmine\block\utils\DyeColor;
|
use pocketmine\block\utils\DyeColor;
|
||||||
use pocketmine\block\utils\HorizontalFacingTrait;
|
use pocketmine\block\utils\HorizontalFacingTrait;
|
||||||
|
use pocketmine\block\utils\SupportType;
|
||||||
use pocketmine\data\bedrock\DyeColorIdMap;
|
use pocketmine\data\bedrock\DyeColorIdMap;
|
||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
use pocketmine\entity\Living;
|
use pocketmine\entity\Living;
|
||||||
@ -94,6 +95,10 @@ class Bed extends Transparent{
|
|||||||
return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 16)];
|
return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 16)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
|
|
||||||
public function isHeadPart() : bool{
|
public function isHeadPart() : bool{
|
||||||
return $this->head;
|
return $this->head;
|
||||||
}
|
}
|
||||||
@ -120,7 +125,7 @@ class Bed extends Transparent{
|
|||||||
|
|
||||||
public function getOtherHalf() : ?Bed{
|
public function getOtherHalf() : ?Bed{
|
||||||
$other = $this->getSide($this->getOtherHalfSide());
|
$other = $this->getSide($this->getOtherHalfSide());
|
||||||
if($other instanceof Bed and $other->head !== $this->head and $other->facing === $this->facing){
|
if($other instanceof Bed && $other->head !== $this->head && $other->facing === $this->facing){
|
||||||
return $other;
|
return $other;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,17 +140,17 @@ class Bed extends Transparent{
|
|||||||
$player->sendMessage(TextFormat::GRAY . "This bed is incomplete");
|
$player->sendMessage(TextFormat::GRAY . "This bed is incomplete");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}elseif($playerPos->distanceSquared($this->position) > 4 and $playerPos->distanceSquared($other->position) > 4){
|
}elseif($playerPos->distanceSquared($this->position) > 4 && $playerPos->distanceSquared($other->position) > 4){
|
||||||
$player->sendMessage(KnownTranslationFactory::tile_bed_tooFar()->prefix(TextFormat::GRAY));
|
$player->sendMessage(KnownTranslationFactory::tile_bed_tooFar()->prefix(TextFormat::GRAY));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$time = $this->position->getWorld()->getTimeOfDay();
|
$time = $this->position->getWorld()->getTimeOfDay();
|
||||||
|
|
||||||
$isNight = ($time >= World::TIME_NIGHT and $time < World::TIME_SUNRISE);
|
$isNight = ($time >= World::TIME_NIGHT && $time < World::TIME_SUNRISE);
|
||||||
|
|
||||||
if(!$isNight){
|
if(!$isNight){
|
||||||
$player->sendMessage(KnownTranslationFactory::tile_bed_tooFar()->prefix(TextFormat::GRAY));
|
$player->sendMessage(KnownTranslationFactory::tile_bed_noSleep()->prefix(TextFormat::GRAY));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -166,7 +171,7 @@ class Bed extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if(($other = $this->getOtherHalf()) !== null and $other->occupied !== $this->occupied){
|
if(!$this->head && ($other = $this->getOtherHalf()) !== null && $other->occupied !== $this->occupied){
|
||||||
$this->occupied = $other->occupied;
|
$this->occupied = $other->occupied;
|
||||||
$this->position->getWorld()->setBlock($this->position, $this);
|
$this->position->getWorld()->setBlock($this->position, $this);
|
||||||
}
|
}
|
||||||
@ -181,12 +186,11 @@ class Bed extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
$down = $this->getSide(Facing::DOWN);
|
if($this->canBeSupportedBy($this->getSide(Facing::DOWN))){
|
||||||
if(!$down->isTransparent()){
|
|
||||||
$this->facing = $player !== null ? $player->getHorizontalFacing() : Facing::NORTH;
|
$this->facing = $player !== null ? $player->getHorizontalFacing() : Facing::NORTH;
|
||||||
|
|
||||||
$next = $this->getSide($this->getOtherHalfSide());
|
$next = $this->getSide($this->getOtherHalfSide());
|
||||||
if($next->canBeReplaced() and !$next->getSide(Facing::DOWN)->isTransparent()){
|
if($next->canBeReplaced() && $this->canBeSupportedBy($next->getSide(Facing::DOWN))){
|
||||||
$nextState = clone $this;
|
$nextState = clone $this;
|
||||||
$nextState->head = true;
|
$nextState->head = true;
|
||||||
$tx->addBlock($blockReplace->position, $this)->addBlock($next->position, $nextState);
|
$tx->addBlock($blockReplace->position, $this)->addBlock($next->position, $nextState);
|
||||||
@ -216,4 +220,8 @@ class Bed extends Transparent{
|
|||||||
|
|
||||||
return parent::getAffectedBlocks();
|
return parent::getAffectedBlocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function canBeSupportedBy(Block $block) : bool{
|
||||||
|
return !$block->getSupportType(Facing::UP)->equals(SupportType::NONE());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ use function mt_rand;
|
|||||||
class Beetroot extends Crops{
|
class Beetroot extends Crops{
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
if($this->age >= 7){
|
if($this->age >= self::MAX_AGE){
|
||||||
return [
|
return [
|
||||||
VanillaItems::BEETROOT(),
|
VanillaItems::BEETROOT(),
|
||||||
VanillaItems::BEETROOT_SEEDS()->setCount(mt_rand(0, 3))
|
VanillaItems::BEETROOT_SEEDS()->setCount(mt_rand(0, 3))
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -28,7 +28,9 @@ use pocketmine\block\utils\BellAttachmentType;
|
|||||||
use pocketmine\block\utils\BlockDataSerializer;
|
use pocketmine\block\utils\BlockDataSerializer;
|
||||||
use pocketmine\block\utils\HorizontalFacingTrait;
|
use pocketmine\block\utils\HorizontalFacingTrait;
|
||||||
use pocketmine\block\utils\InvalidBlockStateException;
|
use pocketmine\block\utils\InvalidBlockStateException;
|
||||||
|
use pocketmine\block\utils\SupportType;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Facing;
|
use pocketmine\math\Facing;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
@ -37,8 +39,6 @@ use pocketmine\world\BlockTransaction;
|
|||||||
use pocketmine\world\sound\BellRingSound;
|
use pocketmine\world\sound\BellRingSound;
|
||||||
|
|
||||||
final class Bell extends Transparent{
|
final class Bell extends Transparent{
|
||||||
private const BELL_RINGING_REPEAT_TICKS = 20;
|
|
||||||
|
|
||||||
use HorizontalFacingTrait;
|
use HorizontalFacingTrait;
|
||||||
|
|
||||||
private BellAttachmentType $attachmentType;
|
private BellAttachmentType $attachmentType;
|
||||||
@ -80,6 +80,32 @@ final class Bell extends Transparent{
|
|||||||
return 0b1111;
|
return 0b1111;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function recalculateCollisionBoxes() : array{
|
||||||
|
if($this->attachmentType->equals(BellAttachmentType::FLOOR())){
|
||||||
|
return [
|
||||||
|
AxisAlignedBB::one()->squash(Facing::axis($this->facing), 1 / 4)->trim(Facing::UP, 3 / 16)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if($this->attachmentType->equals(BellAttachmentType::CEILING())){
|
||||||
|
return [
|
||||||
|
AxisAlignedBB::one()->contract(1 / 4, 0, 1 / 4)->trim(Facing::DOWN, 1 / 4)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$box = AxisAlignedBB::one()
|
||||||
|
->squash(Facing::axis(Facing::rotateY($this->facing, true)), 1 / 4)
|
||||||
|
->trim(Facing::UP, 1 / 16)
|
||||||
|
->trim(Facing::DOWN, 1 / 4);
|
||||||
|
|
||||||
|
return [
|
||||||
|
$this->attachmentType->equals(BellAttachmentType::ONE_WALL()) ? $box->trim($this->facing, 3 / 16) : $box
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
|
|
||||||
public function getAttachmentType() : BellAttachmentType{ return $this->attachmentType; }
|
public function getAttachmentType() : BellAttachmentType{ return $this->attachmentType; }
|
||||||
|
|
||||||
/** @return $this */
|
/** @return $this */
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -29,6 +29,7 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\block\tile\Spawnable;
|
use pocketmine\block\tile\Spawnable;
|
||||||
use pocketmine\block\tile\Tile;
|
use pocketmine\block\tile\Tile;
|
||||||
use pocketmine\block\utils\InvalidBlockStateException;
|
use pocketmine\block\utils\InvalidBlockStateException;
|
||||||
|
use pocketmine\block\utils\SupportType;
|
||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
use pocketmine\item\enchantment\VanillaEnchantments;
|
use pocketmine\item\enchantment\VanillaEnchantments;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
@ -148,14 +149,14 @@ class Block{
|
|||||||
$tileType = $this->idInfo->getTileClass();
|
$tileType = $this->idInfo->getTileClass();
|
||||||
$oldTile = $this->position->getWorld()->getTile($this->position);
|
$oldTile = $this->position->getWorld()->getTile($this->position);
|
||||||
if($oldTile !== null){
|
if($oldTile !== null){
|
||||||
if($tileType === null or !($oldTile instanceof $tileType)){
|
if($tileType === null || !($oldTile instanceof $tileType)){
|
||||||
$oldTile->close();
|
$oldTile->close();
|
||||||
$oldTile = null;
|
$oldTile = null;
|
||||||
}elseif($oldTile instanceof Spawnable){
|
}elseif($oldTile instanceof Spawnable){
|
||||||
$oldTile->setDirty(); //destroy old network cache
|
$oldTile->clearSpawnCompoundCache(); //destroy old network cache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if($oldTile === null and $tileType !== null){
|
if($oldTile === null && $tileType !== null){
|
||||||
/**
|
/**
|
||||||
* @var Tile $tile
|
* @var Tile $tile
|
||||||
* @see Tile::__construct()
|
* @see Tile::__construct()
|
||||||
@ -166,20 +167,28 @@ class Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the given block has an equivalent type to this one. This compares base legacy ID and variant.
|
* Returns a type ID that identifies this type of block. This does not include information like facing, colour,
|
||||||
|
* powered/unpowered, etc.
|
||||||
|
*/
|
||||||
|
public function getTypeId() : int{
|
||||||
|
return ($this->idInfo->getBlockId() << Block::INTERNAL_METADATA_BITS) | $this->idInfo->getVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given block has an equivalent type to this one. This compares the type IDs.
|
||||||
*
|
*
|
||||||
* Note: This ignores additional IDs used to represent additional states. This means that, for example, a lit
|
* Note: This ignores additional IDs used to represent additional states. This means that, for example, a lit
|
||||||
* furnace and unlit furnace are considered the same type.
|
* furnace and unlit furnace are considered the same type.
|
||||||
*/
|
*/
|
||||||
public function isSameType(Block $other) : bool{
|
public function isSameType(Block $other) : bool{
|
||||||
return $this->idInfo->getBlockId() === $other->idInfo->getBlockId() and $this->idInfo->getVariant() === $other->idInfo->getVariant();
|
return $this->getTypeId() === $other->getTypeId();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the given block has the same type and properties as this block.
|
* Returns whether the given block has the same type and properties as this block.
|
||||||
*/
|
*/
|
||||||
public function isSameState(Block $other) : bool{
|
public function isSameState(Block $other) : bool{
|
||||||
return $this->isSameType($other) and $this->writeStateToMeta() === $other->writeStateToMeta();
|
return $this->getFullId() === $other->getFullId();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -353,7 +362,7 @@ class Block{
|
|||||||
*/
|
*/
|
||||||
public function getDrops(Item $item) : array{
|
public function getDrops(Item $item) : array{
|
||||||
if($this->breakInfo->isToolCompatible($item)){
|
if($this->breakInfo->isToolCompatible($item)){
|
||||||
if($this->isAffectedBySilkTouch() and $item->hasEnchantment(VanillaEnchantments::SILK_TOUCH())){
|
if($this->isAffectedBySilkTouch() && $item->hasEnchantment(VanillaEnchantments::SILK_TOUCH())){
|
||||||
return $this->getSilkTouchDrops($item);
|
return $this->getSilkTouchDrops($item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,7 +403,7 @@ class Block{
|
|||||||
* Returns how much XP will be dropped by breaking this block with the given item.
|
* Returns how much XP will be dropped by breaking this block with the given item.
|
||||||
*/
|
*/
|
||||||
public function getXpDropForTool(Item $item) : int{
|
public function getXpDropForTool(Item $item) : int{
|
||||||
if($item->hasEnchantment(VanillaEnchantments::SILK_TOUCH()) or !$this->breakInfo->isToolCompatible($item)){
|
if($item->hasEnchantment(VanillaEnchantments::SILK_TOUCH()) || !$this->breakInfo->isToolCompatible($item)){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,7 +502,7 @@ class Block{
|
|||||||
return $this->position->getWorld()->getBlock($this->position->getSide($side, $step));
|
return $this->position->getWorld()->getBlock($this->position->getSide($side, $step));
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new \InvalidStateException("Block does not have a valid world");
|
throw new \LogicException("Block does not have a valid world");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -577,7 +586,7 @@ class Block{
|
|||||||
final public function getCollisionBoxes() : array{
|
final public function getCollisionBoxes() : array{
|
||||||
if($this->collisionBoxes === null){
|
if($this->collisionBoxes === null){
|
||||||
$this->collisionBoxes = $this->recalculateCollisionBoxes();
|
$this->collisionBoxes = $this->recalculateCollisionBoxes();
|
||||||
$extraOffset = $this->getPositionOffset();
|
$extraOffset = $this->getModelPositionOffset();
|
||||||
$offset = $extraOffset !== null ? $this->position->addVector($extraOffset) : $this->position;
|
$offset = $extraOffset !== null ? $this->position->addVector($extraOffset) : $this->position;
|
||||||
foreach($this->collisionBoxes as $bb){
|
foreach($this->collisionBoxes as $bb){
|
||||||
$bb->offset($offset->x, $offset->y, $offset->z);
|
$bb->offset($offset->x, $offset->y, $offset->z);
|
||||||
@ -588,10 +597,10 @@ class Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an additional fractional vector to shift the block's effective position by based on the current position.
|
* Returns an additional fractional vector to shift the block model's position by based on the current position.
|
||||||
* Used to randomize position of things like bamboo canes and tall grass.
|
* Used to randomize position of things like bamboo canes and tall grass.
|
||||||
*/
|
*/
|
||||||
public function getPositionOffset() : ?Vector3{
|
public function getModelPositionOffset() : ?Vector3{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,10 +611,14 @@ class Block{
|
|||||||
return [AxisAlignedBB::one()];
|
return [AxisAlignedBB::one()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::FULL();
|
||||||
|
}
|
||||||
|
|
||||||
public function isFullCube() : bool{
|
public function isFullCube() : bool{
|
||||||
$bb = $this->getCollisionBoxes();
|
$bb = $this->getCollisionBoxes();
|
||||||
|
|
||||||
return count($bb) === 1 and $bb[0]->getAverageEdgeLength() >= 1 and $bb[0]->isCube();
|
return count($bb) === 1 && $bb[0]->getAverageEdgeLength() >= 1 && $bb[0]->isCube();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{
|
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -38,18 +38,17 @@ class BlockBreakInfo{
|
|||||||
*/
|
*/
|
||||||
public const INCOMPATIBLE_TOOL_MULTIPLIER = 5.0;
|
public const INCOMPATIBLE_TOOL_MULTIPLIER = 5.0;
|
||||||
|
|
||||||
private float $hardness;
|
|
||||||
private float $blastResistance;
|
private float $blastResistance;
|
||||||
private int $toolType;
|
|
||||||
private int $toolHarvestLevel;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param float|null $blastResistance default 5x hardness
|
* @param float|null $blastResistance default 5x hardness
|
||||||
*/
|
*/
|
||||||
public function __construct(float $hardness, int $toolType = BlockToolType::NONE, int $toolHarvestLevel = 0, ?float $blastResistance = null){
|
public function __construct(
|
||||||
$this->hardness = $hardness;
|
private float $hardness,
|
||||||
$this->toolType = $toolType;
|
private int $toolType = BlockToolType::NONE,
|
||||||
$this->toolHarvestLevel = $toolHarvestLevel;
|
private int $toolHarvestLevel = 0,
|
||||||
|
?float $blastResistance = null
|
||||||
|
){
|
||||||
$this->blastResistance = $blastResistance ?? $hardness * 5;
|
$this->blastResistance = $blastResistance ?? $hardness * 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,8 +118,8 @@ class BlockBreakInfo{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->toolType === BlockToolType::NONE or $this->toolHarvestLevel === 0 or (
|
return $this->toolType === BlockToolType::NONE || $this->toolHarvestLevel === 0 || (
|
||||||
($this->toolType & $tool->getBlockToolType()) !== 0 and $tool->getBlockToolHarvestLevel() >= $this->toolHarvestLevel);
|
($this->toolType & $tool->getBlockToolType()) !== 0 && $tool->getBlockToolHarvestLevel() >= $this->toolHarvestLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -17,30 +17,28 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\tile\Tile;
|
use pocketmine\block\tile\Tile;
|
||||||
|
use pocketmine\utils\Utils;
|
||||||
|
|
||||||
class BlockIdentifier{
|
class BlockIdentifier{
|
||||||
|
|
||||||
private int $blockId;
|
|
||||||
private int $variant;
|
|
||||||
private ?int $itemId;
|
|
||||||
/** @phpstan-var class-string<Tile>|null */
|
|
||||||
private ?string $tileClass;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @phpstan-param class-string<Tile>|null $tileClass
|
* @phpstan-param class-string<Tile>|null $tileClass
|
||||||
*/
|
*/
|
||||||
public function __construct(int $blockId, int $variant, ?int $itemId = null, ?string $tileClass = null){
|
public function __construct(
|
||||||
$this->blockId = $blockId;
|
private int $blockId,
|
||||||
$this->variant = $variant;
|
private int $variant,
|
||||||
$this->itemId = $itemId;
|
private ?int $itemId = null,
|
||||||
$this->tileClass = $tileClass;
|
private ?string $tileClass = null
|
||||||
|
){
|
||||||
|
if($tileClass !== null){
|
||||||
|
Utils::testValidInstance($tileClass, Tile::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBlockId() : int{
|
public function getBlockId() : int{
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -42,6 +42,8 @@ final class BlockLegacyMetadata{
|
|||||||
public const BAMBOO_LEAF_SIZE_SHIFT = 1;
|
public const BAMBOO_LEAF_SIZE_SHIFT = 1;
|
||||||
public const BAMBOO_LEAF_SIZE_MASK = 0x03;
|
public const BAMBOO_LEAF_SIZE_MASK = 0x03;
|
||||||
|
|
||||||
|
public const BAMBOO_SAPLING_FLAG_READY = 0x01;
|
||||||
|
|
||||||
public const BARREL_FLAG_OPEN = 0x08;
|
public const BARREL_FLAG_OPEN = 0x08;
|
||||||
|
|
||||||
public const BED_FLAG_HEAD = 0x08;
|
public const BED_FLAG_HEAD = 0x08;
|
||||||
@ -142,6 +144,8 @@ final class BlockLegacyMetadata{
|
|||||||
public const LEAVES_FLAG_NO_DECAY = 0x04;
|
public const LEAVES_FLAG_NO_DECAY = 0x04;
|
||||||
public const LEAVES_FLAG_CHECK_DECAY = 0x08;
|
public const LEAVES_FLAG_CHECK_DECAY = 0x08;
|
||||||
|
|
||||||
|
public const LECTERN_FLAG_POWERED = 0x04;
|
||||||
|
|
||||||
public const LEVER_FLAG_POWERED = 0x08;
|
public const LEVER_FLAG_POWERED = 0x08;
|
||||||
|
|
||||||
public const LIQUID_FLAG_FALLING = 0x08;
|
public const LIQUID_FLAG_FALLING = 0x08;
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -25,7 +25,11 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\block\tile\BrewingStand as TileBrewingStand;
|
use pocketmine\block\tile\BrewingStand as TileBrewingStand;
|
||||||
use pocketmine\block\utils\BrewingStandSlot;
|
use pocketmine\block\utils\BrewingStandSlot;
|
||||||
|
use pocketmine\block\utils\SupportType;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\math\Axis;
|
||||||
|
use pocketmine\math\AxisAlignedBB;
|
||||||
|
use pocketmine\math\Facing;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
use function array_key_exists;
|
use function array_key_exists;
|
||||||
@ -67,6 +71,23 @@ class BrewingStand extends Transparent{
|
|||||||
return 0b111;
|
return 0b111;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function recalculateCollisionBoxes() : array{
|
||||||
|
return [
|
||||||
|
//bottom slab part - in PC this is also inset on X/Z by 1/16, but Bedrock sucks
|
||||||
|
AxisAlignedBB::one()->trim(Facing::UP, 7 / 8),
|
||||||
|
|
||||||
|
//center post
|
||||||
|
AxisAlignedBB::one()
|
||||||
|
->squash(Axis::X, 7 / 16)
|
||||||
|
->squash(Axis::Z, 7 / 16)
|
||||||
|
->trim(Facing::UP, 1 / 8)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
|
|
||||||
public function hasSlot(BrewingStandSlot $slot) : bool{
|
public function hasSlot(BrewingStandSlot $slot) : bool{
|
||||||
return array_key_exists($slot->id(), $this->slots);
|
return array_key_exists($slot->id(), $this->slots);
|
||||||
}
|
}
|
||||||
@ -100,7 +121,7 @@ class BrewingStand extends Transparent{
|
|||||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
if($player instanceof Player){
|
if($player instanceof Player){
|
||||||
$stand = $this->position->getWorld()->getTile($this->position);
|
$stand = $this->position->getWorld()->getTile($this->position);
|
||||||
if($stand instanceof TileBrewingStand and $stand->canOpenWith($item->getCustomName())){
|
if($stand instanceof TileBrewingStand && $stand->canOpenWith($item->getCustomName())){
|
||||||
$player->setCurrentWindow($stand->getInventory());
|
$player->setCurrentWindow($stand->getInventory());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,6 +130,24 @@ class BrewingStand extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onScheduledUpdate() : void{
|
public function onScheduledUpdate() : void{
|
||||||
//TODO
|
$brewing = $this->position->getWorld()->getTile($this->position);
|
||||||
|
if($brewing instanceof TileBrewingStand){
|
||||||
|
if($brewing->onUpdate()){
|
||||||
|
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$changed = false;
|
||||||
|
foreach(BrewingStandSlot::getAll() as $slot){
|
||||||
|
$occupied = !$brewing->getInventory()->isSlotEmpty($slot->getSlotNumber());
|
||||||
|
if($occupied !== $this->hasSlot($slot)){
|
||||||
|
$this->setSlot($slot, $occupied);
|
||||||
|
$changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($changed){
|
||||||
|
$this->position->getWorld()->setBlock($this->position, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -61,10 +61,12 @@ abstract class Button extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
//TODO: check valid target block
|
if($this->canBeSupportedBy($blockClicked, $face)){
|
||||||
$this->facing = $face;
|
$this->facing = $face;
|
||||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
abstract protected function getActivationTime() : int;
|
abstract protected function getActivationTime() : int;
|
||||||
|
|
||||||
@ -86,4 +88,14 @@ abstract class Button extends Flowable{
|
|||||||
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new RedstonePowerOffSound());
|
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new RedstonePowerOffSound());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function onNearbyBlockChange() : void{
|
||||||
|
if(!$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)){
|
||||||
|
$this->position->getWorld()->useBreakOn($this->position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function canBeSupportedBy(Block $support, int $face) : bool{
|
||||||
|
return $support->getSupportType($face)->hasCenterSupport();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,13 +17,14 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\utils\BlockDataSerializer;
|
use pocketmine\block\utils\BlockDataSerializer;
|
||||||
|
use pocketmine\block\utils\SupportType;
|
||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
use pocketmine\event\block\BlockGrowEvent;
|
use pocketmine\event\block\BlockGrowEvent;
|
||||||
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||||
@ -36,6 +37,7 @@ use pocketmine\player\Player;
|
|||||||
use pocketmine\world\BlockTransaction;
|
use pocketmine\world\BlockTransaction;
|
||||||
|
|
||||||
class Cactus extends Transparent{
|
class Cactus extends Transparent{
|
||||||
|
public const MAX_AGE = 15;
|
||||||
|
|
||||||
protected int $age = 0;
|
protected int $age = 0;
|
||||||
|
|
||||||
@ -44,7 +46,7 @@ class Cactus extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||||
$this->age = BlockDataSerializer::readBoundedInt("age", $stateMeta, 0, 15);
|
$this->age = BlockDataSerializer::readBoundedInt("age", $stateMeta, 0, self::MAX_AGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStateBitmask() : int{
|
public function getStateBitmask() : int{
|
||||||
@ -55,8 +57,8 @@ class Cactus extends Transparent{
|
|||||||
|
|
||||||
/** @return $this */
|
/** @return $this */
|
||||||
public function setAge(int $age) : self{
|
public function setAge(int $age) : self{
|
||||||
if($age < 0 || $age > 15){
|
if($age < 0 || $age > self::MAX_AGE){
|
||||||
throw new \InvalidArgumentException("Age must be in range 0-15");
|
throw new \InvalidArgumentException("Age must be in range 0 ... " . self::MAX_AGE);
|
||||||
}
|
}
|
||||||
$this->age = $age;
|
$this->age = $age;
|
||||||
return $this;
|
return $this;
|
||||||
@ -74,6 +76,10 @@ class Cactus extends Transparent{
|
|||||||
return [AxisAlignedBB::one()->contract($shrinkSize, 0, $shrinkSize)->trim(Facing::UP, $shrinkSize)];
|
return [AxisAlignedBB::one()->contract($shrinkSize, 0, $shrinkSize)->trim(Facing::UP, $shrinkSize)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
|
|
||||||
public function onEntityInside(Entity $entity) : bool{
|
public function onEntityInside(Entity $entity) : bool{
|
||||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_CONTACT, 1);
|
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_CONTACT, 1);
|
||||||
$entity->attack($ev);
|
$entity->attack($ev);
|
||||||
@ -82,7 +88,7 @@ class Cactus extends Transparent{
|
|||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
$down = $this->getSide(Facing::DOWN);
|
$down = $this->getSide(Facing::DOWN);
|
||||||
if($down->getId() !== BlockLegacyIds::SAND and !$down->isSameType($this)){
|
if($down->getId() !== BlockLegacyIds::SAND && !$down->isSameType($this)){
|
||||||
$this->position->getWorld()->useBreakOn($this->position);
|
$this->position->getWorld()->useBreakOn($this->position);
|
||||||
}else{
|
}else{
|
||||||
foreach(Facing::HORIZONTAL as $side){
|
foreach(Facing::HORIZONTAL as $side){
|
||||||
@ -101,7 +107,7 @@ class Cactus extends Transparent{
|
|||||||
|
|
||||||
public function onRandomTick() : void{
|
public function onRandomTick() : void{
|
||||||
if(!$this->getSide(Facing::DOWN)->isSameType($this)){
|
if(!$this->getSide(Facing::DOWN)->isSameType($this)){
|
||||||
if($this->age === 15){
|
if($this->age === self::MAX_AGE){
|
||||||
for($y = 1; $y < 3; ++$y){
|
for($y = 1; $y < 3; ++$y){
|
||||||
if(!$this->position->getWorld()->isInWorld($this->position->x, $this->position->y + $y, $this->position->z)){
|
if(!$this->position->getWorld()->isInWorld($this->position->x, $this->position->y + $y, $this->position->z)){
|
||||||
break;
|
break;
|
||||||
@ -129,7 +135,7 @@ class Cactus extends Transparent{
|
|||||||
|
|
||||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
$down = $this->getSide(Facing::DOWN);
|
$down = $this->getSide(Facing::DOWN);
|
||||||
if($down->getId() === BlockLegacyIds::SAND or $down->isSameType($this)){
|
if($down->getId() === BlockLegacyIds::SAND || $down->isSameType($this)){
|
||||||
foreach(Facing::HORIZONTAL as $side){
|
foreach(Facing::HORIZONTAL as $side){
|
||||||
if($this->getSide($side)->isSolid()){
|
if($this->getSide($side)->isSolid()){
|
||||||
return false;
|
return false;
|
||||||
|
@ -17,13 +17,14 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\utils\BlockDataSerializer;
|
use pocketmine\block\utils\BlockDataSerializer;
|
||||||
|
use pocketmine\block\utils\SupportType;
|
||||||
use pocketmine\entity\effect\EffectInstance;
|
use pocketmine\entity\effect\EffectInstance;
|
||||||
use pocketmine\entity\FoodSource;
|
use pocketmine\entity\FoodSource;
|
||||||
use pocketmine\entity\Living;
|
use pocketmine\entity\Living;
|
||||||
@ -35,6 +36,7 @@ use pocketmine\player\Player;
|
|||||||
use pocketmine\world\BlockTransaction;
|
use pocketmine\world\BlockTransaction;
|
||||||
|
|
||||||
class Cake extends Transparent implements FoodSource{
|
class Cake extends Transparent implements FoodSource{
|
||||||
|
public const MAX_BITES = 6;
|
||||||
|
|
||||||
protected int $bites = 0;
|
protected int $bites = 0;
|
||||||
|
|
||||||
@ -43,7 +45,7 @@ class Cake extends Transparent implements FoodSource{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||||
$this->bites = BlockDataSerializer::readBoundedInt("bites", $stateMeta, 0, 6);
|
$this->bites = BlockDataSerializer::readBoundedInt("bites", $stateMeta, 0, self::MAX_BITES);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStateBitmask() : int{
|
public function getStateBitmask() : int{
|
||||||
@ -62,12 +64,16 @@ class Cake extends Transparent implements FoodSource{
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
|
|
||||||
public function getBites() : int{ return $this->bites; }
|
public function getBites() : int{ return $this->bites; }
|
||||||
|
|
||||||
/** @return $this */
|
/** @return $this */
|
||||||
public function setBites(int $bites) : self{
|
public function setBites(int $bites) : self{
|
||||||
if($bites < 0 || $bites > 6){
|
if($bites < 0 || $bites > self::MAX_BITES){
|
||||||
throw new \InvalidArgumentException("Bites must be in range 0-6");
|
throw new \InvalidArgumentException("Bites must be in range 0 ... " . self::MAX_BITES);
|
||||||
}
|
}
|
||||||
$this->bites = $bites;
|
$this->bites = $bites;
|
||||||
return $this;
|
return $this;
|
||||||
@ -94,8 +100,7 @@ class Cake extends Transparent implements FoodSource{
|
|||||||
|
|
||||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
if($player !== null){
|
if($player !== null){
|
||||||
$player->consumeObject($this);
|
return $player->consumeObject($this);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -119,7 +124,7 @@ class Cake extends Transparent implements FoodSource{
|
|||||||
public function getResidue(){
|
public function getResidue(){
|
||||||
$clone = clone $this;
|
$clone = clone $this;
|
||||||
$clone->bites++;
|
$clone->bites++;
|
||||||
if($clone->bites > 6){
|
if($clone->bites > self::MAX_BITES){
|
||||||
$clone = VanillaBlocks::AIR();
|
$clone = VanillaBlocks::AIR();
|
||||||
}
|
}
|
||||||
return $clone;
|
return $clone;
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ class Carrot extends Crops{
|
|||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [
|
return [
|
||||||
VanillaItems::CARROT()->setCount($this->age >= 7 ? mt_rand(1, 4) : 1)
|
VanillaItems::CARROT()->setCount($this->age >= self::MAX_AGE ? mt_rand(1, 4) : 1)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -26,6 +26,8 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\block\tile\Chest as TileChest;
|
use pocketmine\block\tile\Chest as TileChest;
|
||||||
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
|
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
|
||||||
use pocketmine\block\utils\NormalHorizontalFacingInMetadataTrait;
|
use pocketmine\block\utils\NormalHorizontalFacingInMetadataTrait;
|
||||||
|
use pocketmine\block\utils\SupportType;
|
||||||
|
use pocketmine\event\block\ChestPairEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Facing;
|
use pocketmine\math\Facing;
|
||||||
@ -44,17 +46,24 @@ class Chest extends Transparent{
|
|||||||
return [AxisAlignedBB::one()->contract(0.025, 0, 0.025)->trim(Facing::UP, 0.05)];
|
return [AxisAlignedBB::one()->contract(0.025, 0, 0.025)->trim(Facing::UP, 0.05)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
|
|
||||||
public function onPostPlace() : void{
|
public function onPostPlace() : void{
|
||||||
$tile = $this->position->getWorld()->getTile($this->position);
|
$tile = $this->position->getWorld()->getTile($this->position);
|
||||||
if($tile instanceof TileChest){
|
if($tile instanceof TileChest){
|
||||||
foreach([
|
foreach([false, true] as $clockwise){
|
||||||
Facing::rotateY($this->facing, true),
|
$side = Facing::rotateY($this->facing, $clockwise);
|
||||||
Facing::rotateY($this->facing, false)
|
|
||||||
] as $side){
|
|
||||||
$c = $this->getSide($side);
|
$c = $this->getSide($side);
|
||||||
if($c instanceof Chest and $c->isSameType($this) and $c->facing === $this->facing){
|
if($c instanceof Chest && $c->isSameType($this) && $c->facing === $this->facing){
|
||||||
$pair = $this->position->getWorld()->getTile($c->position);
|
$world = $this->position->getWorld();
|
||||||
if($pair instanceof TileChest and !$pair->isPaired()){
|
$pair = $world->getTile($c->position);
|
||||||
|
if($pair instanceof TileChest && !$pair->isPaired()){
|
||||||
|
[$left, $right] = $clockwise ? [$c, $this] : [$this, $c];
|
||||||
|
$ev = new ChestPairEvent($left, $right);
|
||||||
|
$ev->call();
|
||||||
|
if(!$ev->isCancelled() && $world->getBlock($this->position)->isSameType($this) && $world->getBlock($c->position)->isSameType($c)){
|
||||||
$pair->pairWith($tile);
|
$pair->pairWith($tile);
|
||||||
$tile->pairWith($pair);
|
$tile->pairWith($pair);
|
||||||
break;
|
break;
|
||||||
@ -63,6 +72,7 @@ class Chest extends Transparent{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
if($player instanceof Player){
|
if($player instanceof Player){
|
||||||
@ -70,8 +80,8 @@ class Chest extends Transparent{
|
|||||||
$chest = $this->position->getWorld()->getTile($this->position);
|
$chest = $this->position->getWorld()->getTile($this->position);
|
||||||
if($chest instanceof TileChest){
|
if($chest instanceof TileChest){
|
||||||
if(
|
if(
|
||||||
!$this->getSide(Facing::UP)->isTransparent() or
|
!$this->getSide(Facing::UP)->isTransparent() ||
|
||||||
(($pair = $chest->getPair()) !== null and !$pair->getBlock()->getSide(Facing::UP)->isTransparent()) or
|
(($pair = $chest->getPair()) !== null && !$pair->getBlock()->getSide(Facing::UP)->isTransparent()) ||
|
||||||
!$chest->canOpenWith($item->getCustomName())
|
!$chest->canOpenWith($item->getCustomName())
|
||||||
){
|
){
|
||||||
return true;
|
return true;
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -39,6 +39,9 @@ class Cobweb extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
|
if(($item->getBlockToolType() & BlockToolType::SHEARS) !== 0){
|
||||||
|
return [$this->asItem()];
|
||||||
|
}
|
||||||
return [
|
return [
|
||||||
VanillaItems::STRING()
|
VanillaItems::STRING()
|
||||||
];
|
];
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -25,7 +25,9 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\block\utils\BlockDataSerializer;
|
use pocketmine\block\utils\BlockDataSerializer;
|
||||||
use pocketmine\block\utils\HorizontalFacingTrait;
|
use pocketmine\block\utils\HorizontalFacingTrait;
|
||||||
|
use pocketmine\block\utils\SupportType;
|
||||||
use pocketmine\block\utils\TreeType;
|
use pocketmine\block\utils\TreeType;
|
||||||
|
use pocketmine\event\block\BlockGrowEvent;
|
||||||
use pocketmine\item\Fertilizer;
|
use pocketmine\item\Fertilizer;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\VanillaItems;
|
use pocketmine\item\VanillaItems;
|
||||||
@ -40,6 +42,8 @@ use function mt_rand;
|
|||||||
class CocoaBlock extends Transparent{
|
class CocoaBlock extends Transparent{
|
||||||
use HorizontalFacingTrait;
|
use HorizontalFacingTrait;
|
||||||
|
|
||||||
|
public const MAX_AGE = 2;
|
||||||
|
|
||||||
protected int $age = 0;
|
protected int $age = 0;
|
||||||
|
|
||||||
protected function writeStateToMeta() : int{
|
protected function writeStateToMeta() : int{
|
||||||
@ -48,7 +52,7 @@ class CocoaBlock extends Transparent{
|
|||||||
|
|
||||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||||
$this->facing = Facing::opposite(BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x03));
|
$this->facing = Facing::opposite(BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x03));
|
||||||
$this->age = BlockDataSerializer::readBoundedInt("age", $stateMeta >> 2, 0, 2);
|
$this->age = BlockDataSerializer::readBoundedInt("age", $stateMeta >> 2, 0, self::MAX_AGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStateBitmask() : int{
|
public function getStateBitmask() : int{
|
||||||
@ -59,8 +63,8 @@ class CocoaBlock extends Transparent{
|
|||||||
|
|
||||||
/** @return $this */
|
/** @return $this */
|
||||||
public function setAge(int $age) : self{
|
public function setAge(int $age) : self{
|
||||||
if($age < 0 || $age > 2){
|
if($age < 0 || $age > self::MAX_AGE){
|
||||||
throw new \InvalidArgumentException("Age must be in range 0-2");
|
throw new \InvalidArgumentException("Age must be in range 0 ... " . self::MAX_AGE);
|
||||||
}
|
}
|
||||||
$this->age = $age;
|
$this->age = $age;
|
||||||
return $this;
|
return $this;
|
||||||
@ -80,12 +84,16 @@ class CocoaBlock extends Transparent{
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSupportType(int $facing) : SupportType{
|
||||||
|
return SupportType::NONE();
|
||||||
|
}
|
||||||
|
|
||||||
private function canAttachTo(Block $block) : bool{
|
private function canAttachTo(Block $block) : bool{
|
||||||
return $block instanceof Wood && $block->getTreeType()->equals(TreeType::JUNGLE());
|
return $block instanceof Wood && $block->getTreeType()->equals(TreeType::JUNGLE());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
if(Facing::axis($face) !== Axis::Y and $this->canAttachTo($blockClicked)){
|
if(Facing::axis($face) !== Axis::Y && $this->canAttachTo($blockClicked)){
|
||||||
$this->facing = $face;
|
$this->facing = $face;
|
||||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
@ -94,10 +102,7 @@ class CocoaBlock extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
if($this->age < 2 and $item instanceof Fertilizer){
|
if($item instanceof Fertilizer && $this->grow()){
|
||||||
$this->age++;
|
|
||||||
$this->position->getWorld()->setBlock($this->position, $this);
|
|
||||||
|
|
||||||
$item->pop();
|
$item->pop();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -117,15 +122,28 @@ class CocoaBlock extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onRandomTick() : void{
|
public function onRandomTick() : void{
|
||||||
if($this->age < 2 and mt_rand(1, 5) === 1){
|
if(mt_rand(1, 5) === 1){
|
||||||
$this->age++;
|
$this->grow();
|
||||||
$this->position->getWorld()->setBlock($this->position, $this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function grow() : bool{
|
||||||
|
if($this->age < self::MAX_AGE){
|
||||||
|
$block = clone $this;
|
||||||
|
$block->age++;
|
||||||
|
$ev = new BlockGrowEvent($this, $block);
|
||||||
|
$ev->call();
|
||||||
|
if(!$ev->isCancelled()){
|
||||||
|
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [
|
return [
|
||||||
VanillaItems::COCOA_BEANS()->setCount($this->age === 2 ? mt_rand(2, 3) : 1)
|
VanillaItems::COCOA_BEANS()->setCount($this->age === self::MAX_AGE ? mt_rand(2, 3) : 1)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -27,6 +27,7 @@ use pocketmine\block\utils\ColorInMetadataTrait;
|
|||||||
use pocketmine\block\utils\DyeColor;
|
use pocketmine\block\utils\DyeColor;
|
||||||
use pocketmine\block\utils\Fallable;
|
use pocketmine\block\utils\Fallable;
|
||||||
use pocketmine\block\utils\FallableTrait;
|
use pocketmine\block\utils\FallableTrait;
|
||||||
|
use pocketmine\event\block\BlockFormEvent;
|
||||||
use pocketmine\math\Facing;
|
use pocketmine\math\Facing;
|
||||||
|
|
||||||
class ConcretePowder extends Opaque implements Fallable{
|
class ConcretePowder extends Opaque implements Fallable{
|
||||||
@ -42,7 +43,11 @@ class ConcretePowder extends Opaque implements Fallable{
|
|||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if(($block = $this->checkAdjacentWater()) !== null){
|
if(($block = $this->checkAdjacentWater()) !== null){
|
||||||
$this->position->getWorld()->setBlock($this->position, $block);
|
$ev = new BlockFormEvent($this, $block);
|
||||||
|
$ev->call();
|
||||||
|
if(!$ev->isCancelled()){
|
||||||
|
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
$this->startFalling();
|
$this->startFalling();
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -26,6 +26,7 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\block\utils\InvalidBlockStateException;
|
use pocketmine\block\utils\InvalidBlockStateException;
|
||||||
use pocketmine\data\bedrock\CoralTypeIdMap;
|
use pocketmine\data\bedrock\CoralTypeIdMap;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\math\Facing;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
use pocketmine\world\BlockTransaction;
|
use pocketmine\world\BlockTransaction;
|
||||||
@ -65,7 +66,7 @@ final class Coral extends BaseCoral{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
if(!$tx->fetchBlock($blockReplace->getPosition()->down())->isSolid()){
|
if(!$this->canBeSupportedBy($tx->fetchBlock($blockReplace->getPosition()->down()))){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
@ -73,10 +74,14 @@ final class Coral extends BaseCoral{
|
|||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
$world = $this->position->getWorld();
|
$world = $this->position->getWorld();
|
||||||
if(!$world->getBlock($this->position->down())->isSolid()){
|
if(!$this->canBeSupportedBy($world->getBlock($this->position->down()))){
|
||||||
$world->useBreakOn($this->position);
|
$world->useBreakOn($this->position);
|
||||||
}else{
|
}else{
|
||||||
parent::onNearbyBlockChange();
|
parent::onNearbyBlockChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function canBeSupportedBy(Block $block) : bool{
|
||||||
|
return $block->getSupportType(Facing::UP)->hasCenterSupport();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,22 +17,21 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\utils\CoralType;
|
use pocketmine\block\utils\CoralType;
|
||||||
|
use pocketmine\block\utils\CoralTypeTrait;
|
||||||
use pocketmine\block\utils\InvalidBlockStateException;
|
use pocketmine\block\utils\InvalidBlockStateException;
|
||||||
use pocketmine\data\bedrock\CoralTypeIdMap;
|
use pocketmine\data\bedrock\CoralTypeIdMap;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use function mt_rand;
|
use function mt_rand;
|
||||||
|
|
||||||
final class CoralBlock extends Opaque{
|
final class CoralBlock extends Opaque{
|
||||||
|
use CoralTypeTrait;
|
||||||
private CoralType $coralType;
|
|
||||||
private bool $dead = false;
|
|
||||||
|
|
||||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
|
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
|
||||||
$this->coralType = CoralType::TUBE();
|
$this->coralType = CoralType::TUBE();
|
||||||
@ -60,22 +59,6 @@ final class CoralBlock extends Opaque{
|
|||||||
return 0b1111;
|
return 0b1111;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCoralType() : CoralType{ return $this->coralType; }
|
|
||||||
|
|
||||||
/** @return $this */
|
|
||||||
public function setCoralType(CoralType $coralType) : self{
|
|
||||||
$this->coralType = $coralType;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isDead() : bool{ return $this->dead; }
|
|
||||||
|
|
||||||
/** @return $this */
|
|
||||||
public function setDead(bool $dead) : self{
|
|
||||||
$this->dead = $dead;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if(!$this->dead){
|
if(!$this->dead){
|
||||||
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, mt_rand(40, 200));
|
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, mt_rand(40, 200));
|
||||||
|
@ -17,13 +17,13 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\crafting\CraftingGrid;
|
use pocketmine\block\inventory\CraftingTableInventory;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
@ -32,7 +32,7 @@ class CraftingTable extends Opaque{
|
|||||||
|
|
||||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
if($player instanceof Player){
|
if($player instanceof Player){
|
||||||
$player->setCraftingGrid(new CraftingGrid($player, CraftingGrid::SIZE_BIG));
|
$player->setCurrentWindow(new CraftingTableInventory($this->position));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* @link http://www.pocketmine.net/
|
* @link http://www.pocketmine.net/
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
@ -34,6 +34,7 @@ use pocketmine\world\BlockTransaction;
|
|||||||
use function mt_rand;
|
use function mt_rand;
|
||||||
|
|
||||||
abstract class Crops extends Flowable{
|
abstract class Crops extends Flowable{
|
||||||
|
public const MAX_AGE = 7;
|
||||||
|
|
||||||
protected int $age = 0;
|
protected int $age = 0;
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ abstract class Crops extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||||
$this->age = BlockDataSerializer::readBoundedInt("age", $stateMeta, 0, 7);
|
$this->age = BlockDataSerializer::readBoundedInt("age", $stateMeta, 0, self::MAX_AGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStateBitmask() : int{
|
public function getStateBitmask() : int{
|
||||||
@ -53,8 +54,8 @@ abstract class Crops extends Flowable{
|
|||||||
|
|
||||||
/** @return $this */
|
/** @return $this */
|
||||||
public function setAge(int $age) : self{
|
public function setAge(int $age) : self{
|
||||||
if($age < 0 || $age > 7){
|
if($age < 0 || $age > self::MAX_AGE){
|
||||||
throw new \InvalidArgumentException("Age must be in range 0-7");
|
throw new \InvalidArgumentException("Age must be in range 0 ... " . self::MAX_AGE);
|
||||||
}
|
}
|
||||||
$this->age = $age;
|
$this->age = $age;
|
||||||
return $this;
|
return $this;
|
||||||
@ -69,20 +70,19 @@ abstract class Crops extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||||
if($this->age < 7 and $item instanceof Fertilizer){
|
if($this->age < self::MAX_AGE && $item instanceof Fertilizer){
|
||||||
$block = clone $this;
|
$block = clone $this;
|
||||||
$block->age += mt_rand(2, 5);
|
$block->age += mt_rand(2, 5);
|
||||||
if($block->age > 7){
|
if($block->age > self::MAX_AGE){
|
||||||
$block->age = 7;
|
$block->age = self::MAX_AGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
$ev = new BlockGrowEvent($this, $block);
|
$ev = new BlockGrowEvent($this, $block);
|
||||||
$ev->call();
|
$ev->call();
|
||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
|
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
|
||||||
}
|
|
||||||
|
|
||||||
$item->pop();
|
$item->pop();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -101,7 +101,7 @@ abstract class Crops extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onRandomTick() : void{
|
public function onRandomTick() : void{
|
||||||
if($this->age < 7 and mt_rand(0, 2) === 1){
|
if($this->age < self::MAX_AGE && mt_rand(0, 2) === 1){
|
||||||
$block = clone $this;
|
$block = clone $this;
|
||||||
++$block->age;
|
++$block->age;
|
||||||
$ev = new BlockGrowEvent($this, $block);
|
$ev = new BlockGrowEvent($this, $block);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user