mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-09 19:24:12 +00:00
Compare commits
1759 Commits
1.7dev-501
...
3.7.0
Author | SHA1 | Date | |
---|---|---|---|
14a6779e08 | |||
cce99b07af | |||
baa094a2d1 | |||
f2ff510597 | |||
562179bdd6 | |||
5c12bee874 | |||
99606bbe23 | |||
a1d50de12e | |||
4252c5914b | |||
0659d2fbef | |||
10612acace | |||
1d810f8aeb | |||
414104851a | |||
c0bed03a2a | |||
d25c84acff | |||
55994e08db | |||
6f5d4d6b80 | |||
df1ef7fe0c | |||
20a25a69df | |||
faca610594 | |||
91603dc2d6 | |||
af90e18b18 | |||
ab5b4d112b | |||
a30b1fb6d5 | |||
20b4723728 | |||
d1ced0ffc6 | |||
2164dbae67 | |||
6c92a2e88b | |||
97deadc59f | |||
0c3b136a8d | |||
79b7e08e60 | |||
2540dacdd7 | |||
f1078e3909 | |||
2f43b054de | |||
23b5d64535 | |||
9afa0e5483 | |||
4eaea54b0e | |||
6b51bf4a80 | |||
cba8d86c4f | |||
2e834c8f5c | |||
f9873e9108 | |||
074baf7e1c | |||
2e0dd574e0 | |||
e16d8e31af | |||
3c93a57397 | |||
e2e927b328 | |||
a8dab25201 | |||
3de2b7969e | |||
8f486ea65d | |||
6b971b1761 | |||
6f36fa504b | |||
8e73842a93 | |||
e71e18fc88 | |||
e1bacb5c6d | |||
44697e784a | |||
65529ff2ce | |||
c346c45d42 | |||
c433fad0a7 | |||
8fad5a6e30 | |||
7a6f279825 | |||
10b72c895d | |||
d520928888 | |||
27767e7ddb | |||
243c12de7c | |||
372545e47e | |||
8913b48700 | |||
6ee4a0e090 | |||
8bd8da4bc6 | |||
9ba4144a71 | |||
9da7c6af27 | |||
109312284c | |||
51934614bc | |||
9e89f65094 | |||
9562711b84 | |||
30b49e0d22 | |||
a975868fc3 | |||
b38b932845 | |||
43cb19ebca | |||
769cc91543 | |||
278f37d3e0 | |||
02a6ca84a9 | |||
b8703d5dff | |||
37c2d78731 | |||
b7663e5815 | |||
1d0ffa06f8 | |||
768cfe3953 | |||
2822465f33 | |||
5da48f429f | |||
dbd0d04549 | |||
0f92ec6d2a | |||
791b4d8ef3 | |||
0b7ff6f2e7 | |||
af092b01e1 | |||
d811217755 | |||
d7f86f0240 | |||
5fe1d2e396 | |||
ddbb5363ef | |||
d3704bfae4 | |||
07f034d2da | |||
331ae5498f | |||
eebd90ec42 | |||
8e47a40b4c | |||
0f9fdf6442 | |||
5364e4de68 | |||
1099e2044b | |||
80d48161d3 | |||
fbe8485696 | |||
a150f39b02 | |||
71d17c50d6 | |||
3a18bdd6a0 | |||
96857c65b6 | |||
9826abd83e | |||
48c8c2a8c3 | |||
c83b7d9b69 | |||
c66dc7b273 | |||
5bf7350ee5 | |||
636cc1c199 | |||
62b6405371 | |||
9ecf23d3ee | |||
187f36fe38 | |||
dc89b48354 | |||
e6d1c1dfbc | |||
5a8812b1dc | |||
4b8e4123af | |||
45a4252c26 | |||
feaaa925a7 | |||
5221db1178 | |||
47321114eb | |||
a27c9409f1 | |||
854f851525 | |||
9003b38be3 | |||
a6a93f822f | |||
d4851a8f1f | |||
480a513f30 | |||
4fd3bee360 | |||
41fd7545e3 | |||
82dddde159 | |||
bc709efb77 | |||
cd98e6a23e | |||
cb591a98f4 | |||
e9d1af0aee | |||
0f545c410a | |||
1c2ed0836f | |||
6cf30dc813 | |||
f7d9247d39 | |||
3380aa3ac2 | |||
6a9cad8fb7 | |||
c9e598cdb9 | |||
a6e5b6e158 | |||
22a6b817d7 | |||
2cdf97b7b5 | |||
836cb67850 | |||
ab37df4484 | |||
93969197f7 | |||
946a1036f1 | |||
43410cdafb | |||
a99e15012c | |||
b22a2ef914 | |||
f7f7be896e | |||
254281cd5e | |||
5dfceeea98 | |||
4b9a142a5d | |||
0bacf51729 | |||
33f6b441d8 | |||
11b59498d9 | |||
d71a543d10 | |||
5e0c3333cf | |||
0f941410f6 | |||
504cc3bf8b | |||
6bd1491b8b | |||
658786f2f6 | |||
d34f3f1af3 | |||
8650c187f9 | |||
4b4820cf53 | |||
d33acc4fd0 | |||
f7de6eb59f | |||
75a0627bf2 | |||
8752e363c9 | |||
9ed1b5ca7f | |||
1cbb31f1db | |||
1393b4c4e2 | |||
2921c86b3c | |||
9c3a929b65 | |||
9abaa42cd7 | |||
77b9feb3c0 | |||
e0e2e1775f | |||
d2d65ce6cc | |||
ff2e982f22 | |||
daf56e990b | |||
3f5e83a322 | |||
5ecc5ed7e0 | |||
cd80ae00d4 | |||
beb5d72299 | |||
0eef634aab | |||
0ea166a551 | |||
6417cff618 | |||
a71af952ba | |||
93dd05a03e | |||
98f903783c | |||
5d47ea4337 | |||
c242d6213a | |||
4ad1093fd7 | |||
fc0782df02 | |||
bfaa224f6b | |||
de88f0fce1 | |||
9b078854c4 | |||
42f8e061a5 | |||
1455c38dbe | |||
75df6973df | |||
4763360e9e | |||
0299191e64 | |||
2664a1b4d8 | |||
4249c00c3e | |||
517c4e5143 | |||
69c343bb9b | |||
70df1579a8 | |||
ea9f9aa250 | |||
34a899e28b | |||
b80868040e | |||
a7f1181335 | |||
bf8a8b386e | |||
4b518f2a58 | |||
60b1f0a6e9 | |||
5934399a0d | |||
b42132a7c3 | |||
c05697f506 | |||
d4fe1b8ece | |||
9b2653fb6f | |||
ed88684e71 | |||
cbb9c4f298 | |||
660d42e8d1 | |||
dbeceb02f9 | |||
fd77dd0066 | |||
87ce87112b | |||
1d71f5edb3 | |||
0f620157e8 | |||
2323601f98 | |||
d34b94302f | |||
ec4c61e113 | |||
231e491bb9 | |||
69cdc6f13a | |||
dfeb62491a | |||
178eedb536 | |||
4975da2aae | |||
5946ec8819 | |||
abf0dee426 | |||
30f5a8fac6 | |||
f704061618 | |||
23dc6e09d8 | |||
15b7fc978e | |||
bb396174ba | |||
dcef3cba21 | |||
5f8a9f8747 | |||
84e41e6967 | |||
5e0e0daf7d | |||
a95694ed06 | |||
762405d16a | |||
e3f46987f5 | |||
e4223bb7dc | |||
f091446ec7 | |||
b0f891081c | |||
acd7c9b336 | |||
75482124f2 | |||
288599cbe7 | |||
aa7206126a | |||
1a6db1c7ce | |||
f1c071ce7f | |||
e2f46a4358 | |||
36c0c350a7 | |||
4c08a05fae | |||
6295ef8a81 | |||
05dba61a69 | |||
b473ffdedc | |||
60dddcd12a | |||
c010ef45ed | |||
93c26a0b0c | |||
08ec021f78 | |||
545ec9c881 | |||
b0060caaf7 | |||
c90d1faa81 | |||
d5a1961e6b | |||
449dda83fb | |||
6bc79149c3 | |||
cdf7e28251 | |||
a02f422d85 | |||
f8bfbc107d | |||
554c029fbd | |||
e018311e73 | |||
de50f02076 | |||
71d02e5870 | |||
46d9475568 | |||
788b278fc3 | |||
2e4143f57e | |||
d312aef1ac | |||
200de3fe84 | |||
f560a6efea | |||
7ecd7fd13f | |||
5284ad0346 | |||
b893645a81 | |||
b19b3134ad | |||
7cf36f460b | |||
243f86b0a0 | |||
9156cbc269 | |||
a5f776af2f | |||
43fe6a1934 | |||
342a74ffcb | |||
3d2701e775 | |||
2183bf875c | |||
8cc2a4ce5d | |||
e26af3fa1b | |||
1634dd62e3 | |||
755db3dac8 | |||
3dabf90b0e | |||
f61e14e341 | |||
7b24fbc8db | |||
0543c17849 | |||
c4f3426bae | |||
046c39b02e | |||
87b471ce0f | |||
055ba6aa7c | |||
5c3eed40b3 | |||
3e5237b6e0 | |||
af1227f154 | |||
d9a867016c | |||
a50a863ab7 | |||
9caf62778c | |||
d257d36e55 | |||
1b03168b88 | |||
6b9fee05d6 | |||
44d8a5528e | |||
45a18ffe1e | |||
f0182c9996 | |||
265b61b3e6 | |||
2d88058710 | |||
ab48d85c35 | |||
cf43f479df | |||
c143834632 | |||
d9b7a28747 | |||
31ceafa111 | |||
a0eb6e23e5 | |||
694d7d4e20 | |||
2da2fdd6d4 | |||
0aa30295af | |||
c1c56f29bb | |||
9b820a0849 | |||
c6a4bc4bf7 | |||
3128449033 | |||
a60154e0b7 | |||
4cbbf2e91c | |||
b0624aff9f | |||
c38e2c5ccb | |||
02ef0bfbb4 | |||
a714612453 | |||
4835537886 | |||
4a6841a5a4 | |||
f61e099828 | |||
925da62afa | |||
09985c5763 | |||
447b9562bb | |||
d1ee9eb960 | |||
196cf8a68d | |||
cac21c2caf | |||
6dd2597934 | |||
5e68858ebf | |||
45c9caa38c | |||
b35759cc25 | |||
2a40c0d82c | |||
8ac1b18b17 | |||
4aef9919dc | |||
43426a4c5c | |||
3028832cd3 | |||
9f8a2dc61a | |||
d9ebe6f321 | |||
cb1eb1ee09 | |||
d563b9e31b | |||
7c44eea625 | |||
d749f19c73 | |||
41fd03f329 | |||
646c8970b8 | |||
58067b2ad1 | |||
0c9946621c | |||
f1cd6940f9 | |||
af5637e050 | |||
4221e274d6 | |||
a524b0e447 | |||
88a5e92c20 | |||
b876ae4ef8 | |||
1983964f9e | |||
c4c55a45c9 | |||
c5cd813b76 | |||
bc2dff3f51 | |||
839d5eab7b | |||
cd506bb443 | |||
4c8ffce86f | |||
78923177f9 | |||
df6bb2ea0e | |||
b7062e7bff | |||
ba68192206 | |||
6579930638 | |||
a0ab996b9f | |||
97980d4516 | |||
b261129788 | |||
d9220395d1 | |||
4f2f373a24 | |||
2858db430e | |||
de6d62aba2 | |||
32836cbfb8 | |||
8316e00927 | |||
6f694b0801 | |||
fd459cda54 | |||
a66dd4a7d9 | |||
3617eba4a3 | |||
e79cc98883 | |||
a3552875cb | |||
d259b2c9ee | |||
10fa74b417 | |||
ab5aec6c30 | |||
0e508876d2 | |||
50b89c30f8 | |||
17ceb27af4 | |||
adbd1c7bed | |||
495fdbd19f | |||
620784e4e7 | |||
cf20e626e2 | |||
d75c830a7e | |||
1dd6591ac1 | |||
6efef3bbc7 | |||
b1e0f82cbf | |||
c065cfbeda | |||
722924a779 | |||
60e1b29462 | |||
0171095036 | |||
5b511f6d06 | |||
426dee04a6 | |||
9d8898a4ed | |||
3bb22f9778 | |||
bb1944ca40 | |||
d1a20ecb4a | |||
16c636df83 | |||
f6a8ec83a1 | |||
28137efb53 | |||
e597067a92 | |||
06f00020cd | |||
7b0836d399 | |||
cea146e335 | |||
5eeaeb6c3e | |||
2712287995 | |||
8db1ccc1ae | |||
5d56030afa | |||
6be5e75263 | |||
d9c251b613 | |||
8085b81f5c | |||
6b44f99dfb | |||
33d3fff3c5 | |||
7c092b93b4 | |||
aa05650994 | |||
758d9b9784 | |||
24a6bf7365 | |||
9a5d51fd3d | |||
fa9ea6a7d7 | |||
6a7f39978b | |||
c52e1ea9f9 | |||
5e94d20d79 | |||
a0bb747d6d | |||
4bc0d850b1 | |||
ad9df6764d | |||
97583c8b04 | |||
107192c753 | |||
6309a242dc | |||
870f9abc20 | |||
0e2bbc44db | |||
e58d015f14 | |||
d9768abe47 | |||
e9b84ecc8b | |||
0d65f9c4b8 | |||
c83d12790e | |||
5863d4c066 | |||
22077c1fdd | |||
7d54d18732 | |||
bfbc845efa | |||
f33c19e77a | |||
2ff4228fb7 | |||
06c4f31db7 | |||
09dea035d4 | |||
a9fc67663c | |||
519659fd2b | |||
6c70e84fa2 | |||
7d0e631a75 | |||
5134c0cf5a | |||
65b751d080 | |||
27effff403 | |||
a940cc5b5e | |||
15e654131c | |||
6e6cda91ce | |||
0aa63d269a | |||
53a76c0d14 | |||
69500fe183 | |||
191f0038b8 | |||
99d6aa92cb | |||
90d01f5ed2 | |||
5af4dd20df | |||
c7d58db7eb | |||
a3b78236eb | |||
b70905b287 | |||
d8e27e6081 | |||
7a48c0b23d | |||
14a2ffa51b | |||
c447d51e3f | |||
557fd34754 | |||
32077d96b4 | |||
9f4722f537 | |||
cb04f287eb | |||
f649ef5195 | |||
b615cad22d | |||
b93e219231 | |||
a4a9309193 | |||
e621cde8f1 | |||
56ee957fda | |||
1193efd69e | |||
2738e38aee | |||
f466fd5568 | |||
72d447276b | |||
d5a5209334 | |||
3a85e6cab9 | |||
d0aff2ecbd | |||
bca493a682 | |||
ba12dfafd6 | |||
e09087de26 | |||
888dba704b | |||
511249c562 | |||
17f1bf5512 | |||
5179bb1d30 | |||
6bff840293 | |||
08897c6941 | |||
05d9bb45d0 | |||
dfe2aa9c67 | |||
4006be35d9 | |||
e5cda34548 | |||
032b20f659 | |||
fe6d546190 | |||
c7af1cf785 | |||
22fcfffa53 | |||
7dd53f2397 | |||
298259b473 | |||
c123f2d10b | |||
3e6f70ddf6 | |||
bea634a9b7 | |||
8daf3dc8b4 | |||
4cc7573a64 | |||
9d80802e53 | |||
ec1e257e21 | |||
d419d4308f | |||
9ca38ba868 | |||
424c50e1e9 | |||
566f3c6262 | |||
0d05dcec08 | |||
986077e03c | |||
ddcb2f002a | |||
c496480d2b | |||
6fce2b3349 | |||
64ed8adefc | |||
2eda8cfad3 | |||
91be5aba0c | |||
5df601c817 | |||
21e7b5ea43 | |||
8304675af7 | |||
1a47735d84 | |||
0cdf4d0c55 | |||
e6e28b74b5 | |||
ebffff0caa | |||
0dc4bd36e1 | |||
9d17c9a09d | |||
72f46b4631 | |||
3892f2f404 | |||
bfa415e108 | |||
b66095cb36 | |||
0336ae8229 | |||
4a1d67cb91 | |||
b4694092b7 | |||
4b3e17e681 | |||
d99ee515c6 | |||
17f7dc34be | |||
a63d66c048 | |||
95f6995ae0 | |||
4a24d7909e | |||
5424644ca1 | |||
4e2387edc1 | |||
a5e38576ef | |||
aa7c4bc64d | |||
381151dedc | |||
a604e6835e | |||
df8e10cad9 | |||
d98a6e566c | |||
142a6d7678 | |||
b2ca364de0 | |||
ade2be9eee | |||
09ed40a921 | |||
565373cee6 | |||
c29723e3c4 | |||
39ed6a7cdf | |||
a8811ab2b3 | |||
bec5aaa54b | |||
974583a853 | |||
03f8fe62d4 | |||
cf29ab1f17 | |||
c5c5a53a13 | |||
699f35cc05 | |||
8fa196efc9 | |||
63a65680ac | |||
47cd6fe105 | |||
f582b5a3db | |||
b1ab881b99 | |||
69c54e789a | |||
7f0fa2ac3d | |||
f3b2bcfd13 | |||
c947909c2e | |||
09dadc72bc | |||
e33d1279fa | |||
9e1fa453ad | |||
ca541032ae | |||
bcf9915082 | |||
6a05edb4e9 | |||
70635d0870 | |||
8d6dc4e188 | |||
46bd096f06 | |||
51a8905fb3 | |||
f954d7c3dc | |||
7ad0aa56b1 | |||
1ff6f8846e | |||
12d8d925c8 | |||
f3f229ef7c | |||
6614183c7f | |||
e6f53cc56b | |||
87f458f9bd | |||
5a7e575c3a | |||
7ebf3c7bf4 | |||
20b37d0208 | |||
d6d98183ea | |||
334caaaa34 | |||
89cf76363f | |||
9ff5c65fb6 | |||
1532b0ef6d | |||
6fcaef068f | |||
61accee682 | |||
9ece971a2b | |||
5546c88f88 | |||
c09ad9263b | |||
4c4761d200 | |||
5492495d38 | |||
6bef07db7c | |||
e8c7ae595d | |||
0d9f40873f | |||
4cc2f037a9 | |||
f7358cd7e1 | |||
a4aee98cba | |||
a97c7d3132 | |||
99045fe21a | |||
bda271ca63 | |||
808d289610 | |||
4a1ed21e52 | |||
b3f2396ea5 | |||
ab0510cb37 | |||
06c035bfe6 | |||
1b053c7928 | |||
c684f99cc4 | |||
9a423be1db | |||
08be51dc23 | |||
94352782d5 | |||
8fae79f85b | |||
8d47a222b4 | |||
695793795e | |||
9a2845640b | |||
580f71d496 | |||
24f11779f2 | |||
706c620d04 | |||
951870e6ec | |||
9f425bbe2b | |||
a4965842d6 | |||
1405099768 | |||
d0339796b4 | |||
1464487945 | |||
40c28f4d26 | |||
90bf94f8f7 | |||
5e13e2e777 | |||
1ef6f5d166 | |||
eccc249009 | |||
522ef042a7 | |||
4be36914d6 | |||
e3ef1ecb30 | |||
dbaf7287bc | |||
3640062142 | |||
9af70283fd | |||
b3b240e25b | |||
76ee6bc298 | |||
b18872fbc6 | |||
2b30ef1671 | |||
04f20c703c | |||
dd8499e202 | |||
124ebf69c5 | |||
efe4b0cd3a | |||
4d1e56069d | |||
4274640845 | |||
527d8e9374 | |||
c1c70a8a98 | |||
45d30d53cc | |||
cfc8dfa369 | |||
93a2f397c6 | |||
62fc875cdc | |||
58b665985e | |||
0f5c48e342 | |||
b7f15b6574 | |||
08ad5db05b | |||
6ab2fa84da | |||
b480c63060 | |||
f6b54f5116 | |||
89bfc380e3 | |||
94e8623c75 | |||
40030e9800 | |||
ad1cf38c21 | |||
5d769147ca | |||
6f00a30ad7 | |||
b4bf6901e3 | |||
921f7e8f6a | |||
71c3c34976 | |||
16c253d7a9 | |||
7efe767f1f | |||
710e1d014d | |||
2e18fe710c | |||
165aac1ba3 | |||
878dd3b842 | |||
7fc22d3227 | |||
478a131aa5 | |||
53068caf3c | |||
fe7ad7a5b3 | |||
7bfe487ee5 | |||
24f749a933 | |||
d8cf835f92 | |||
65e44364e5 | |||
af80aefd45 | |||
1d5c741f28 | |||
3a373b880d | |||
1b7cd156aa | |||
ebbbc581ca | |||
8aa8280a63 | |||
6a637d9099 | |||
7a164a8254 | |||
4a5ff32d2e | |||
066c990301 | |||
06b80a9536 | |||
b5dcdea6d8 | |||
287ff8d7bf | |||
b3ffce9729 | |||
ce9f18c6b4 | |||
9610c55b19 | |||
1087212d75 | |||
b01b477a2a | |||
0c350f2f57 | |||
bfcef2ab6b | |||
2994d0f3ae | |||
2d454ae56f | |||
066c9d4fd4 | |||
23829952c3 | |||
57cc0ebe75 | |||
7ee98ff139 | |||
f1cab91ac9 | |||
7554d9a370 | |||
e0bc9c5e96 | |||
32574118ea | |||
5a3135659b | |||
70caa00266 | |||
ee7c838040 | |||
34e9e93210 | |||
b90d7d1839 | |||
5dbb0d177e | |||
670b940837 | |||
6cad7be3ef | |||
28a72a93b4 | |||
58f0ad3e3e | |||
0df3585c81 | |||
697723b551 | |||
5926d80525 | |||
0f0d12bebc | |||
dfc11abf2d | |||
17eef9f902 | |||
a57ec1b1ba | |||
905259a4e1 | |||
b04319a4ab | |||
ca6930006c | |||
33eeeb856e | |||
0afbf6c547 | |||
c43ce5c8fa | |||
57cfe9fd43 | |||
d8824e7ee1 | |||
3455d0f3b9 | |||
ec2cca04a7 | |||
6b2250cbce | |||
8dae497610 | |||
cade15e2dd | |||
272b76d24c | |||
8c672cb7c8 | |||
4d9368f205 | |||
97c267c70c | |||
85a3c0e7dc | |||
d3e54db146 | |||
0081e30a89 | |||
2f70a1eefb | |||
7ba6e92b6c | |||
76174f1920 | |||
47c862bc38 | |||
860c20109b | |||
1c0b49343c | |||
814a949580 | |||
b393f5f17e | |||
f1970492c1 | |||
dd6b5902a6 | |||
87852f2fe1 | |||
056d24c67d | |||
4c9ca53b32 | |||
484d34fe04 | |||
6c6630d845 | |||
a5a236084f | |||
390db976e5 | |||
98ac534820 | |||
641a5a5e23 | |||
ebacb8525f | |||
579ab5866b | |||
56b04fa0bb | |||
95787c2be9 | |||
7b7be9618c | |||
4a8232d591 | |||
40e5a1aacb | |||
dbda044229 | |||
d2a037de71 | |||
03510333dc | |||
064e9464bc | |||
2d3ce9e8b0 | |||
49f80830a7 | |||
80daaf09b2 | |||
30ad3a1705 | |||
4e7d1a7947 | |||
da6439e3f4 | |||
5f2d4c36c0 | |||
1f9bed275a | |||
77f3ca4d47 | |||
d88368ceb6 | |||
f77a829a52 | |||
f315aca4c3 | |||
9f7f62e9e5 | |||
cc97f76ec9 | |||
3b0aad38cf | |||
a9b7cd1699 | |||
37b65aac91 | |||
ad7787e13b | |||
7b0ce16b12 | |||
0ff6b7b572 | |||
763e20ba4e | |||
4b99285fd6 | |||
03a55d5e9d | |||
fe29b89fd1 | |||
b0780c4d1d | |||
c835c97aba | |||
78eae28a3e | |||
31c187f366 | |||
2e6afa54c2 | |||
e36a6dc8cc | |||
2e9e44ba05 | |||
c9ec6f0a63 | |||
60836ebec9 | |||
3def3cd502 | |||
b5da6b1591 | |||
8a9af7bf2f | |||
8cfd5604cf | |||
f51743765d | |||
0b9ce8a0d4 | |||
c3c360f589 | |||
5a55d434ab | |||
19d2d6b91c | |||
ff2e99ecdc | |||
07a156f5c4 | |||
13fe8ee96d | |||
eb0276d459 | |||
cfb10360ff | |||
05af87e1d4 | |||
b3ea9606c7 | |||
a080a9b75c | |||
137a05c418 | |||
245f5c6bef | |||
3be6665e3d | |||
8704d378d4 | |||
b9718f9e87 | |||
1d1e6966a2 | |||
610b7bd8b0 | |||
17607b8116 | |||
4c98d9d3ad | |||
7d5b3079bc | |||
88d83e0fca | |||
4b221c0601 | |||
e867427f71 | |||
c4c6c58615 | |||
89643ff9af | |||
9657d50aeb | |||
3725bea3e5 | |||
f3a84b332b | |||
f6481eab8f | |||
8e5aca70b4 | |||
85136b7b4a | |||
47742d74c8 | |||
ca54c8d78e | |||
601811f0f8 | |||
aeb551b317 | |||
37b445f210 | |||
d04991feb6 | |||
c327b3d2c4 | |||
af69418a55 | |||
8cd311bcb4 | |||
78ec3937bf | |||
4e3e807741 | |||
8c6161a4f2 | |||
c8a87b14d5 | |||
8fca7cc68d | |||
45f940681a | |||
e3c97d7d5e | |||
172abef2a7 | |||
709abb02e6 | |||
428ca29e4b | |||
f61ad20f6b | |||
3c9af5cd6d | |||
996935e9b2 | |||
3707a41b67 | |||
354b2dc5d1 | |||
0c70b83d81 | |||
083a1e1ff6 | |||
17b58357fb | |||
96a4dbb7d8 | |||
5eec683110 | |||
0bca3cd481 | |||
b54197904d | |||
fb484087a8 | |||
14914781fc | |||
fdd5b7b9c9 | |||
c83c0eb935 | |||
b331f8e1c9 | |||
ee787974f2 | |||
73e56c8a36 | |||
5f7c884255 | |||
2b5e6b790f | |||
1a21041d00 | |||
7b17a83227 | |||
edd150971e | |||
38f4afb17c | |||
9d16863b1a | |||
41a179e6e1 | |||
3a31c531af | |||
e081b7dffa | |||
0233ae1eb6 | |||
dce8ed9dd1 | |||
35eaf38ca1 | |||
1d71f0cf43 | |||
9644766df3 | |||
857f6dd5df | |||
0d177d5219 | |||
fe21f0e916 | |||
4c1d29cdf7 | |||
fa21cd96c5 | |||
a22e5616f6 | |||
b6317fa7ce | |||
b1cb63ebd6 | |||
7b7917939a | |||
6aaaaefd2f | |||
1bb0337420 | |||
b6b0bbde18 | |||
5d07f66d86 | |||
ec28612a12 | |||
6047810113 | |||
d535fe20a3 | |||
515e4aabc4 | |||
f27c6fcf70 | |||
7864a315f6 | |||
02b4eeeb9b | |||
6b4b4e4bb1 | |||
f2b8d6879f | |||
60212cef2f | |||
15270f8329 | |||
05ef13b23a | |||
1b4723d816 | |||
c493d0e6ac | |||
b3043f9552 | |||
18fdbc2834 | |||
a8c766be88 | |||
e20be3eeba | |||
51f43fb375 | |||
132746aa3d | |||
d03f36ebee | |||
7fce48d38c | |||
b7ca045c51 | |||
81957d133d | |||
299e4c8a85 | |||
0a50b8cb9b | |||
6d53350291 | |||
ad61d70eee | |||
353a1d69db | |||
1d8b77f16e | |||
e3d2fa10a5 | |||
ad15ab5b42 | |||
b003295d01 | |||
4f8f334436 | |||
71fdd59c4c | |||
0a9ed059d6 | |||
74c0863905 | |||
87ff1c0382 | |||
2eaba7c936 | |||
3ee6bfca2a | |||
63ab27550a | |||
d612988882 | |||
c9a0c381b1 | |||
982444949c | |||
8cf0fc63d8 | |||
c18ba38b74 | |||
3a1df1d99e | |||
8ccd13319c | |||
c513d355cb | |||
02b53785be | |||
9dd0ee7f05 | |||
595f1f58da | |||
509e8c5f6d | |||
263cd900a8 | |||
164ce76ff5 | |||
fbf760bafe | |||
2c1afe5f2c | |||
b109b457dc | |||
e12e2897bb | |||
8f41384923 | |||
acf29711c2 | |||
1c4dd4f280 | |||
faa88a55e4 | |||
c9ed517063 | |||
28b0f5f86a | |||
e87e2d4e52 | |||
86c27953ec | |||
5552704922 | |||
c7ac5dfd4b | |||
bd9b59f401 | |||
2f03f5f6d5 | |||
f4a26ddfd9 | |||
adb9390b53 | |||
6111ce7df1 | |||
1f73c08762 | |||
2900167ffa | |||
11cc9f19ad | |||
807af2e6fb | |||
f2511983cf | |||
bac649137b | |||
71224f51d5 | |||
6c3fc4af46 | |||
75d13be38e | |||
9bc860f7a8 | |||
66963fbf9a | |||
172c6420c1 | |||
e7fc9227bc | |||
13cd0cdcfd | |||
0bb5e88b5c | |||
389990e0a8 | |||
067aad9546 | |||
b1a7606e82 | |||
febba6e3a6 | |||
d8dc89e7c8 | |||
b75413e3c4 | |||
f08537a1e0 | |||
6643fa5f09 | |||
210e108574 | |||
813437e3ee | |||
24295ce02f | |||
29fd26627e | |||
22b91aaa24 | |||
f757ba1851 | |||
8c1c8f34cc | |||
c285295037 | |||
2034caf71c | |||
89ccac7a8c | |||
f6e71d8296 | |||
b333a0e24c | |||
8312ad709e | |||
63fc04b3dd | |||
34b8557094 | |||
edaef588ab | |||
889222e9c5 | |||
8239c67b1a | |||
ed65e91a3c | |||
619390c5b7 | |||
7e70569ba2 | |||
083ac8a770 | |||
b21572774a | |||
b8523cb304 | |||
6ceb9af749 | |||
bcd197d7bb | |||
3148f692c1 | |||
d8d22efc3b | |||
7b3653f75d | |||
9c5f7128a4 | |||
1e4a97f921 | |||
4d743ade45 | |||
78b5cc993b | |||
5e91c05424 | |||
e7c5d14af3 | |||
126a97b405 | |||
753ed3801d | |||
68ef4b210d | |||
c3822b795c | |||
be0e85dfae | |||
72690ea7f5 | |||
c9bd60123b | |||
05f4262e81 | |||
dd11bcaf11 | |||
b96adda14d | |||
5c66c615bf | |||
2ff2a2de08 | |||
78f8d54f89 | |||
5b6762d0d5 | |||
2a0a2134d1 | |||
e70af362d0 | |||
24aab8365e | |||
0e5504ed3f | |||
83008440c0 | |||
b14dfa9f7e | |||
197102ca3d | |||
f497e43db3 | |||
38c3f00ef7 | |||
396056c636 | |||
dd1dfefd83 | |||
68638f9779 | |||
7565b786e7 | |||
ae0c1c185f | |||
723251e800 | |||
295016cbc1 | |||
8228774ad4 | |||
2a54726905 | |||
8b225fc4ef | |||
a014b44b69 | |||
c7544c1d25 | |||
eb28622823 | |||
68494f1c0d | |||
27ea0d360f | |||
d384df1f2e | |||
fe8102c062 | |||
8b15d85469 | |||
a5ba716232 | |||
db432bb024 | |||
91486a23a5 | |||
d80c471ae1 | |||
b4068dfd2f | |||
3095eb544d | |||
0247dff909 | |||
5368120f13 | |||
2e7db552dc | |||
53c35aaa1d | |||
3293074cfc | |||
d8f4dde5f3 | |||
dfa6cd2b7e | |||
e03d2b23f7 | |||
96a2fd7482 | |||
88c56bcdc8 | |||
2731fc3d0f | |||
a02f178f80 | |||
96d26a77a1 | |||
554fe4d14d | |||
532269a484 | |||
1e2122d854 | |||
c276ef2b7f | |||
5138bdc4bd | |||
a30a157d8c | |||
e565cdeea4 | |||
556a465c05 | |||
280f2b7259 | |||
933b0e8b41 | |||
58279d4cfe | |||
1e21066c1c | |||
76854da7ba | |||
46cbcb0c42 | |||
af9b0b019d | |||
7db8845375 | |||
f47f593555 | |||
691df5c11d | |||
9a1d3aec6b | |||
670a53ba3b | |||
f22ad14c67 | |||
64540f36be | |||
e66b1953de | |||
aa6666872a | |||
646455f6e8 | |||
05a1e61e5b | |||
5f52e00213 | |||
476ac39988 | |||
5f1ae1059e | |||
08d8adae5b | |||
8d988af7db | |||
db5890fddb | |||
5b532fdcf5 | |||
e85fc54037 | |||
7fb237938c | |||
9a5f9c8586 | |||
4b16be7e0b | |||
47faf5a994 | |||
3f31f6d310 | |||
c06c1c7ce0 | |||
a889a0e517 | |||
9ed0d9d36f | |||
3134fa2744 | |||
2660448601 | |||
eb354916d4 | |||
033b44df5a | |||
ef2dd1de92 | |||
5b7b2dd0e2 | |||
3a10df634b | |||
f1aecc3a71 | |||
42d04a4418 | |||
3fe4ebc301 | |||
d97abfaa7b | |||
526f05631e | |||
ebaef89e06 | |||
6ab0cff9d3 | |||
ae31ce1d25 | |||
a1cf5dbd1e | |||
c86132028e | |||
5ce55bd3b0 | |||
c81f178cdb | |||
fc795b80ae | |||
99134de6b6 | |||
1fc388d6de | |||
eba1ca030c | |||
8ce0fab8cc | |||
5ed2d6022c | |||
37d085f793 | |||
69c54de460 | |||
b9d3bd22a3 | |||
d4d57aa9ea | |||
4ce1f228e6 | |||
4b03dbebba | |||
1d5978df98 | |||
5d32587cf7 | |||
d53258c943 | |||
773f760fff | |||
c20b16a0fe | |||
b151cb26a5 | |||
49622cc2a5 | |||
56328f66a7 | |||
f41a731493 | |||
ec332e3e60 | |||
a1090623a2 | |||
8572e9e560 | |||
bc836aaec1 | |||
145a4fad0f | |||
08c48d8145 | |||
81ecb56095 | |||
a6d7365a28 | |||
1f4f8ab3f0 | |||
1420cd1fa5 | |||
30a83544a0 | |||
7e20385bdb | |||
c7e803372c | |||
cf3638ad8d | |||
0dd8fd2651 | |||
c0c684b12e | |||
924334a776 | |||
be7c27f60d | |||
2b37b4a659 | |||
a4c50d3204 | |||
eb9f60f41c | |||
071aa44d29 | |||
25089f5e70 | |||
22dd8faf1d | |||
7354a55af8 | |||
611f5d684b | |||
9a099d3f5d | |||
5eb1ee3416 | |||
e4b6a18404 | |||
364d278714 | |||
c464d39401 | |||
a185b78486 | |||
c19cf22ac5 | |||
d2fb32c28a | |||
49fbbea7bf | |||
1648fff916 | |||
8d645b714f | |||
403e996d2f | |||
73e09392b6 | |||
209e28dfe5 | |||
ac5a91b67e | |||
24c5d7557e | |||
3d89bf5693 | |||
e48ec9fb71 | |||
95606b6e04 | |||
c243daabe1 | |||
357674cb54 | |||
9d5eeb328e | |||
b2ee6b2ca5 | |||
2860e9e8ee | |||
e82073834f | |||
7fcc538a75 | |||
7f6b8ad7c2 | |||
313b224bec | |||
d12b1d3e07 | |||
eeeef8df51 | |||
9c786089f8 | |||
e3cae7364f | |||
d542bbc736 | |||
e88541b269 | |||
fdad965db8 | |||
dd844f7ad3 | |||
596c8a7b4f | |||
9c598d1345 | |||
a2af838b1d | |||
bf97eab98f | |||
a9a55e9558 | |||
95fb1d1602 | |||
fa644edef3 | |||
ddc9dca8b4 | |||
86eee429bb | |||
4f20a504e3 | |||
6a1f8640f6 | |||
8a0414f306 | |||
d478661961 | |||
b8064aa45c | |||
00f596c4f8 | |||
3f7b14bf59 | |||
ba0a256834 | |||
f2f8c235e7 | |||
69b3bb183d | |||
cd35bd6872 | |||
d09a43cfef | |||
40b995a435 | |||
590826b9bd | |||
a5e87484d9 | |||
8a86e0825b | |||
b39bbffdc5 | |||
bd3d2451bc | |||
606407933e | |||
ad09e8c8d0 | |||
486edf0e55 | |||
2ee01eb195 | |||
9098502199 | |||
b130374e46 | |||
31106bc227 | |||
cc1a3d695f | |||
8020780fc5 | |||
2f266a5922 | |||
3827892e48 | |||
e06b78b0ee | |||
74cff89df3 | |||
a9957c3db3 | |||
2e9bf7e93b | |||
dbcc69c2de | |||
cdd3fe81e1 | |||
a8a3eb3866 | |||
83a3c6f614 | |||
8cc6a32a04 | |||
c1a2144f60 | |||
b2491a5874 | |||
2e125168c3 | |||
5059a92b91 | |||
ea5db98d12 | |||
1f77c074e9 | |||
73a5788774 | |||
dc3bf8546e | |||
c7f8796136 | |||
c5336776a5 | |||
b623c4aba1 | |||
49a39fc7bd | |||
2e4519cb36 | |||
2ff3b12376 | |||
9e4bccd8c0 | |||
1c5180b720 | |||
fa6d44ea9e | |||
9d018e8d9e | |||
ae2e1fdd5a | |||
97bfcf6e71 | |||
5457c7a202 | |||
ee28296d60 | |||
06af742bef | |||
6bdf5e15c0 | |||
d4eba3f4b1 | |||
5a89e80873 | |||
28e601bbb9 | |||
7e9f1324a7 | |||
973d5dc251 | |||
533d139385 | |||
6a94c8183c | |||
629a254639 | |||
732b931556 | |||
2dd1878d57 | |||
3104a312b2 | |||
d6d47feda9 | |||
0ba1b58ee0 | |||
ab2df8b11b | |||
eb01dcaf60 | |||
f0535df96d | |||
f903dbfe00 | |||
e0d5c79848 | |||
e024f381c9 | |||
2a09aaf456 | |||
0ad8ea6e92 | |||
bd47852ca4 | |||
2b036b1a5c | |||
e5ec8fa603 | |||
abe5d94d5b | |||
da5febc34a | |||
3de5e132a2 | |||
37e8c8d324 | |||
aa11dbb928 | |||
e7adaef2d2 | |||
6bf9ae0a18 | |||
e7b2dc87d6 | |||
d7a02793fa | |||
6a996611f8 | |||
ad8d67137e | |||
cbbed6a6c1 | |||
99ef3e6576 | |||
eeaf75ac85 | |||
6954bfac4b | |||
f27b62027c | |||
093cb5b39e | |||
3f41628bf3 | |||
a3fa8adf4a | |||
08daf655e5 | |||
61fc090cf2 | |||
ecd830463c | |||
ffe89f5e1b | |||
88a05845c2 | |||
2cabdca3f7 | |||
be1ddb9f5b | |||
7fc3eeab00 | |||
9395dbf9fa | |||
a7396d7ae9 | |||
3b632c2870 | |||
7dd834bca0 | |||
2b6e135c83 | |||
c26e3aa9fa | |||
aeba15c5c6 | |||
4c583ec8ab | |||
af2435f199 | |||
456987e212 | |||
8e6ec04abc | |||
42a7b7fa36 | |||
ce4e0bf69c | |||
dc84484c2b | |||
e7e4645c0b | |||
4e9e285e37 | |||
3962d32ffe | |||
a84aba5517 | |||
0b82d5c8d4 | |||
3aef4c5a09 | |||
6307952ae9 | |||
cacd0f5d8f | |||
f66928c345 | |||
9abfd54cc1 | |||
4a85311c5f | |||
8a4f6eb6c2 | |||
6e7a693355 | |||
b7bd8dc7f1 | |||
b445825467 | |||
98d6aea7fe | |||
b75d121c7e | |||
88bbb03f12 | |||
9478bc281f | |||
7ec886faa2 | |||
610e62e2cd | |||
906442136b | |||
3600542d78 | |||
3b36d46a8f | |||
63fa6a36a9 | |||
e0ed877494 | |||
bab2daf711 | |||
5858025d90 | |||
dbac2abafb | |||
266d1cb935 | |||
ffbb44673f | |||
a84a8ecc14 | |||
687886e70b | |||
bad323f5cc | |||
ca9f700fb0 | |||
c51cc6b2fe | |||
03c66f0f86 | |||
610b041631 | |||
75289b1498 | |||
4eea54780a | |||
e860d32b3a | |||
c4486d9ad7 | |||
8222b16d9a | |||
dcb53b1cbb | |||
a52a2f6d26 | |||
906d7eb176 | |||
bf3f5532ac | |||
07bf1c9e22 | |||
b659a3d39f | |||
68b30108be | |||
f223fb2876 | |||
8bb785b7af | |||
806a2005d7 | |||
c794ced0ad | |||
f993358c5f | |||
1c12be6bf2 | |||
a1d9b8486e | |||
9397356ce4 | |||
e56e363dcc | |||
18b287c3ea | |||
9014eb72e9 | |||
82948726ed | |||
c601816586 | |||
54f7a88fbb | |||
d2d1df0447 | |||
f9b1afe4cf | |||
033cb8bd63 | |||
0ed9fcb641 | |||
efac23d4af | |||
48dc1c38f7 | |||
ffb3e2b47a | |||
ef816c0a52 | |||
3e35bc38e2 | |||
de0741f727 | |||
6fd4b9f1e2 | |||
6c8a1a5b80 | |||
3842ee15cf | |||
6c71b443e8 | |||
4a4900e5e7 | |||
26d4169fea | |||
7d88a8b315 | |||
41592a04b7 | |||
1d4bafb6ff | |||
28996f561f | |||
0658c0851b | |||
0df2064802 | |||
6543d96910 | |||
0bf5ab76fb | |||
8e1394bf53 | |||
6ddbdc9dc1 | |||
2a8be527d7 | |||
aca1422fca | |||
b0d0932ed9 | |||
fd5557861b | |||
1de7c5b114 | |||
2fb580db26 | |||
e5ca22a9a6 | |||
69ddaacc28 | |||
897a31e608 | |||
4943ff9dfc | |||
e36b38939c | |||
ecb3f9aeac | |||
f0696f77ef | |||
6813838754 | |||
65fe19ca71 | |||
a4f5cab12d | |||
29e06e30b2 | |||
3939e2d9dd | |||
2579438b84 | |||
95d42b9907 | |||
2eb6e075ae | |||
8f928915d9 | |||
3af8cf48b2 | |||
21c03670b6 | |||
0c868b16b6 | |||
1e67360048 | |||
3520dafd29 | |||
857b63ba8f | |||
9551e5b8e5 | |||
c7f15a556d | |||
efca9f0450 | |||
d728154e87 | |||
2e1a167bed | |||
6f6e3aaa21 | |||
9c65a2b890 | |||
beb5bf6dda | |||
7a5e5773b7 | |||
f1b0a4f1de | |||
751345c736 | |||
e850f34d76 | |||
8d7c65585c | |||
96f6362117 | |||
66c768d453 | |||
6fe7763db9 | |||
fda97decaa | |||
b3f44562e9 | |||
51350be190 | |||
7f4b5d282e | |||
94feecd44b | |||
45b02d92d4 | |||
fe4b5498e6 | |||
98b36fd73e | |||
07c7048433 | |||
f09cf92197 | |||
98eba11da5 | |||
a6c1e02847 | |||
b04cee12ea | |||
c4966404bb | |||
579c508761 | |||
43959bccb1 | |||
e6bd12dc2f | |||
7daca754b1 | |||
cb90e30bcf | |||
71d11c73f0 | |||
24116ba846 | |||
a0683dbb0f | |||
b6811b643c | |||
4d2549b50a | |||
1fb3274f37 | |||
6772a69c55 | |||
266a253c03 | |||
c62e1abf2f | |||
55f405f5c2 | |||
8fbd0e58f0 | |||
418d099a2e | |||
9d2eb5e911 | |||
b6c1124d50 | |||
03fda936a8 | |||
684fd46d09 | |||
90fc649441 | |||
0410df77aa | |||
0f30467f62 | |||
a84910f04c | |||
3ee225caec | |||
f963dbd10d | |||
debfbf0d93 | |||
5c37d298a6 | |||
3ca162f23f | |||
5f48433c95 | |||
33352638a9 | |||
db52501462 | |||
3a0cbd1cd4 | |||
1bdb68b7da | |||
6ce728169e | |||
06a3c7c478 | |||
70982c145b | |||
417f2d8998 | |||
7339c4ac2f | |||
43a0ede9d2 | |||
c747c7d025 | |||
c9e2e8980f | |||
9a956692de | |||
d30a6b60b7 | |||
41873bb115 | |||
8064152777 | |||
872df446bd | |||
376a615634 | |||
c16c9efdf3 | |||
c3cc6f9880 | |||
1e139743b8 | |||
bde0ba1100 | |||
50f273c041 | |||
db095f9705 | |||
f580f27ec7 | |||
a46029c0f6 | |||
1a615591e2 | |||
d19683b7dd | |||
f17b3b2a3b | |||
a0a2ea01bc | |||
5132ab6cd9 | |||
256bdf2581 | |||
8a3f8b4706 | |||
7264ce43ae | |||
66e475cbb8 | |||
1e896efff9 | |||
4db7a7e57f | |||
54b23968e7 | |||
bcb080e2b9 | |||
e5c58f9b04 | |||
af7aef70db | |||
3ea72a0bf9 | |||
be02fbb352 | |||
a67f7e3930 | |||
965c19375f | |||
63edcb8934 | |||
e7a012d69a | |||
99c55ac889 | |||
f14adf5827 | |||
c64b9ad63a | |||
dda71b06ae | |||
3c4dca7fdb | |||
ddbc5cf960 | |||
1edf69892a | |||
f10c2a2df2 | |||
3bbdc5ab5b | |||
082e3404c3 | |||
547833ae23 | |||
6e1df36188 | |||
329fe7d844 | |||
b7aaf54a6f | |||
6332814a04 | |||
9d4818d360 | |||
36f3accf4b | |||
8d08840ea4 | |||
7f0d0c9d63 | |||
bf55f03a3e | |||
a5c3fbdd7a | |||
a8bf2191b9 | |||
0688a86f57 | |||
2e11e448dd | |||
8bf275cb8b | |||
1896576a24 | |||
8f811c29d7 | |||
3a4f79629c | |||
375243860e | |||
a842a5319f | |||
c2b0f6af22 | |||
6490d99ac2 | |||
e0b063ac85 | |||
12ac2f4ac7 | |||
cc1951c7ba | |||
0e538ee51d | |||
1b4b832c8c | |||
4f8e4f0522 | |||
0ee78d2416 | |||
4c46087ffc | |||
bb3e72ea4b | |||
914e4c9a72 | |||
9fd7312629 | |||
24387d1efe | |||
3853938ef3 | |||
4ec8416f9a | |||
8aff793a4f | |||
d93ded9047 | |||
fbd04b0fe7 | |||
953f45c50f | |||
1822abc862 | |||
92e966686e | |||
3f50f88e2c | |||
532600ab67 | |||
78f8fe602c | |||
e75fbd7fb4 | |||
06f605879a | |||
4c7038f941 | |||
4bd4d42b82 | |||
f5ebfc3418 | |||
4ae278686c | |||
740786c99e | |||
6abf880e44 | |||
853411fa4f | |||
6e30d23254 | |||
717b36a983 | |||
90eed14cd6 | |||
4452e6ac93 | |||
56f1a6ba37 | |||
8c47a338df | |||
7c6535283e | |||
c669819bbb | |||
50f3231629 | |||
015cde2169 | |||
b9b50dd5dc | |||
da3640357c | |||
0004e7429f | |||
e2e6b7516a | |||
b903161a5d | |||
99fe63b2a3 | |||
dbc180315e | |||
45983acc0d | |||
a02af1053f | |||
7de88b9040 | |||
58327d0514 | |||
db31d13f96 | |||
55d0684565 | |||
7e3cd24444 | |||
2088a43c56 |
@ -4,3 +4,7 @@ root = yes
|
||||
[*]
|
||||
indent_size = 4
|
||||
indent_style = tab
|
||||
|
||||
[*.yml]
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
|
6
.github/ISSUE_TEMPLATE.md
vendored
6
.github/ISSUE_TEMPLATE.md
vendored
@ -1,6 +1,6 @@
|
||||
### Issue description
|
||||
<!---
|
||||
THIS ISSUE TRACKER IS FOR BUG REPORTING, NOT FOR HELP & SUPPORT. If you need help, use the links below.
|
||||
THIS ISSUE TRACKER IS FOR BUG REPORTING, NOT FOR HELP & SUPPORT. If you need help, use the links below.
|
||||
- http://pmmp.readthedocs.io/en/rtfd/ - Documentation
|
||||
- https://forums.pmmp.io - PMMP Forums
|
||||
|
||||
@ -28,7 +28,7 @@ NO support whatsoever will be provided for third-party modified variants of Pock
|
||||
|
||||
Note that 32-bit platforms are no longer supported by PocketMine-MP and issues concerning 32-bit platforms will be closed.
|
||||
-->
|
||||
* PocketMine-MP:
|
||||
* PocketMine-MP: <!-- LATEST IS NOT A VALID VERSION -->
|
||||
* PHP:
|
||||
* Server OS:
|
||||
* Game version: PE/Win10 (delete as appropriate)
|
||||
@ -43,6 +43,6 @@ If the issue is **not** reproducible without plugins:
|
||||
|
||||
### Crashdump, backtrace or other files
|
||||
- Do not paste crashdumps into an issue - please use our Crash Archive at https://crash.pmmp.io for submitting crash reports to not spam the issue tracker. Add links to your reports in the Crash Archive here.
|
||||
- Please use gist or anything else to add other files and add links here
|
||||
- Please use gist or anything else to add other files and add links here
|
||||
|
||||
* ...
|
||||
|
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -33,4 +33,8 @@ Requires translations:
|
||||
-->
|
||||
|
||||
## Tests
|
||||
<!-- Attach scripts or actions to test this pull request, as well as the result -->
|
||||
<!--
|
||||
Details should be provided of tests done. Simply saying "tested" or equivalent is not acceptable.
|
||||
|
||||
Attach scripts or actions to test this pull request, as well as the result
|
||||
-->
|
||||
|
12
.github/support.yml
vendored
Normal file
12
.github/support.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Configuration for support-requests - https://github.com/dessant/support-requests
|
||||
|
||||
# Label used to mark issues as support requests
|
||||
supportLabel: "Support request"
|
||||
# Comment to post on issues marked as support requests. Add a link
|
||||
# to a support page, or set to `false` to disable
|
||||
supportComment: >
|
||||
This issue tracker is not a support forum. Please use the [forums](https://forums.pmmp.io) for support.
|
||||
# Whether to close issues marked as support requests
|
||||
close: true
|
||||
# Whether to lock issues marked as support requests
|
||||
lock: false
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,14 +1,16 @@
|
||||
players/*
|
||||
worlds/*
|
||||
plugin_data/*
|
||||
plugins/*
|
||||
bin/*
|
||||
bin*/*
|
||||
timings/*
|
||||
crashdumps/*
|
||||
*.log
|
||||
*.txt
|
||||
*.phar
|
||||
server.properties
|
||||
/pocketmine.yml
|
||||
memoryDump_*/*
|
||||
memory_dumps/*
|
||||
resource_packs/
|
||||
|
||||
# Common IDEs
|
||||
|
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -7,6 +7,6 @@
|
||||
[submodule "tests/plugins/PocketMine-DevTools"]
|
||||
path = tests/plugins/PocketMine-DevTools
|
||||
url = https://github.com/pmmp/PocketMine-DevTools.git
|
||||
[submodule "tests/plugins/PocketMine-TesterPlugin"]
|
||||
path = tests/plugins/PocketMine-TesterPlugin
|
||||
url = https://github.com/pmmp/PocketMine-TesterPlugin.git
|
||||
[submodule "src/pocketmine/resources/vanilla"]
|
||||
path = src/pocketmine/resources/vanilla
|
||||
url = https://github.com/pmmp/BedrockData.git
|
||||
|
@ -2,13 +2,14 @@ language: php
|
||||
|
||||
php:
|
||||
- 7.2
|
||||
- 7.3
|
||||
|
||||
before_script:
|
||||
# - pecl install channel://pecl.php.net/pthreads-3.1.6
|
||||
- echo | pecl install channel://pecl.php.net/yaml-2.0.2
|
||||
- git clone https://github.com/krakjoe/pthreads.git
|
||||
- echo | pecl install channel://pecl.php.net/yaml-2.0.4
|
||||
- git clone https://github.com/pmmp/pthreads.git
|
||||
- cd pthreads
|
||||
- git checkout 6c6b15138c923b69cfa46ee05fc2dd45da587287
|
||||
- git checkout 6ca019c58b4fa09ee2ff490f2444e34bef0773d0
|
||||
- phpize
|
||||
- ./configure
|
||||
- make
|
||||
@ -18,7 +19,7 @@ before_script:
|
||||
- composer install
|
||||
|
||||
script:
|
||||
- ./tests/travis.sh
|
||||
- ./tests/travis.sh -t4
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
@ -5,58 +5,48 @@
|
||||
|
||||
## Creating an Issue
|
||||
- If you are reporting a bug:
|
||||
- **make sure that you are using the latest supported version** before opening an issue.
|
||||
- **test it on a clean test server, WITHOUT PLUGINS**, to see if the issue still occurs. If not then it may be a plugin issue. Please also indicate the result of such tests.
|
||||
|
||||
- [Search the issue tracker](https://github.com/pmmp/PocketMine-MP/issues?utf8=%E2%9C%93&q=is%3Aissue) to check if anyone has already reported it, to avoid needlessly creating duplicate issues. Make sure you also check closed issues, as an issue you think is valid may already have been resolved.
|
||||
|
||||
- If your issue is related to a plugin, **do not report here, contact the plugin's original author** instead.
|
||||
|
||||
- **make sure that you are using the latest supported version** before opening an issue.
|
||||
- **test it on a clean test server, WITHOUT PLUGINS**, to see if the issue still occurs. If not then it may be a plugin issue. Please also indicate the result of such tests.
|
||||
- **[Search the issue tracker](https://github.com/pmmp/PocketMine-MP/issues?utf8=%E2%9C%93&q=is%3Aissue)** to check if anyone has already reported it, to avoid needlessly creating duplicate issues. Make sure you also check closed issues, as an issue you think is valid may already have been resolved.
|
||||
- **Do not report plugin issues here.** If your issue is related to a plugin, contact the plugin's original author instead.
|
||||
- **Support requests are not bugs.** Issues such as "How do I do this" are not bugs and will be closed. If you need help, please see [here](README.md#discussion) and do not misuse our issue tracker.
|
||||
|
||||
- **No generic titles** such as "Question", "Help", "Crash Report" etc. A good issue report provides a quick summary in the title. If you just got a crash report but you don't understand it, please look for a line starting with `Message`. It summarizes the bug.
|
||||
|
||||
- Information must be provided in the issue body, not in the title. No tags like `[BUG]` are allowed in the title, including `[SOLVED]` for solved issues.
|
||||
|
||||
- Similarly, no generic issue reports. For bugs, it is the issue author's responsibility to provide us an issue that is **trackable, debuggable, reproducible, reported professionally and is an actual bug**.
|
||||
<br><br>Valid issue reports must include instructions how to reproduce the issue or a crashdump/backtrace (unless the cause of the issue is obvious).
|
||||
<br><br>**If you do not provide us with a summary or instructions on how to reproduce the issue, it will be treated as spam and will therefore be closed.**
|
||||
<br><br>In simple words, if the issue cannot be properly confirmed to be valid or lacks required information, the issue will be closed until further information is provided.
|
||||
|
||||
- **Provide information in the issue body, not in the title.** No tags like `[BUG]` are allowed in the title, including `[SOLVED]` for solved issues.
|
||||
- **No generic issue reports.** For bugs, it is the issue author's responsibility to provide us an issue that is **trackable, debuggable, reproducible, reported professionally and is an actual bug**.
|
||||
<br>Valid issue reports must include instructions how to reproduce the issue or a crashdump/backtrace (unless the cause of the issue is obvious).
|
||||
<br>**If you do not provide us with a summary or instructions on how to reproduce the issue, it will be treated as spam and will therefore be closed.**
|
||||
<br>In simple words, if the issue cannot be properly confirmed to be valid or lacks required information, the issue will be closed until further information is provided.
|
||||
- To express appreciation, objection, confusion or other supported reactions on pull requests, issues or comments on them, use GitHub [reactions](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments) rather than posting an individual comment with an emoji only. This helps keeping the issue/pull request conversation clean and readable.
|
||||
|
||||
- If your issue is related to the PocketMine-MP website, forums, etc., please [talk to a human directly](README.md#discussion).
|
||||
|
||||
|
||||
|
||||
## Contributing Code
|
||||
- To contribute code to the repository, [fork it on GitHub](https://github.com/pmmp/PocketMine-MP/fork), create a branch on your fork, and make your changes on your fork. You can then make a [pull request](https://github.com/pmmp/PocketMine-MP/pull/new) to the project to compare your branch to ours and propose your changes to our repository. We use the Pull Request system to allow members of the team to review changes before they are merged.
|
||||
## Contributing
|
||||
To contribute to the repository, [fork it on GitHub](https://github.com/pmmp/PocketMine-MP/fork), create a branch on your fork, and make your changes on your fork. You can then make a [pull request](https://github.com/pmmp/PocketMine-MP/pull/new) to the project to compare your branch to ours and propose your changes to our repository. We use the Pull Request system to allow members of the team to review changes before they are merged.
|
||||
|
||||
- By proposing a pull request to the project, you agree to your code being distributed within PocketMine-MP under the [LGPL license](LICENSE).
|
||||
### Licensing
|
||||
By proposing a pull request to the project, you agree to your code being distributed within PocketMine-MP under the [LGPL license](LICENSE).
|
||||
|
||||
- At PocketMine, **we enforce a very high standard for contributions**. This is because PocketMine-MP and its related projects are used very widely in production. While this might seem like we are being mean at times, **our priority is what is best for PocketMine-MP itself**. We try to ensure that our project's codebase is as clean as possible and ensure that only top-quality material makes it through to PocketMine-MP itself. **If a contribution does not live up to our standards, changes may be requested or the pull request may be closed.**
|
||||
|
||||
- **Your pull request will be checked and discussed in due time.** Since the team is scattered all around the world, your PR may not receive any attention for some time.
|
||||
|
||||
- **Avoid using GitHub Web Editor**. The web editor lacks most useful GIT features and **should only be used for very minor changes**. It is immediately clear if the web editor has been used, and if so the PR is more likely to be rejected. If you want to make serious contributions, **please learn how to use [GIT version control](https://git-scm.com/)**.
|
||||
|
||||
- **Do not copy-paste code**. There are potential license issues implicit with copy-pasting, and copy-paste usually indicates a lack of understanding of the actual code. Copy-pasted code is obvious a mile off and **any PR like this is likely to be closed**. If you want to use somebody else's code from a Git repository, **use [GIT's cherry-pick feature](https://git-scm.com/docs/git-cherry-pick)** to cherry-pick the commit. **Cherry-picking is the politer way to copy somebody's changes** and retains all the original accreditation, so there is no need for copy-pasted commits with descriptions like `Some code, thanks @exampleperson`.
|
||||
|
||||
- In addition to the above, **make sure you can explain your changes**. If you can't provide a good explanation of changes, your PR may be rejected.
|
||||
### Contribution standards
|
||||
- **We enforce a very high standard for contributions**. This is because PocketMine-MP and its related projects are used very widely in production. While this might seem like we are being mean at times, **our priority is what is best for PocketMine-MP itself**.
|
||||
We try to ensure that our project's codebase is as clean as possible and ensure that only top-quality material makes it through to PocketMine-MP itself.
|
||||
- **If a contribution does not meet our standards, changes may be requested or the pull request may be closed.**
|
||||
|
||||
### Pull requests
|
||||
- **Create a new branch for each pull request.** Do not create a pull request with commits that exist in another pull request.
|
||||
|
||||
- **Code should use the same style as in PocketMine-MP.** See [below](#code-syntax) for an example.
|
||||
|
||||
- **The code must be clear** and written in English, comments included.
|
||||
|
||||
- **Use descriptive commit titles.** You can see an example [here](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
|
||||
|
||||
- **Try to stick to one change per commit.** This ensures that if you create a PR with several changes, we can decide which ones we wish to include and which ones not to include.
|
||||
|
||||
- **It is inadvisable to create pull requests with large commits** unless this has been discussed with the team beforehand. Large pull requests are difficult to review, and such pull requests may end up being closed. The only exception is when all features in the pull request are related to each other, and share the same core changes.
|
||||
|
||||
- **Do not include multiple unrelated changes in one commit.** An atomic style for commits is preferred - this means that changes included in a commit should be part of a single distinct change set. See [this link](https://www.freshconsulting.com/atomic-commits/) for more information on atomic commits. See the [documentation on `git add`](https://git-scm.com/docs/git-add) for information on how to isolate local changes for committing.
|
||||
- **Your pull request will be checked and discussed in due time.** Since the team is scattered all around the world, your PR may not receive any attention for some time.
|
||||
- **It is inadvisable to create large pull requests with lots of changes** unless this has been discussed with the team beforehand. Large pull requests are difficult to review, and such pull requests may end up being closed. The only exception is when all features in the pull request are related to each other, and share the same core changes.
|
||||
- **You may be asked to rebase your pull request** if the branch becomes outdated and/or if possibly conflicting changes are made to the target branch. To see how to do this, read [this page](https://github.com/edx/edx-platform/wiki/How-to-Rebase-a-Pull-Request).
|
||||
- **Details should be provided of tests done.** Simply saying "Tested" or equivalent is not acceptable.
|
||||
|
||||
### Code contributions
|
||||
- **Avoid committing changes directly on GitHub. This includes use of the web editor, and also uploading files.** The web editor lacks most useful GIT features and **should only be used for very minor changes**. It is immediately clear if the web editor has been used, and if so the PR is more likely to be rejected. If you want to make serious contributions, **please learn how to use [GIT version control](https://git-scm.com/)**.
|
||||
- **Do not copy-paste code**. There are potential license issues implicit with copy-pasting, and copy-paste usually indicates a lack of understanding of the actual code. Copy-pasted code is obvious a mile off and **any PR like this is likely to be closed**. If you want to use somebody else's code from a Git repository, **use [GIT's cherry-pick feature](https://git-scm.com/docs/git-cherry-pick)** to cherry-pick the commit. **Cherry-picking is the politer way to copy somebody's changes** and retains all the original accreditation, so there is no need for copy-pasted commits with descriptions like `Some code, thanks @exampleperson`.
|
||||
- **Make sure you can explain your changes**. If you can't provide a good explanation of changes, your PR may be rejected.
|
||||
- **Code should use the same style as in PocketMine-MP.** See [below](#code-syntax) for an example.
|
||||
- **The code must be clear** and written in English, comments included.
|
||||
|
||||
|
||||
**Thanks for contributing to PocketMine-MP!**
|
||||
@ -78,17 +68,18 @@ It is mainly [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accept
|
||||
- Strings SHOULD use the double quote `"` except when the single quote is required.
|
||||
- All code SHOULD have parameter and type declarations where possible.
|
||||
- Strict types SHOULD be enabled on new files where it is sensible to do so.
|
||||
- All constant declarations SHOULD be preceded by a visibility modifier.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\example;
|
||||
|
||||
class ExampleClass{
|
||||
|
||||
const EXAMPLE_CLASS_CONSTANT = 1;
|
||||
public const EXAMPLE_CLASS_CONSTANT = 1;
|
||||
|
||||
public $examplePublicVariable = "defaultValue";
|
||||
private $examplePrivateVariable;
|
||||
@ -99,7 +90,7 @@ class ExampleClass{
|
||||
* @param string $firstArgument the first argument
|
||||
* @param string|null $secondArgument default null
|
||||
*/
|
||||
public function __construct(string $firstArgument, &$secondArgument = null){
|
||||
public function __construct(string $firstArgument, ?string &$secondArgument = null){
|
||||
if($firstArgument === "exampleValue"){ //Remember to use === instead of == when possible
|
||||
//do things
|
||||
}elseif($firstArgument === "otherValue"){
|
||||
@ -119,7 +110,6 @@ class ExampleClass{
|
||||
public function doStuff(string $stuff) : string{
|
||||
return $stuff;
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -133,4 +123,4 @@ class ExampleClass{
|
||||
* After voting has been closed, no further votes will be counted.
|
||||
* An RFC will be rejected if less than 50% + 1 (simple majority) has voted Yes.
|
||||
* If the RFC is approved, Team Members have the final word on its implementation or rejection.
|
||||
* RFCs with complex voting options will specify the vote percentage or other details.
|
||||
* RFCs with complex voting options will specify the vote percentage or other details.
|
||||
|
18
README.md
18
README.md
@ -1,6 +1,6 @@
|
||||
# [](https://pmmp.io)
|
||||
|
||||
__A highly customisable, open source server software for Minecraft: Pocket Edition written in PHP__
|
||||
__A highly customisable, open source server software for Minecraft: Bedrock Edition written in PHP__
|
||||
|
||||
[](https://travis-ci.org/pmmp/PocketMine-MP)
|
||||
|
||||
@ -10,7 +10,6 @@ If you don't find what you're looking for there, [talk to a human](#discussion).
|
||||
|
||||
### Discussion
|
||||
- [Forums](https://forums.pmmp.io/)
|
||||
- [#pmmp + #pocketmine channel IRC](http://webchat.freenode.net/?channels=pmmp,pocketmine)
|
||||
|
||||
### Plugins
|
||||
There are a very wide range of already-written plugins available which you can use to customise your server. Check out [Poggit](https://poggit.pmmp.io), or just search GitHub.
|
||||
@ -23,19 +22,10 @@ There are a very wide range of already-written plugins available which you can u
|
||||
Yes you can! Contributions are welcomed provided that they comply with our [Contributing Guidelines](CONTRIBUTING.md). Please ensure you read the relevant sections of the guidelines carefully before making a Pull Request or opening an Issue.
|
||||
|
||||
### Where can I get the latest .phar?
|
||||
Head over to our [official Jenkins server](https://jenkins.pmmp.io/)
|
||||
- Latest release builds can be found in our [GitHub releases](https://github.com/pmmp/PocketMine-MP/releases).
|
||||
- Latest bleeding-edge development builds (and other builds in the build job channels) can be found on our [Jenkins server](https://jenkins.pmmp.io/).
|
||||
|
||||
## Third-party Libraries/Protocols Used
|
||||
* __[PHP Sockets](http://php.net/manual/en/book.sockets.php)__
|
||||
* __[PHP mbstring](http://php.net/manual/en/book.mbstring.php)__
|
||||
* __[PHP BCMath](http://php.net/manual/en/book.bc.php)__
|
||||
* __[PHP pthreads](http://pthreads.org/)__ by _[krakjoe](https://github.com/krakjoe)_: Threading for PHP - Share Nothing, Do Everything.
|
||||
* __[PHP YAML](https://code.google.com/p/php-yaml/)__ by _Bryan Davis_: The Yaml PHP Extension provides a wrapper to the LibYAML library.
|
||||
* __[LibYAML](http://pyyaml.org/wiki/LibYAML)__ by _Kirill Simonov_: A YAML 1.1 parser and emitter written in C.
|
||||
* __[cURL](http://curl.haxx.se/)__: cURL is a command line tool for transferring data with URL syntax
|
||||
* __[Zlib](http://www.zlib.net/)__: A Massively Spiffy Yet Delicately Unobtrusive Compression Library
|
||||
* __[Source RCON Protocol](https://developer.valvesoftware.com/wiki/Source_RCON_Protocol)__
|
||||
* __[UT3 Query Protocol](http://wiki.unrealadmin.org/UT3_query_protocol)__
|
||||
**Note: Please avoid development builds unless there is no other alternative for what you need.** Development builds are subject to changes at any time without notice, and it is likely that your server or plugins might break without warning.
|
||||
|
||||
## Licensing information
|
||||
|
||||
|
@ -1,13 +1,16 @@
|
||||
{
|
||||
"name": "pmmp/pocketmine-mp",
|
||||
"name": "pocketmine/pocketmine-mp",
|
||||
"description": "A server software for Minecraft: Pocket Edition written in PHP",
|
||||
"type": "project",
|
||||
"homepage": "https://pmmp.io",
|
||||
"license": "LGPL-3.0",
|
||||
"require": {
|
||||
"php": ">=7.2.0RC3",
|
||||
"php": ">=7.2.0",
|
||||
"php-64bit": "*",
|
||||
"ext-bcmath": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-ctype": "*",
|
||||
"ext-date": "*",
|
||||
"ext-hash": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
@ -21,14 +24,25 @@
|
||||
"ext-yaml": ">=2.0.0",
|
||||
"ext-zip": "*",
|
||||
"ext-zlib": ">=1.2.11",
|
||||
"pmmp/raklib": "dev-master#29ab14d5d8640a8ee359ce315b083a129e72db4a",
|
||||
"pmmp/pocketmine-spl": "^0.1.0"
|
||||
"pocketmine/raklib": "^0.12.0",
|
||||
"pocketmine/spl": "^0.3.0",
|
||||
"pocketmine/binaryutils": "^0.1.0",
|
||||
"pocketmine/nbt": "^0.2.6",
|
||||
"pocketmine/math": "^0.2.0",
|
||||
"pocketmine/snooze": "^0.1.0",
|
||||
"daverandom/callback-validator": "dev-master",
|
||||
"adhocore/json-comment": "^0.0.7"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"psr-4": {
|
||||
"": ["src"]
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"pocketmine\\": "tests/phpunit/"
|
||||
}
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
@ -36,7 +50,23 @@
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/pmmp/PocketMine-SPL"
|
||||
"url": "https://github.com/pmmp/SPL"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/pmmp/BinaryUtils"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/pmmp/NBT"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/pmmp/Math"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/pmmp/Snooze"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
333
composer.lock
generated
333
composer.lock
generated
@ -1,23 +1,291 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "169d2724a6847e704f3bb76030bebc87",
|
||||
"content-hash": "2f5313e4ebd7b62c785cf683b27464b4",
|
||||
"packages": [
|
||||
{
|
||||
"name": "pmmp/pocketmine-spl",
|
||||
"version": "0.1.0",
|
||||
"name": "adhocore/json-comment",
|
||||
"version": "v0.0.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/PocketMine-SPL.git",
|
||||
"reference": "c56936e6aaad925bb60002b29b1c70f497af4679"
|
||||
"url": "https://github.com/adhocore/php-json-comment.git",
|
||||
"reference": "135356c7e7336ef59924f1d921c770045f937a76"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/PocketMine-SPL/zipball/c56936e6aaad925bb60002b29b1c70f497af4679",
|
||||
"reference": "c56936e6aaad925bb60002b29b1c70f497af4679",
|
||||
"url": "https://api.github.com/repos/adhocore/php-json-comment/zipball/135356c7e7336ef59924f1d921c770045f937a76",
|
||||
"reference": "135356c7e7336ef59924f1d921c770045f937a76",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8 || ^5.7 || ^6.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Ahc\\Json\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jitendra Adhikari",
|
||||
"email": "jiten.adhikary@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Lightweight JSON comment stripper library for PHP",
|
||||
"keywords": [
|
||||
"comment",
|
||||
"json",
|
||||
"strip-comment"
|
||||
],
|
||||
"time": "2018-08-01T12:27:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "daverandom/callback-validator",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/DaveRandom/CallbackValidator.git",
|
||||
"reference": "d87a08cddbc6099816ed01e50ce25cdfc43b542f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/DaveRandom/CallbackValidator/zipball/d87a08cddbc6099816ed01e50ce25cdfc43b542f",
|
||||
"reference": "d87a08cddbc6099816ed01e50ce25cdfc43b542f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-reflection": "*",
|
||||
"php": ">=7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^6.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"DaveRandom\\CallbackValidator\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Chris Wright",
|
||||
"email": "cw@daverandom.com"
|
||||
}
|
||||
],
|
||||
"description": "Tools for validating callback signatures",
|
||||
"time": "2017-04-03T15:22:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/binaryutils",
|
||||
"version": "0.1.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BinaryUtils.git",
|
||||
"reference": "33f511715d22418c03368b49b45a6c25d6b33806"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/33f511715d22418c03368b49b45a6c25d6b33806",
|
||||
"reference": "33f511715d22418c03368b49b45a6c25d6b33806",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"php-64bit": "*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"pocketmine\\utils\\": "src/"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"LGPL-3.0"
|
||||
],
|
||||
"description": "Classes and methods for conveniently handling binary data",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/BinaryUtils/tree/0.1.8",
|
||||
"issues": "https://github.com/pmmp/BinaryUtils/issues"
|
||||
},
|
||||
"time": "2019-01-16T17:31:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/math",
|
||||
"version": "0.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/Math.git",
|
||||
"reference": "b755d3fb7025c4ddb7d9d6df0ba7e0b65125e51c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/Math/zipball/b755d3fb7025c4ddb7d9d6df0ba7e0b65125e51c",
|
||||
"reference": "b755d3fb7025c4ddb7d9d6df0ba7e0b65125e51c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.0",
|
||||
"php-64bit": "*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"pocketmine\\math\\": "src/"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"LGPL-3.0"
|
||||
],
|
||||
"description": "PHP library containing math related code used in PocketMine-MP",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/Math/tree/0.2.2",
|
||||
"issues": "https://github.com/pmmp/Math/issues"
|
||||
},
|
||||
"time": "2019-01-04T15:42:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/nbt",
|
||||
"version": "0.2.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/NBT.git",
|
||||
"reference": "92eaf84dd61f700d3ec02ebd01b606cb5b1590d4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/NBT/zipball/92eaf84dd61f700d3ec02ebd01b606cb5b1590d4",
|
||||
"reference": "92eaf84dd61f700d3ec02ebd01b606cb5b1590d4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-zlib": "*",
|
||||
"php": ">=7.2.0",
|
||||
"php-64bit": "*",
|
||||
"pocketmine/binaryutils": "^0.1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"pocketmine\\nbt\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"pocketmine\\nbt\\": "tests/phpunit/"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"LGPL-3.0"
|
||||
],
|
||||
"description": "PHP library for working with Named Binary Tags",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/NBT/tree/0.2.6",
|
||||
"issues": "https://github.com/pmmp/NBT/issues"
|
||||
},
|
||||
"time": "2019-02-07T16:28:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/raklib",
|
||||
"version": "0.12.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/RakLib.git",
|
||||
"reference": "54a36d55eeba0a182e00439920ee2fcfa8c72bf3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/54a36d55eeba0a182e00439920ee2fcfa8c72bf3",
|
||||
"reference": "54a36d55eeba0a182e00439920ee2fcfa8c72bf3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-bcmath": "*",
|
||||
"ext-pthreads": ">=3.1.7dev",
|
||||
"ext-sockets": "*",
|
||||
"php": ">=7.2.0",
|
||||
"php-64bit": "*",
|
||||
"php-ipv6": "*",
|
||||
"pocketmine/binaryutils": "^0.1.0",
|
||||
"pocketmine/snooze": "^0.1.0",
|
||||
"pocketmine/spl": "^0.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"raklib\\": "src/"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"GPL-3.0"
|
||||
],
|
||||
"description": "A RakNet server implementation written in PHP",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/RakLib/tree/0.12",
|
||||
"issues": "https://github.com/pmmp/RakLib/issues"
|
||||
},
|
||||
"time": "2019-01-21T14:17:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/snooze",
|
||||
"version": "0.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/Snooze.git",
|
||||
"reference": "b7bd231bdb75e69300cac89ccd515fc731c38c40"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/Snooze/zipball/b7bd231bdb75e69300cac89ccd515fc731c38c40",
|
||||
"reference": "b7bd231bdb75e69300cac89ccd515fc731c38c40",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-pthreads": ">=3.1.7dev",
|
||||
"php-64bit": ">=7.2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"pocketmine\\snooze\\": "src/"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"LGPL-3.0"
|
||||
],
|
||||
"description": "Thread notification management library for code using the pthreads extension",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/Snooze/tree/0.1.1",
|
||||
"issues": "https://github.com/pmmp/Snooze/issues"
|
||||
},
|
||||
"time": "2019-01-04T15:54:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/spl",
|
||||
"version": "0.3.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/SPL.git",
|
||||
"reference": "7fd53857cd000491ba69e8db865792a024dd2c49"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/SPL/zipball/7fd53857cd000491ba69e8db865792a024dd2c49",
|
||||
"reference": "7fd53857cd000491ba69e8db865792a024dd2c49",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -34,62 +302,27 @@
|
||||
],
|
||||
"description": "Standard library files required by PocketMine-MP and related projects",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/PocketMine-SPL/tree/master"
|
||||
"source": "https://github.com/pmmp/SPL/tree/0.3.2"
|
||||
},
|
||||
"time": "2017-12-10T12:18:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pmmp/raklib",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/RakLib.git",
|
||||
"reference": "29ab14d5d8640a8ee359ce315b083a129e72db4a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/29ab14d5d8640a8ee359ce315b083a129e72db4a",
|
||||
"reference": "29ab14d5d8640a8ee359ce315b083a129e72db4a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-bcmath": "*",
|
||||
"ext-pthreads": ">=3.1.7dev",
|
||||
"ext-sockets": "*",
|
||||
"php": ">=7.2.0RC3",
|
||||
"pmmp/pocketmine-spl": "^0.1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"./"
|
||||
]
|
||||
},
|
||||
"license": [
|
||||
"GPL-3.0"
|
||||
],
|
||||
"description": "A RakNet server implementation written in PHP",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/RakLib/tree/master",
|
||||
"issues": "https://github.com/pmmp/RakLib/issues"
|
||||
},
|
||||
"time": "2017-12-10T12:24:38+00:00"
|
||||
"time": "2018-08-12T15:17:39+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"php": 5,
|
||||
"ext-pthreads": 20,
|
||||
"pmmp/raklib": 20
|
||||
"daverandom/callback-validator": 20
|
||||
},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": ">=7.2.0RC3",
|
||||
"php": ">=7.2.0",
|
||||
"php-64bit": "*",
|
||||
"ext-bcmath": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-ctype": "*",
|
||||
"ext-date": "*",
|
||||
"ext-hash": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
|
140
doxygen.conf
140
doxygen.conf
@ -38,20 +38,20 @@ PROJECT_NAME = PocketMine-MP
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = "PM_VERSION - API PM_API"
|
||||
PROJECT_NUMBER = "PM_VERSION"
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
# quick idea about the purpose of the project. Keep the description short.
|
||||
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_BRIEF =
|
||||
|
||||
# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
|
||||
# the documentation. The maximum height of the logo should not exceed 55 pixels
|
||||
# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
|
||||
# to the output directory.
|
||||
|
||||
PROJECT_LOGO = "/home/jenkins/PocketMine-h-64.png"
|
||||
PROJECT_LOGO =
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
|
||||
# into which the generated documentation will be written. If a relative path is
|
||||
@ -151,7 +151,7 @@ FULL_PATH_NAMES = NO
|
||||
# specify the list of include paths that are normally passed to the compiler
|
||||
# using the -I flag.
|
||||
|
||||
STRIP_FROM_INC_PATH =
|
||||
STRIP_FROM_INC_PATH =
|
||||
|
||||
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
|
||||
# less readable) file names. This can be useful is your file systems doesn't
|
||||
@ -218,13 +218,13 @@ TAB_SIZE = 4
|
||||
# "Side Effects:". You can put \n's in the value part of an alias to insert
|
||||
# newlines.
|
||||
|
||||
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 =
|
||||
TCL_SUBST =
|
||||
|
||||
# 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
|
||||
@ -240,7 +240,7 @@ OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
# qualified scopes will look different, etc.
|
||||
# The default value is: NO.
|
||||
|
||||
OPTIMIZE_OUTPUT_JAVA = YES
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
|
||||
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
|
||||
# sources. Doxygen will then generate output that is tailored for Fortran.
|
||||
@ -268,7 +268,7 @@ OPTIMIZE_OUTPUT_VHDL = NO
|
||||
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
|
||||
# the files are not read by doxygen.
|
||||
|
||||
EXTENSION_MAPPING =
|
||||
EXTENSION_MAPPING =
|
||||
|
||||
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
|
||||
# according to the Markdown format, which allows for more readable
|
||||
@ -600,7 +600,7 @@ GENERATE_DEPRECATEDLIST= YES
|
||||
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
|
||||
# ... \endcond blocks.
|
||||
|
||||
ENABLED_SECTIONS =
|
||||
ENABLED_SECTIONS =
|
||||
|
||||
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
|
||||
# initial value of a variable or macro / define can have for it to appear in the
|
||||
@ -642,7 +642,7 @@ SHOW_NAMESPACES = YES
|
||||
# by doxygen. Whatever the program writes to standard output is used as the file
|
||||
# version. For an example see the documentation.
|
||||
|
||||
FILE_VERSION_FILTER =
|
||||
FILE_VERSION_FILTER =
|
||||
|
||||
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
|
||||
# by doxygen. The layout file controls the global structure of the generated
|
||||
@ -655,7 +655,7 @@ FILE_VERSION_FILTER =
|
||||
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
|
||||
# tag is left empty.
|
||||
|
||||
LAYOUT_FILE =
|
||||
LAYOUT_FILE =
|
||||
|
||||
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
|
||||
# the reference definitions. This must be a list of .bib files. The .bib
|
||||
@ -666,7 +666,7 @@ LAYOUT_FILE =
|
||||
# search path. Do not use file names with spaces, bibtex cannot handle them. See
|
||||
# also \cite for info how to create references.
|
||||
|
||||
CITE_BIB_FILES =
|
||||
CITE_BIB_FILES =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to warning and progress messages
|
||||
@ -725,7 +725,7 @@ WARN_FORMAT = "$file:$line: $text"
|
||||
# messages should be written. If left blank the output is written to standard
|
||||
# error (stderr).
|
||||
|
||||
WARN_LOGFILE =
|
||||
WARN_LOGFILE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the input files
|
||||
@ -737,7 +737,9 @@ WARN_LOGFILE =
|
||||
# spaces.
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = ./
|
||||
INPUT = ./src \
|
||||
./vendor/pocketmine \
|
||||
./README.md
|
||||
|
||||
# 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
|
||||
@ -757,9 +759,7 @@ INPUT_ENCODING = UTF-8
|
||||
# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
|
||||
# *.qsf, *.as and *.js.
|
||||
|
||||
FILE_PATTERNS = *.php \
|
||||
*.sh \
|
||||
*.md
|
||||
FILE_PATTERNS = *.php
|
||||
|
||||
# The RECURSIVE tag can be used to specify whether or not subdirectories should
|
||||
# be searched for input files as well.
|
||||
@ -774,7 +774,7 @@ RECURSIVE = YES
|
||||
# Note that relative paths are relative to the directory from which doxygen is
|
||||
# run.
|
||||
|
||||
EXCLUDE =
|
||||
EXCLUDE =
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||
@ -793,7 +793,10 @@ EXCLUDE_SYMLINKS = YES
|
||||
EXCLUDE_PATTERNS = */bin/* \
|
||||
*/players/* \
|
||||
*/worlds/* \
|
||||
*/plugins/*
|
||||
*/plugins/* \
|
||||
*/plugin_data/* \
|
||||
*/tests/* \
|
||||
*/stubs/*
|
||||
|
||||
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
|
||||
# (namespaces, classes, functions, etc.) that should be excluded from the
|
||||
@ -804,13 +807,13 @@ EXCLUDE_PATTERNS = */bin/* \
|
||||
# Note that the wildcards are matched against the file with absolute path, so to
|
||||
# exclude all test directories use the pattern */test/*
|
||||
|
||||
EXCLUDE_SYMBOLS =
|
||||
EXCLUDE_SYMBOLS =
|
||||
|
||||
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
|
||||
# that contain example code fragments that are included (see the \include
|
||||
# command).
|
||||
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATH =
|
||||
|
||||
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
|
||||
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
|
||||
@ -830,7 +833,7 @@ EXAMPLE_RECURSIVE = NO
|
||||
# that contain images that are to be included in the documentation (see the
|
||||
# \image command).
|
||||
|
||||
IMAGE_PATH =
|
||||
IMAGE_PATH =
|
||||
|
||||
# The INPUT_FILTER tag can be used to specify a program that doxygen should
|
||||
# invoke to filter for each input file. Doxygen will invoke the filter program
|
||||
@ -847,7 +850,7 @@ IMAGE_PATH =
|
||||
# code is scanned, but not when the output code is generated. If lines are added
|
||||
# or removed, the anchors will not be placed correctly.
|
||||
|
||||
INPUT_FILTER =
|
||||
INPUT_FILTER =
|
||||
|
||||
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
|
||||
# basis. Doxygen will compare the file name with each pattern and apply the
|
||||
@ -856,7 +859,7 @@ INPUT_FILTER =
|
||||
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
|
||||
# patterns match the file name, INPUT_FILTER is applied.
|
||||
|
||||
FILTER_PATTERNS =
|
||||
FILTER_PATTERNS =
|
||||
|
||||
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
|
||||
# INPUT_FILTER ) will also be used to filter the input files that are used for
|
||||
@ -871,14 +874,14 @@ FILTER_SOURCE_FILES = NO
|
||||
# *.ext= (so without naming a filter).
|
||||
# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
|
||||
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
|
||||
# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
|
||||
# is part of the input, its contents will be placed on the main page
|
||||
# (index.html). This can be useful if you have a project on for instance GitHub
|
||||
# and want to reuse the introduction page also for the doxygen output.
|
||||
|
||||
USE_MDFILE_AS_MAINPAGE = README.md
|
||||
USE_MDFILE_AS_MAINPAGE = ./README.md
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to source browsing
|
||||
@ -983,7 +986,7 @@ CLANG_ASSISTED_PARSING = NO
|
||||
# specified with INPUT and INCLUDE_PATH.
|
||||
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
|
||||
|
||||
CLANG_OPTIONS =
|
||||
CLANG_OPTIONS =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
@ -1009,7 +1012,7 @@ COLS_IN_ALPHA_INDEX = 5
|
||||
# while generating the index headers.
|
||||
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
|
||||
|
||||
IGNORE_PREFIX =
|
||||
IGNORE_PREFIX =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the HTML output
|
||||
@ -1053,7 +1056,7 @@ HTML_FILE_EXTENSION = .html
|
||||
# of the possible markers and block names see the documentation.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_HEADER =
|
||||
HTML_HEADER =
|
||||
|
||||
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
|
||||
# generated HTML page. If the tag is left blank doxygen will generate a standard
|
||||
@ -1063,7 +1066,7 @@ HTML_HEADER =
|
||||
# that doxygen normally uses.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_FOOTER =
|
||||
HTML_FOOTER =
|
||||
|
||||
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
|
||||
# sheet that is used by each HTML page. It can be used to fine-tune the look of
|
||||
@ -1075,7 +1078,7 @@ HTML_FOOTER =
|
||||
# obsolete.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_STYLESHEET =
|
||||
HTML_STYLESHEET =
|
||||
|
||||
# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
|
||||
# defined cascading style sheet that is included after the standard style sheets
|
||||
@ -1086,7 +1089,7 @@ HTML_STYLESHEET =
|
||||
# see the documentation.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
|
||||
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
|
||||
# other source files which should be copied to the HTML output directory. Note
|
||||
@ -1096,7 +1099,7 @@ HTML_EXTRA_STYLESHEET =
|
||||
# files will be copied as-is; there are no commands or markers available.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_EXTRA_FILES =
|
||||
HTML_EXTRA_FILES =
|
||||
|
||||
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
|
||||
# will adjust the colors in the stylesheet and background images according to
|
||||
@ -1224,7 +1227,7 @@ GENERATE_HTMLHELP = NO
|
||||
# written to the html output directory.
|
||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||
|
||||
CHM_FILE =
|
||||
CHM_FILE =
|
||||
|
||||
# The HHC_LOCATION tag can be used to specify the location (absolute path
|
||||
# including file name) of the HTML help compiler ( hhc.exe). If non-empty
|
||||
@ -1232,7 +1235,7 @@ CHM_FILE =
|
||||
# The file has to be specified with full path.
|
||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||
|
||||
HHC_LOCATION =
|
||||
HHC_LOCATION =
|
||||
|
||||
# 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).
|
||||
@ -1245,7 +1248,7 @@ GENERATE_CHI = NO
|
||||
# and project file content.
|
||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||
|
||||
CHM_INDEX_ENCODING =
|
||||
CHM_INDEX_ENCODING =
|
||||
|
||||
# The BINARY_TOC flag controls whether a binary table of contents is generated (
|
||||
# YES) or a normal table of contents ( NO) in the .chm file.
|
||||
@ -1275,7 +1278,7 @@ GENERATE_QHP = NO
|
||||
# the HTML output folder.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QCH_FILE =
|
||||
QCH_FILE =
|
||||
|
||||
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
|
||||
# Project output. For more information please see Qt Help Project / Namespace
|
||||
@ -1300,7 +1303,7 @@ QHP_VIRTUAL_FOLDER = doc
|
||||
# filters).
|
||||
# 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
|
||||
# custom filter to add. For more information please see Qt Help Project / Custom
|
||||
@ -1308,21 +1311,21 @@ QHP_CUST_FILTER_NAME =
|
||||
# filters).
|
||||
# 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
|
||||
# project's filter section matches. Qt Help Project / Filter Attributes (see:
|
||||
# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
|
||||
# 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
|
||||
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
|
||||
# generated .qhp file.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHG_LOCATION =
|
||||
QHG_LOCATION =
|
||||
|
||||
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
|
||||
# generated, together with the HTML files, they form an Eclipse help plugin. To
|
||||
@ -1455,7 +1458,7 @@ MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
|
||||
# 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
|
||||
# of code that will be used on startup of the MathJax code. See the MathJax site
|
||||
@ -1463,7 +1466,7 @@ MATHJAX_EXTENSIONS =
|
||||
# example see the documentation.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
MATHJAX_CODEFILE =
|
||||
MATHJAX_CODEFILE =
|
||||
|
||||
# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
|
||||
# the HTML output. The underlying search engine uses javascript and DHTML and
|
||||
@ -1523,7 +1526,7 @@ EXTERNAL_SEARCH = NO
|
||||
# Searching" for details.
|
||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||
|
||||
SEARCHENGINE_URL =
|
||||
SEARCHENGINE_URL =
|
||||
|
||||
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
|
||||
# search data is written to a file for indexing by an external tool. With the
|
||||
@ -1539,7 +1542,7 @@ SEARCHDATA_FILE = searchdata.xml
|
||||
# projects and redirect the results back to the right project.
|
||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||
|
||||
EXTERNAL_SEARCH_ID =
|
||||
EXTERNAL_SEARCH_ID =
|
||||
|
||||
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
|
||||
# projects other than the one defined by this configuration file, but that are
|
||||
@ -1549,7 +1552,7 @@ EXTERNAL_SEARCH_ID =
|
||||
# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
|
||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||
|
||||
EXTRA_SEARCH_MAPPINGS =
|
||||
EXTRA_SEARCH_MAPPINGS =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the LaTeX output
|
||||
@ -1610,7 +1613,7 @@ PAPER_TYPE = a4
|
||||
# If left blank no extra packages will be included.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
EXTRA_PACKAGES =
|
||||
EXTRA_PACKAGES =
|
||||
|
||||
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
|
||||
# generated LaTeX document. The header should contain everything until the first
|
||||
@ -1626,7 +1629,7 @@ EXTRA_PACKAGES =
|
||||
# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
|
||||
# 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
|
||||
# generated LaTeX document. The footer should contain everything after the last
|
||||
@ -1635,7 +1638,7 @@ LATEX_HEADER =
|
||||
# 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.
|
||||
|
||||
LATEX_FOOTER =
|
||||
LATEX_FOOTER =
|
||||
|
||||
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
|
||||
# other source files which should be copied to the LATEX_OUTPUT output
|
||||
@ -1643,7 +1646,7 @@ LATEX_FOOTER =
|
||||
# markers available.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_EXTRA_FILES =
|
||||
LATEX_EXTRA_FILES =
|
||||
|
||||
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
|
||||
# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
|
||||
@ -1743,14 +1746,14 @@ RTF_HYPERLINKS = NO
|
||||
# default style sheet that doxygen normally uses.
|
||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_STYLESHEET_FILE =
|
||||
|
||||
# Set optional variables used in the generation of an RTF document. Syntax is
|
||||
# similar to doxygen's config file. A template extensions file can be generated
|
||||
# using doxygen -e rtf extensionFile.
|
||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||
|
||||
RTF_EXTENSIONS_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the man page output
|
||||
@ -1811,13 +1814,13 @@ XML_OUTPUT = xml
|
||||
# validating XML parser to check the syntax of the XML files.
|
||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
||||
|
||||
XML_SCHEMA =
|
||||
XML_SCHEMA =
|
||||
|
||||
# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
|
||||
# validating XML parser to check the syntax of the XML files.
|
||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
||||
|
||||
XML_DTD =
|
||||
XML_DTD =
|
||||
|
||||
# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
|
||||
# listings (including syntax highlighting and cross-referencing information) to
|
||||
@ -1894,7 +1897,7 @@ PERLMOD_PRETTY = YES
|
||||
# overwrite each other's variables.
|
||||
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
|
||||
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
@ -1935,7 +1938,7 @@ SEARCH_INCLUDES = YES
|
||||
# preprocessor.
|
||||
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
|
||||
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_PATH =
|
||||
|
||||
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
|
||||
# patterns (like *.h and *.hpp) to filter out the header-files in the
|
||||
@ -1943,7 +1946,7 @@ INCLUDE_PATH =
|
||||
# used.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
|
||||
# The PREDEFINED tag can be used to specify one or more macro names that are
|
||||
# defined before the preprocessor is started (similar to the -D option of e.g.
|
||||
@ -1953,7 +1956,7 @@ INCLUDE_FILE_PATTERNS =
|
||||
# recursively expanded use the := operator instead of the = operator.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
PREDEFINED =
|
||||
PREDEFINED =
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||
# tag can be used to specify a list of macro names that should be expanded. The
|
||||
@ -1962,7 +1965,7 @@ PREDEFINED =
|
||||
# definition found in the source code.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
EXPAND_AS_DEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
|
||||
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
|
||||
# remove all refrences to function-like macros that are alone on a line, have an
|
||||
@ -1991,13 +1994,13 @@ SKIP_FUNCTION_MACROS = YES
|
||||
# the path). If a tag file is not located in the directory in which doxygen is
|
||||
# run, you must also specify the path to the tagfile here.
|
||||
|
||||
TAGFILES =
|
||||
TAGFILES =
|
||||
|
||||
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
|
||||
# tag file that is based on the input files it reads. See section "Linking to
|
||||
# external documentation" for more information about the usage of tag files.
|
||||
|
||||
GENERATE_TAGFILE =
|
||||
GENERATE_TAGFILE =
|
||||
|
||||
# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
|
||||
# class index. If set to NO only the inherited external classes will be listed.
|
||||
@ -2045,14 +2048,14 @@ CLASS_DIAGRAMS = NO
|
||||
# the mscgen tool resides. If left empty the tool is assumed to be found in the
|
||||
# default search path.
|
||||
|
||||
MSCGEN_PATH =
|
||||
MSCGEN_PATH =
|
||||
|
||||
# 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
|
||||
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
|
||||
# If left empty dia is assumed to be found in the default search path.
|
||||
|
||||
DIA_PATH =
|
||||
DIA_PATH =
|
||||
|
||||
# If set to YES, the inheritance and collaboration graphs will hide inheritance
|
||||
# and usage relations if the target is undocumented or is not a class.
|
||||
@ -2101,7 +2104,7 @@ DOT_FONTSIZE = 10
|
||||
# the path where dot can find it using this tag.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_FONTPATH =
|
||||
DOT_FONTPATH =
|
||||
|
||||
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
|
||||
# each documented class showing the direct and indirect inheritance relations.
|
||||
@ -2239,26 +2242,26 @@ INTERACTIVE_SVG = YES
|
||||
# found. If left blank, it is assumed the dot tool can be found in the path.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_PATH =
|
||||
DOT_PATH =
|
||||
|
||||
# The DOTFILE_DIRS tag can be used to specify one or more directories that
|
||||
# contain dot files that are included in the documentation (see the \dotfile
|
||||
# command).
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOTFILE_DIRS =
|
||||
DOTFILE_DIRS =
|
||||
|
||||
# The MSCFILE_DIRS tag can be used to specify one or more directories that
|
||||
# contain msc files that are included in the documentation (see the \mscfile
|
||||
# command).
|
||||
|
||||
MSCFILE_DIRS =
|
||||
MSCFILE_DIRS =
|
||||
|
||||
# The DIAFILE_DIRS tag can be used to specify one or more directories that
|
||||
# contain dia files that are included in the documentation (see the \diafile
|
||||
# command).
|
||||
|
||||
DIAFILE_DIRS =
|
||||
DIAFILE_DIRS =
|
||||
|
||||
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
|
||||
# that will be shown in the graph. If the number of nodes in a graph becomes
|
||||
@ -2319,4 +2322,3 @@ GENERATE_LEGEND = YES
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_CLEANUP = YES
|
||||
|
||||
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\event\TranslationContainer;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\utils\TextFormat;
|
||||
|
||||
/**
|
||||
@ -116,7 +116,7 @@ abstract class Achievement{
|
||||
public static function broadcast(Player $player, string $achievementId) : bool{
|
||||
if(isset(Achievement::$list[$achievementId])){
|
||||
$translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"] . TextFormat::RESET]);
|
||||
if(Server::getInstance()->getConfigBool("announce-player-achievements", true) === true){
|
||||
if(Server::getInstance()->getConfigBool("announce-player-achievements", true)){
|
||||
Server::getInstance()->broadcastMessage($translation);
|
||||
}else{
|
||||
$player->sendMessage($translation);
|
||||
@ -147,6 +147,4 @@ abstract class Achievement{
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -30,9 +30,70 @@ use pocketmine\plugin\PluginManager;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\VersionString;
|
||||
use raklib\RakLib;
|
||||
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 max;
|
||||
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 str_split;
|
||||
use function strpos;
|
||||
use function substr;
|
||||
use function time;
|
||||
use function zend_version;
|
||||
use function zlib_encode;
|
||||
use const E_COMPILE_ERROR;
|
||||
use const E_COMPILE_WARNING;
|
||||
use const E_CORE_ERROR;
|
||||
use const E_CORE_WARNING;
|
||||
use const E_DEPRECATED;
|
||||
use const E_ERROR;
|
||||
use const E_NOTICE;
|
||||
use const E_PARSE;
|
||||
use const E_RECOVERABLE_ERROR;
|
||||
use const E_STRICT;
|
||||
use const E_USER_DEPRECATED;
|
||||
use const E_USER_ERROR;
|
||||
use const E_USER_NOTICE;
|
||||
use const E_USER_WARNING;
|
||||
use const E_WARNING;
|
||||
use const FILE_IGNORE_NEW_LINES;
|
||||
use const JSON_UNESCAPED_SLASHES;
|
||||
use const PHP_EOL;
|
||||
use const PHP_OS;
|
||||
|
||||
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 = 2;
|
||||
|
||||
private const PLUGIN_INVOLVEMENT_NONE = "none";
|
||||
private const PLUGIN_INVOLVEMENT_DIRECT = "direct";
|
||||
private const PLUGIN_INVOLVEMENT_INDIRECT = "indirect";
|
||||
|
||||
/** @var Server */
|
||||
private $server;
|
||||
private $fp;
|
||||
@ -54,6 +115,7 @@ class CrashDump{
|
||||
if(!is_resource($this->fp)){
|
||||
throw new \RuntimeException("Could not create Crash Dump");
|
||||
}
|
||||
$this->data["format_version"] = self::FORMAT_VERSION;
|
||||
$this->data["time"] = $this->time;
|
||||
$this->addLine($this->server->getName() . " Crash Dump " . date("D M j H:i:s T Y", $this->time));
|
||||
$this->addLine();
|
||||
@ -64,6 +126,8 @@ class CrashDump{
|
||||
$this->extraData();
|
||||
|
||||
$this->encodeData();
|
||||
|
||||
fclose($this->fp);
|
||||
}
|
||||
|
||||
public function getPath() : string{
|
||||
@ -83,7 +147,11 @@ class CrashDump{
|
||||
$this->addLine("----------------------REPORT THE DATA BELOW THIS LINE-----------------------");
|
||||
$this->addLine();
|
||||
$this->addLine("===BEGIN CRASH DUMP===");
|
||||
$this->encodedData = zlib_encode(json_encode($this->data, JSON_UNESCAPED_SLASHES), ZLIB_ENCODING_DEFLATE, 9);
|
||||
$json = json_encode($this->data, JSON_UNESCAPED_SLASHES);
|
||||
if($json === false){
|
||||
throw new \RuntimeException("Failed to encode crashdump JSON: " . json_last_error_msg());
|
||||
}
|
||||
$this->encodedData = zlib_encode($json, ZLIB_ENCODING_DEFLATE, 9);
|
||||
foreach(str_split(base64_encode($this->encodedData), 76) as $line){
|
||||
$this->addLine($line);
|
||||
}
|
||||
@ -115,10 +183,10 @@ class CrashDump{
|
||||
}
|
||||
|
||||
private function extraData(){
|
||||
global $arguments;
|
||||
global $argv;
|
||||
|
||||
if($this->server->getProperty("auto-report.send-settings", true) !== false){
|
||||
$this->data["parameters"] = (array) $arguments;
|
||||
$this->data["parameters"] = (array) $argv;
|
||||
$this->data["server.properties"] = @file_get_contents($this->server->getDataPath() . "server.properties");
|
||||
$this->data["server.properties"] = preg_replace("#^rcon\\.password=(.*)$#m", "rcon.password=******", $this->data["server.properties"]);
|
||||
$this->data["pocketmine.yml"] = @file_get_contents($this->server->getDataPath() . "pocketmine.yml");
|
||||
@ -148,7 +216,7 @@ class CrashDump{
|
||||
$error = $lastExceptionError;
|
||||
}else{
|
||||
$error = (array) error_get_last();
|
||||
$error["trace"] = getTrace(4); //Skipping CrashDump->baseCrash, CrashDump->construct, Server->crashDump
|
||||
$error["trace"] = Utils::currentTrace(3); //Skipping CrashDump->baseCrash, CrashDump->construct, Server->crashDump
|
||||
$errorConversion = [
|
||||
E_ERROR => "E_ERROR",
|
||||
E_WARNING => "E_WARNING",
|
||||
@ -167,7 +235,7 @@ class CrashDump{
|
||||
E_USER_DEPRECATED => "E_USER_DEPRECATED"
|
||||
];
|
||||
$error["fullFile"] = $error["file"];
|
||||
$error["file"] = cleanPath($error["file"]);
|
||||
$error["file"] = Utils::cleanPath($error["file"]);
|
||||
$error["type"] = $errorConversion[$error["type"]] ?? $error["type"];
|
||||
if(($pos = strpos($error["message"], "\n")) !== false){
|
||||
$error["message"] = substr($error["message"], 0, $pos);
|
||||
@ -175,6 +243,9 @@ class CrashDump{
|
||||
}
|
||||
|
||||
if(isset($lastError)){
|
||||
if(isset($lastError["trace"])){
|
||||
$lastError["trace"] = Utils::printableTrace($lastError["trace"]);
|
||||
}
|
||||
$this->data["lastError"] = $lastError;
|
||||
}
|
||||
|
||||
@ -186,54 +257,74 @@ class CrashDump{
|
||||
$this->addLine("Line: " . $error["line"]);
|
||||
$this->addLine("Type: " . $error["type"]);
|
||||
|
||||
if(strpos($error["file"], "src/pocketmine/") === false and strpos($error["file"], "src/raklib/") === false and file_exists($error["fullFile"])){
|
||||
$this->addLine();
|
||||
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
|
||||
$this->data["plugin"] = true;
|
||||
|
||||
$reflection = new \ReflectionClass(PluginBase::class);
|
||||
$file = $reflection->getProperty("file");
|
||||
$file->setAccessible(true);
|
||||
foreach($this->server->getPluginManager()->getPlugins() as $plugin){
|
||||
$filePath = \pocketmine\cleanPath($file->getValue($plugin));
|
||||
if(strpos($error["file"], $filePath) === 0){
|
||||
$this->data["plugin"] = $plugin->getName();
|
||||
$this->addLine("BAD PLUGIN: " . $plugin->getDescription()->getFullName());
|
||||
$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;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$this->data["plugin"] = false;
|
||||
}
|
||||
|
||||
$this->addLine();
|
||||
$this->addLine("Code:");
|
||||
$this->data["code"] = [];
|
||||
|
||||
if($this->server->getProperty("auto-report.send-code", true) !== false){
|
||||
if($this->server->getProperty("auto-report.send-code", true) !== false and file_exists($error["fullFile"])){
|
||||
$file = @file($error["fullFile"], FILE_IGNORE_NEW_LINES);
|
||||
for($l = max(0, $error["line"] - 10); $l < $error["line"] + 10; ++$l){
|
||||
$this->addLine("[" . ($l + 1) . "] " . @$file[$l]);
|
||||
$this->data["code"][$l + 1] = @$file[$l];
|
||||
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"] = $error["trace"]) as $line){
|
||||
foreach(($this->data["trace"] = Utils::printableTrace($error["trace"])) as $line){
|
||||
$this->addLine($line);
|
||||
}
|
||||
$this->addLine();
|
||||
}
|
||||
|
||||
private function determinePluginFromFile(string $filePath, bool $crashFrame) : bool{
|
||||
$frameCleanPath = Utils::cleanPath($filePath); //this will be empty in phar stub
|
||||
if($frameCleanPath !== "" and strpos($frameCleanPath, "src/pocketmine/") === false and strpos($frameCleanPath, "vendor/pocketmine/") === false and file_exists($filePath)){
|
||||
$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;
|
||||
}
|
||||
|
||||
$reflection = new \ReflectionClass(PluginBase::class);
|
||||
$file = $reflection->getProperty("file");
|
||||
$file->setAccessible(true);
|
||||
foreach($this->server->getPluginManager()->getPlugins() as $plugin){
|
||||
$filePath = Utils::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(){
|
||||
$version = new VersionString();
|
||||
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
|
||||
$this->data["general"] = [];
|
||||
$this->data["general"]["name"] = $this->server->getName();
|
||||
$this->data["general"]["version"] = $version->get(false);
|
||||
$this->data["general"]["build"] = $version->getBuild();
|
||||
$this->data["general"]["base_version"] = \pocketmine\BASE_VERSION;
|
||||
$this->data["general"]["build"] = \pocketmine\BUILD_NUMBER;
|
||||
$this->data["general"]["is_dev"] = \pocketmine\IS_DEVELOPMENT_BUILD;
|
||||
$this->data["general"]["protocol"] = ProtocolInfo::CURRENT_PROTOCOL;
|
||||
$this->data["general"]["api"] = \pocketmine\API_VERSION;
|
||||
$this->data["general"]["git"] = \pocketmine\GIT_COMMIT;
|
||||
$this->data["general"]["raklib"] = RakLib::VERSION;
|
||||
$this->data["general"]["uname"] = php_uname("a");
|
||||
@ -241,7 +332,7 @@ class CrashDump{
|
||||
$this->data["general"]["zend"] = zend_version();
|
||||
$this->data["general"]["php_os"] = PHP_OS;
|
||||
$this->data["general"]["os"] = Utils::getOS();
|
||||
$this->addLine($this->server->getName() . " version: " . $version->get(false) . " #" . $version->getBuild() . " [Protocol " . ProtocolInfo::CURRENT_PROTOCOL . "; API " . API_VERSION . "]");
|
||||
$this->addLine($this->server->getName() . " version: " . $version->getFullVersion(true) . " [Protocol " . ProtocolInfo::CURRENT_PROTOCOL . "]");
|
||||
$this->addLine("Git commit: " . GIT_COMMIT);
|
||||
$this->addLine("uname -a: " . php_uname("a"));
|
||||
$this->addLine("PHP Version: " . phpversion());
|
||||
@ -256,5 +347,4 @@ class CrashDump{
|
||||
public function add($str){
|
||||
fwrite($this->fp, $str);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -24,11 +24,43 @@ declare(strict_types=1);
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\event\server\LowMemoryEvent;
|
||||
use pocketmine\event\Timings;
|
||||
use pocketmine\scheduler\DumpWorkerMemoryTask;
|
||||
use pocketmine\scheduler\GarbageCollectionTask;
|
||||
use pocketmine\utils\MainLogger;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\utils\Utils;
|
||||
use function arsort;
|
||||
use function count;
|
||||
use function fclose;
|
||||
use function file_exists;
|
||||
use function file_put_contents;
|
||||
use function fopen;
|
||||
use function fwrite;
|
||||
use function gc_collect_cycles;
|
||||
use function gc_disable;
|
||||
use function gc_enable;
|
||||
use function get_class;
|
||||
use function get_declared_classes;
|
||||
use function implode;
|
||||
use function ini_get;
|
||||
use function ini_set;
|
||||
use function is_array;
|
||||
use function is_object;
|
||||
use function is_resource;
|
||||
use function is_string;
|
||||
use function json_encode;
|
||||
use function min;
|
||||
use function mkdir;
|
||||
use function preg_match;
|
||||
use function print_r;
|
||||
use function round;
|
||||
use function spl_object_hash;
|
||||
use function sprintf;
|
||||
use function strlen;
|
||||
use function strtoupper;
|
||||
use function substr;
|
||||
use const JSON_PRETTY_PRINT;
|
||||
use const JSON_UNESCAPED_SLASHES;
|
||||
use const SORT_NUMERIC;
|
||||
|
||||
class MemoryManager{
|
||||
|
||||
@ -186,7 +218,7 @@ class MemoryManager{
|
||||
}
|
||||
|
||||
$ev = new LowMemoryEvent($memory, $limit, $global, $triggerCount);
|
||||
$this->server->getPluginManager()->callEvent($ev);
|
||||
$ev->call();
|
||||
|
||||
$cycles = 0;
|
||||
if($this->garbageCollectionTrigger){
|
||||
@ -243,9 +275,12 @@ class MemoryManager{
|
||||
Timings::$garbageCollectorTimer->startTiming();
|
||||
|
||||
if($this->garbageCollectionAsync){
|
||||
$size = $this->server->getScheduler()->getAsyncTaskPoolSize();
|
||||
for($i = 0; $i < $size; ++$i){
|
||||
$this->server->getScheduler()->scheduleAsyncTaskToWorker(new GarbageCollectionTask(), $i);
|
||||
$pool = $this->server->getAsyncPool();
|
||||
if(($w = $pool->shutdownUnusedWorkers()) > 0){
|
||||
$this->server->getLogger()->debug("Shut down $w idle async pool workers");
|
||||
}
|
||||
foreach($pool->getRunningWorkers() as $i){
|
||||
$pool->submitTaskToWorker(new GarbageCollectionTask(), $i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,13 +299,13 @@ class MemoryManager{
|
||||
* @param int $maxStringSize
|
||||
*/
|
||||
public function dumpServerMemory(string $outputFolder, int $maxNesting, int $maxStringSize){
|
||||
MainLogger::getLogger()->notice("[Dump] After the memory dump is done, the server might crash");
|
||||
self::dumpMemory($this->server, $this->server->getLoader(), $outputFolder, $maxNesting, $maxStringSize);
|
||||
$this->server->getLogger()->notice("[Dump] After the memory dump is done, the server might crash");
|
||||
self::dumpMemory($this->server, $outputFolder, $maxNesting, $maxStringSize, $this->server->getLogger());
|
||||
|
||||
if($this->dumpWorkers){
|
||||
$scheduler = $this->server->getScheduler();
|
||||
for($i = 0, $size = $scheduler->getAsyncTaskPoolSize(); $i < $size; ++$i){
|
||||
$scheduler->scheduleAsyncTaskToWorker(new DumpWorkerMemoryTask($outputFolder, $maxNesting, $maxStringSize), $i);
|
||||
$pool = $this->server->getAsyncPool();
|
||||
foreach($pool->getRunningWorkers() as $i){
|
||||
$pool->submitTaskToWorker(new DumpWorkerMemoryTask($outputFolder, $maxNesting, $maxStringSize), $i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -278,13 +313,15 @@ class MemoryManager{
|
||||
/**
|
||||
* Static memory dumper accessible from any thread.
|
||||
*
|
||||
* @param mixed $startingObject
|
||||
* @param \ClassLoader $loader
|
||||
* @param string $outputFolder
|
||||
* @param int $maxNesting
|
||||
* @param int $maxStringSize
|
||||
* @param mixed $startingObject
|
||||
* @param string $outputFolder
|
||||
* @param int $maxNesting
|
||||
* @param int $maxStringSize
|
||||
* @param \Logger $logger
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public static function dumpMemory($startingObject, \ClassLoader $loader, string $outputFolder, int $maxNesting, int $maxStringSize){
|
||||
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger){
|
||||
$hardLimit = ini_get('memory_limit');
|
||||
ini_set('memory_limit', '-1');
|
||||
gc_disable();
|
||||
@ -306,7 +343,7 @@ class MemoryManager{
|
||||
$staticProperties = [];
|
||||
$staticCount = 0;
|
||||
|
||||
foreach($loader->getClasses() as $className){
|
||||
foreach(get_declared_classes() as $className){
|
||||
$reflection = new \ReflectionClass($className);
|
||||
$staticProperties[$className] = [];
|
||||
foreach($reflection->getProperties() as $property){
|
||||
@ -328,9 +365,9 @@ class MemoryManager{
|
||||
}
|
||||
|
||||
file_put_contents($outputFolder . "/staticProperties.js", json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
MainLogger::getLogger()->info("[Dump] Wrote $staticCount static properties");
|
||||
$logger->info("[Dump] Wrote $staticCount static properties");
|
||||
|
||||
if($GLOBALS !== null){ //This might be null if we're on a different thread
|
||||
if(isset($GLOBALS)){ //This might be null if we're on a different thread
|
||||
$globalVariables = [];
|
||||
$globalCount = 0;
|
||||
|
||||
@ -356,7 +393,7 @@ class MemoryManager{
|
||||
}
|
||||
|
||||
file_put_contents($outputFolder . "/globalVariables.js", json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
MainLogger::getLogger()->info("[Dump] Wrote $globalCount global variables");
|
||||
$logger->info("[Dump] Wrote $globalCount global variables");
|
||||
}
|
||||
|
||||
self::continueDump($startingObject, $data, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
@ -393,15 +430,22 @@ class MemoryManager{
|
||||
$info["implements"] = implode(", ", $reflection->getInterfaceNames());
|
||||
}
|
||||
|
||||
foreach($reflection->getProperties() as $property){
|
||||
if($property->isStatic()){
|
||||
continue;
|
||||
}
|
||||
for($original = $reflection; $reflection !== false; $reflection = $reflection->getParentClass()){
|
||||
foreach($reflection->getProperties() as $property){
|
||||
if($property->isStatic()){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!$property->isPublic()){
|
||||
$property->setAccessible(true);
|
||||
$name = $property->getName();
|
||||
if($reflection !== $original and !$property->isPublic()){
|
||||
$name = $reflection->getName() . ":" . $name;
|
||||
}
|
||||
if(!$property->isPublic()){
|
||||
$property->setAccessible(true);
|
||||
}
|
||||
|
||||
self::continueDump($property->getValue($object), $info["properties"][$name], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
self::continueDump($property->getValue($object), $info["properties"][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
|
||||
fwrite($obData, "$hash@$className: " . json_encode($info, JSON_UNESCAPED_SLASHES) . "\n");
|
||||
@ -410,7 +454,7 @@ class MemoryManager{
|
||||
|
||||
}while($continue);
|
||||
|
||||
MainLogger::getLogger()->info("[Dump] Wrote " . count($objects) . " objects");
|
||||
$logger->info("[Dump] Wrote " . count($objects) . " objects");
|
||||
|
||||
fclose($obData);
|
||||
|
||||
@ -420,7 +464,7 @@ class MemoryManager{
|
||||
arsort($instanceCounts, SORT_NUMERIC);
|
||||
file_put_contents($outputFolder . "/instanceCounts.js", json_encode($instanceCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
|
||||
MainLogger::getLogger()->info("[Dump] Finished!");
|
||||
$logger->info("[Dump] Finished!");
|
||||
|
||||
ini_set('memory_limit', $hardLimit);
|
||||
gc_enable();
|
||||
@ -462,7 +506,7 @@ class MemoryManager{
|
||||
self::continueDump($value, $data[$key], $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize);
|
||||
}
|
||||
}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);
|
||||
}elseif(is_resource($from)){
|
||||
$data = "(resource) " . print_r($from, true);
|
||||
}else{
|
||||
|
@ -35,7 +35,7 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
||||
/** @var Server */
|
||||
private $server;
|
||||
/** @var CompoundTag|null */
|
||||
private $namedtag;
|
||||
private $namedtag = null;
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
@ -44,10 +44,8 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
||||
public function __construct(Server $server, string $name){
|
||||
$this->server = $server;
|
||||
$this->name = $name;
|
||||
if(file_exists($this->server->getDataPath() . "players/" . strtolower($this->getName()) . ".dat")){
|
||||
if($this->server->hasOfflinePlayerData($this->name)){
|
||||
$this->namedtag = $this->server->getOfflinePlayerData($this->name);
|
||||
}else{
|
||||
$this->namedtag = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +62,7 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
||||
}
|
||||
|
||||
public function isOp() : bool{
|
||||
return $this->server->isOp(strtolower($this->getName()));
|
||||
return $this->server->isOp($this->name);
|
||||
}
|
||||
|
||||
public function setOp(bool $value){
|
||||
@ -72,39 +70,39 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
||||
return;
|
||||
}
|
||||
|
||||
if($value === true){
|
||||
$this->server->addOp(strtolower($this->getName()));
|
||||
if($value){
|
||||
$this->server->addOp($this->name);
|
||||
}else{
|
||||
$this->server->removeOp(strtolower($this->getName()));
|
||||
$this->server->removeOp($this->name);
|
||||
}
|
||||
}
|
||||
|
||||
public function isBanned() : bool{
|
||||
return $this->server->getNameBans()->isBanned(strtolower($this->getName()));
|
||||
return $this->server->getNameBans()->isBanned($this->name);
|
||||
}
|
||||
|
||||
public function setBanned(bool $value){
|
||||
if($value === true){
|
||||
$this->server->getNameBans()->addBan($this->getName(), null, null, null);
|
||||
if($value){
|
||||
$this->server->getNameBans()->addBan($this->name, null, null, null);
|
||||
}else{
|
||||
$this->server->getNameBans()->remove($this->getName());
|
||||
$this->server->getNameBans()->remove($this->name);
|
||||
}
|
||||
}
|
||||
|
||||
public function isWhitelisted() : bool{
|
||||
return $this->server->isWhitelisted(strtolower($this->getName()));
|
||||
return $this->server->isWhitelisted($this->name);
|
||||
}
|
||||
|
||||
public function setWhitelisted(bool $value){
|
||||
if($value === true){
|
||||
$this->server->addWhitelist(strtolower($this->getName()));
|
||||
if($value){
|
||||
$this->server->addWhitelist($this->name);
|
||||
}else{
|
||||
$this->server->removeWhitelist(strtolower($this->getName()));
|
||||
$this->server->removeWhitelist($this->name);
|
||||
}
|
||||
}
|
||||
|
||||
public function getPlayer(){
|
||||
return $this->server->getPlayerExact($this->getName());
|
||||
return $this->server->getPlayerExact($this->name);
|
||||
}
|
||||
|
||||
public function getFirstPlayed(){
|
||||
@ -134,6 +132,4 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
||||
public function removeMetadata(string $metadataKey, Plugin $owningPlugin){
|
||||
$this->server->getPlayerMetadata()->removeMetadata($this, $metadataKey, $owningPlugin);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -24,141 +24,149 @@ declare(strict_types=1);
|
||||
namespace {
|
||||
const INT32_MIN = -0x80000000;
|
||||
const INT32_MAX = 0x7fffffff;
|
||||
|
||||
function safe_var_dump(){
|
||||
static $cnt = 0;
|
||||
foreach(func_get_args() as $var){
|
||||
switch(true){
|
||||
case is_array($var):
|
||||
echo str_repeat(" ", $cnt) . "array(" . count($var) . ") {" . PHP_EOL;
|
||||
foreach($var as $key => $value){
|
||||
echo str_repeat(" ", $cnt + 1) . "[" . (is_int($key) ? $key : '"' . $key . '"') . "]=>" . PHP_EOL;
|
||||
++$cnt;
|
||||
safe_var_dump($value);
|
||||
--$cnt;
|
||||
}
|
||||
echo str_repeat(" ", $cnt) . "}" . PHP_EOL;
|
||||
break;
|
||||
case is_int($var):
|
||||
echo str_repeat(" ", $cnt) . "int(" . $var . ")" . PHP_EOL;
|
||||
break;
|
||||
case is_float($var):
|
||||
echo str_repeat(" ", $cnt) . "float(" . $var . ")" . PHP_EOL;
|
||||
break;
|
||||
case is_bool($var):
|
||||
echo str_repeat(" ", $cnt) . "bool(" . ($var === true ? "true" : "false") . ")" . PHP_EOL;
|
||||
break;
|
||||
case is_string($var):
|
||||
echo str_repeat(" ", $cnt) . "string(" . strlen($var) . ") \"$var\"" . PHP_EOL;
|
||||
break;
|
||||
case is_resource($var):
|
||||
echo str_repeat(" ", $cnt) . "resource() of type (" . get_resource_type($var) . ")" . PHP_EOL;
|
||||
break;
|
||||
case is_object($var):
|
||||
echo str_repeat(" ", $cnt) . "object(" . get_class($var) . ")" . PHP_EOL;
|
||||
break;
|
||||
case is_null($var):
|
||||
echo str_repeat(" ", $cnt) . "NULL" . PHP_EOL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function dummy(){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace pocketmine {
|
||||
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\ServerKiller;
|
||||
use pocketmine\utils\Terminal;
|
||||
use pocketmine\utils\Timezone;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\VersionString;
|
||||
use pocketmine\wizard\SetupWizard;
|
||||
use raklib\RakLib;
|
||||
|
||||
const NAME = "PocketMine-MP";
|
||||
const VERSION = "1.7dev";
|
||||
const API_VERSION = "3.0.0-ALPHA10";
|
||||
const CODENAME = "[REDACTED]";
|
||||
const BASE_VERSION = "3.7.0";
|
||||
const IS_DEVELOPMENT_BUILD = false;
|
||||
const BUILD_NUMBER = 0;
|
||||
|
||||
const MIN_PHP_VERSION = "7.2.0RC3";
|
||||
const MIN_PHP_VERSION = "7.2.0";
|
||||
|
||||
function critical_error($message){
|
||||
echo "[ERROR] $message" . PHP_EOL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Startup code. Do not look at it, it may harm you.
|
||||
* Most of them are hacks to fix date-related bugs, or basic functions used after this
|
||||
* This is the only non-class based file on this project.
|
||||
* Enjoy it as much as I did writing it. I don't want to do it again.
|
||||
*/
|
||||
|
||||
if(version_compare(MIN_PHP_VERSION, PHP_VERSION) > 0){
|
||||
echo "[CRITICAL] " . \pocketmine\NAME . " requires PHP >= " . MIN_PHP_VERSION . ", but you have PHP " . PHP_VERSION . "." . PHP_EOL;
|
||||
echo "[CRITICAL] Please use the installer provided on the homepage, or update to a newer PHP version." . PHP_EOL;
|
||||
exit(1);
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
function check_platform_dependencies(){
|
||||
if(version_compare(MIN_PHP_VERSION, PHP_VERSION) > 0){
|
||||
//If PHP version isn't high enough, anything below might break, so don't bother checking it.
|
||||
return [
|
||||
\pocketmine\NAME . " requires PHP >= " . MIN_PHP_VERSION . ", but you have PHP " . PHP_VERSION . "."
|
||||
];
|
||||
}
|
||||
|
||||
$messages = [];
|
||||
|
||||
if(PHP_INT_SIZE < 8){
|
||||
$messages[] = "Running " . \pocketmine\NAME . " with 32-bit systems/PHP is no longer supported. Please upgrade to a 64-bit system, or use a 64-bit PHP binary if this is a 64-bit system.";
|
||||
}
|
||||
|
||||
if(php_sapi_name() !== "cli"){
|
||||
$messages[] = "You must run " . \pocketmine\NAME . " using the CLI.";
|
||||
}
|
||||
|
||||
$extensions = [
|
||||
"bcmath" => "BC Math",
|
||||
"curl" => "cURL",
|
||||
"ctype" => "ctype",
|
||||
"date" => "Date",
|
||||
"hash" => "Hash",
|
||||
"json" => "JSON",
|
||||
"mbstring" => "Multibyte String",
|
||||
"openssl" => "OpenSSL",
|
||||
"pcre" => "PCRE",
|
||||
"phar" => "Phar",
|
||||
"pthreads" => "pthreads",
|
||||
"reflection" => "Reflection",
|
||||
"sockets" => "Sockets",
|
||||
"spl" => "SPL",
|
||||
"yaml" => "YAML",
|
||||
"zip" => "Zip",
|
||||
"zlib" => "Zlib"
|
||||
];
|
||||
|
||||
foreach($extensions as $ext => $name){
|
||||
if(!extension_loaded($ext)){
|
||||
$messages[] = "Unable to find the $name ($ext) extension.";
|
||||
}
|
||||
}
|
||||
|
||||
if(extension_loaded("pthreads")){
|
||||
$pthreads_version = phpversion("pthreads");
|
||||
if(substr_count($pthreads_version, ".") < 2){
|
||||
$pthreads_version = "0.$pthreads_version";
|
||||
}
|
||||
if(version_compare($pthreads_version, "3.1.7dev") < 0){
|
||||
$messages[] = "pthreads >= 3.1.7dev is required, while you have $pthreads_version.";
|
||||
}
|
||||
}
|
||||
|
||||
if(extension_loaded("leveldb")){
|
||||
$leveldb_version = phpversion("leveldb");
|
||||
if(version_compare($leveldb_version, "0.2.1") < 0){
|
||||
$messages[] = "php-leveldb >= 0.2.1 is required, while you have $leveldb_version.";
|
||||
}
|
||||
}
|
||||
|
||||
if(extension_loaded("pocketmine")){
|
||||
$messages[] = "The native PocketMine extension is no longer supported.";
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
if(!extension_loaded("pthreads")){
|
||||
echo "[CRITICAL] Unable to find the pthreads extension." . PHP_EOL;
|
||||
echo "[CRITICAL] Please use the installer provided on the homepage." . PHP_EOL;
|
||||
if(!empty($messages = check_platform_dependencies())){
|
||||
echo PHP_EOL;
|
||||
$binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown";
|
||||
critical_error("Selected PHP binary ($binary) does not satisfy some requirements.");
|
||||
foreach($messages as $m){
|
||||
echo " - $m" . PHP_EOL;
|
||||
}
|
||||
critical_error("Please recompile PHP with the needed configuration, or refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html.");
|
||||
echo PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
unset($messages);
|
||||
|
||||
error_reporting(-1);
|
||||
|
||||
function error_handler($severity, $message, $file, $line){
|
||||
if(error_reporting() & $severity){
|
||||
throw new \ErrorException($message, 0, $severity, $file, $line);
|
||||
}else{ //stfu operator
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
set_error_handler('\pocketmine\error_handler');
|
||||
|
||||
if(!extension_loaded("phar")){
|
||||
echo "[CRITICAL] Unable to find the Phar extension." . PHP_EOL;
|
||||
echo "[CRITICAL] Please use the installer provided on the homepage." . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(\Phar::running(true) !== ""){
|
||||
define('pocketmine\PATH', \Phar::running(true) . "/");
|
||||
}else{
|
||||
define('pocketmine\PATH', dirname(__FILE__, 3) . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', \pocketmine\PATH . 'vendor/autoload.php');
|
||||
$opts = getopt("", ["bootstrap:"]);
|
||||
if(isset($opts["bootstrap"])){
|
||||
$bootstrap = realpath($opts["bootstrap"]) ?: $opts["bootstrap"];
|
||||
}else{
|
||||
$bootstrap = \pocketmine\PATH . 'vendor/autoload.php';
|
||||
}
|
||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
|
||||
|
||||
function composer_error_die($message){
|
||||
echo "[CRITICAL] $message" . PHP_EOL;
|
||||
echo "[CRITICAL] Please install/update Composer dependencies or use provided builds." . PHP_EOL;
|
||||
if(\pocketmine\COMPOSER_AUTOLOADER_PATH !== false and is_file(\pocketmine\COMPOSER_AUTOLOADER_PATH)){
|
||||
require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH);
|
||||
}else{
|
||||
critical_error("Composer autoloader not found at " . $bootstrap);
|
||||
critical_error("Please install/update Composer dependencies or use provided builds.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(is_file(\pocketmine\COMPOSER_AUTOLOADER_PATH)){
|
||||
require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH);
|
||||
}else{
|
||||
composer_error_die("Composer autoloader not found.");
|
||||
}
|
||||
|
||||
if(!class_exists(RakLib::class)){
|
||||
composer_error_die("Unable to find the RakLib library.");
|
||||
}
|
||||
if(version_compare(RakLib::VERSION, "0.9.0") < 0){ //TODO: remove this check (it's managed by Composer now)
|
||||
composer_error_die("RakLib version 0.9.0 is required, while you have version " . RakLib::VERSION . ".");
|
||||
}
|
||||
if(!class_exists(\BaseClassLoader::class)){
|
||||
composer_error_die("Unable to find the PocketMine-SPL library.");
|
||||
}
|
||||
set_error_handler([Utils::class, 'errorExceptionHandler']);
|
||||
|
||||
/*
|
||||
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
|
||||
*/
|
||||
$autoloader = new \BaseClassLoader();
|
||||
$autoloader->addPath(\pocketmine\PATH . "src");
|
||||
$autoloader->addPath(\pocketmine\PATH . "src" . DIRECTORY_SEPARATOR . "spl");
|
||||
$autoloader->register(false);
|
||||
|
||||
set_time_limit(0); //Who set it to 30 seconds?!?!
|
||||
@ -169,374 +177,65 @@ namespace pocketmine {
|
||||
ini_set("default_charset", "utf-8");
|
||||
|
||||
ini_set("memory_limit", '-1');
|
||||
define('pocketmine\START_TIME', microtime(true));
|
||||
|
||||
define('pocketmine\RESOURCE_PATH', \pocketmine\PATH . 'src' . DIRECTORY_SEPARATOR . 'pocketmine' . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR);
|
||||
|
||||
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-profiler"]);
|
||||
$opts = getopt("", ["data:", "plugins:", "no-wizard"]);
|
||||
|
||||
define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR);
|
||||
define('pocketmine\PLUGIN_PATH', isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR);
|
||||
|
||||
Terminal::init();
|
||||
|
||||
define('pocketmine\ANSI', Terminal::hasFormattingCodes());
|
||||
define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR);
|
||||
define('pocketmine\PLUGIN_PATH', isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR);
|
||||
|
||||
if(!file_exists(\pocketmine\DATA)){
|
||||
mkdir(\pocketmine\DATA, 0777, true);
|
||||
}
|
||||
|
||||
//Logger has a dependency on timezone, so we'll set it to UTC until we can get the actual timezone.
|
||||
date_default_timezone_set("UTC");
|
||||
//Logger has a dependency on timezone
|
||||
$tzError = Timezone::init();
|
||||
|
||||
$logger = new MainLogger(\pocketmine\DATA . "server.log");
|
||||
$logger->registerStatic();
|
||||
|
||||
do{
|
||||
$timezone = ini_get("date.timezone");
|
||||
if($timezone !== ""){
|
||||
/*
|
||||
* This is here so that people don't come to us complaining and fill up the issue tracker when they put
|
||||
* an incorrect timezone abbreviation in php.ini apparently.
|
||||
*/
|
||||
if(strpos($timezone, "/") === false){
|
||||
$default_timezone = timezone_name_from_abbr($timezone);
|
||||
if($default_timezone !== false){
|
||||
ini_set("date.timezone", $default_timezone);
|
||||
date_default_timezone_set($default_timezone);
|
||||
break;
|
||||
}else{
|
||||
//Bad php.ini value, try another method to detect timezone
|
||||
$logger->warning("Timezone \"$timezone\" could not be parsed as a valid timezone from php.ini, falling back to auto-detection");
|
||||
}
|
||||
}else{
|
||||
date_default_timezone_set($timezone);
|
||||
break;
|
||||
foreach($tzError as $e){
|
||||
$logger->warning($e);
|
||||
}
|
||||
unset($tzError);
|
||||
|
||||
if(extension_loaded("xdebug")){
|
||||
$logger->warning(PHP_EOL . PHP_EOL . PHP_EOL . "\tYou are running " . \pocketmine\NAME . " with xdebug enabled. This has a major impact on performance." . PHP_EOL . PHP_EOL);
|
||||
}
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
$logger->warning("Non-packaged " . \pocketmine\NAME . " installation detected. Consider using a phar in production for better performance.");
|
||||
}
|
||||
|
||||
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
|
||||
define('pocketmine\VERSION', $version->getFullVersion(true));
|
||||
|
||||
$gitHash = str_repeat("00", 20);
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
if(Utils::execute("git rev-parse HEAD", $out) === 0 and $out !== false and strlen($out = trim($out)) === 40){
|
||||
$gitHash = trim($out);
|
||||
if(Utils::execute("git diff --quiet") === 1 or Utils::execute("git diff --cached --quiet") === 1){ //Locally-modified
|
||||
$gitHash .= "-dirty";
|
||||
}
|
||||
}
|
||||
|
||||
if(($timezone = detect_system_timezone()) and date_default_timezone_set($timezone)){
|
||||
//Success! Timezone has already been set and validated in the if statement.
|
||||
//This here is just for redundancy just in case some program wants to read timezone data from the ini.
|
||||
ini_set("date.timezone", $timezone);
|
||||
break;
|
||||
}
|
||||
|
||||
if($response = Utils::getURL("http://ip-api.com/json") //If system timezone detection fails or timezone is an invalid value.
|
||||
and $ip_geolocation_data = json_decode($response, true)
|
||||
and $ip_geolocation_data['status'] !== 'fail'
|
||||
and date_default_timezone_set($ip_geolocation_data['timezone'])
|
||||
){
|
||||
//Again, for redundancy.
|
||||
ini_set("date.timezone", $ip_geolocation_data['timezone']);
|
||||
break;
|
||||
}
|
||||
|
||||
ini_set("date.timezone", "UTC");
|
||||
date_default_timezone_set("UTC");
|
||||
$logger->warning("Timezone could not be automatically determined or was set to an invalid value. An incorrect timezone will result in incorrect timestamps on console logs. It has been set to \"UTC\" by default. You can change it on the php.ini file.");
|
||||
}while(false);
|
||||
|
||||
|
||||
function detect_system_timezone(){
|
||||
switch(Utils::getOS()){
|
||||
case 'win':
|
||||
$regex = '/(UTC)(\+*\-*\d*\d*\:*\d*\d*)/';
|
||||
|
||||
/*
|
||||
* wmic timezone get Caption
|
||||
* Get the timezone offset
|
||||
*
|
||||
* Sample Output var_dump
|
||||
* array(3) {
|
||||
* [0] =>
|
||||
* string(7) "Caption"
|
||||
* [1] =>
|
||||
* string(20) "(UTC+09:30) Adelaide"
|
||||
* [2] =>
|
||||
* string(0) ""
|
||||
* }
|
||||
*/
|
||||
exec("wmic timezone get Caption", $output);
|
||||
|
||||
$string = trim(implode("\n", $output));
|
||||
|
||||
//Detect the Time Zone string
|
||||
preg_match($regex, $string, $matches);
|
||||
|
||||
if(!isset($matches[2])){
|
||||
return false;
|
||||
}
|
||||
|
||||
$offset = $matches[2];
|
||||
|
||||
if($offset == ""){
|
||||
return "UTC";
|
||||
}
|
||||
|
||||
return parse_offset($offset);
|
||||
case 'linux':
|
||||
// Ubuntu / Debian.
|
||||
if(file_exists('/etc/timezone')){
|
||||
$data = file_get_contents('/etc/timezone');
|
||||
if($data){
|
||||
return trim($data);
|
||||
}
|
||||
}
|
||||
|
||||
// RHEL / CentOS
|
||||
if(file_exists('/etc/sysconfig/clock')){
|
||||
$data = parse_ini_file('/etc/sysconfig/clock');
|
||||
if(!empty($data['ZONE'])){
|
||||
return trim($data['ZONE']);
|
||||
}
|
||||
}
|
||||
|
||||
//Portable method for incompatible linux distributions.
|
||||
|
||||
$offset = trim(exec('date +%:z'));
|
||||
|
||||
if($offset == "+00:00"){
|
||||
return "UTC";
|
||||
}
|
||||
|
||||
return parse_offset($offset);
|
||||
case 'mac':
|
||||
if(is_link('/etc/localtime')){
|
||||
$filename = readlink('/etc/localtime');
|
||||
if(strpos($filename, '/usr/share/zoneinfo/') === 0){
|
||||
$timezone = substr($filename, 20);
|
||||
return trim($timezone);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}else{
|
||||
$phar = new \Phar(\Phar::running(false));
|
||||
$meta = $phar->getMetadata();
|
||||
if(isset($meta["git"])){
|
||||
$gitHash = $meta["git"];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $offset In the format of +09:00, +02:00, -04:00 etc.
|
||||
*
|
||||
* @return string|bool
|
||||
*/
|
||||
function parse_offset($offset){
|
||||
//Make signed offsets unsigned for date_parse
|
||||
if(strpos($offset, '-') !== false){
|
||||
$negative_offset = true;
|
||||
$offset = str_replace('-', '', $offset);
|
||||
}else{
|
||||
if(strpos($offset, '+') !== false){
|
||||
$negative_offset = false;
|
||||
$offset = str_replace('+', '', $offset);
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||
|
||||
$parsed = date_parse($offset);
|
||||
$offset = $parsed['hour'] * 3600 + $parsed['minute'] * 60 + $parsed['second'];
|
||||
|
||||
//After date_parse is done, put the sign back
|
||||
if($negative_offset == true){
|
||||
$offset = -abs($offset);
|
||||
}
|
||||
|
||||
//And then, look the offset up.
|
||||
//timezone_name_from_abbr is not used because it returns false on some(most) offsets because it's mapping function is weird.
|
||||
//That's been a bug in PHP since 2008!
|
||||
foreach(timezone_abbreviations_list() as $zones){
|
||||
foreach($zones as $timezone){
|
||||
if($timezone['offset'] == $offset){
|
||||
return $timezone['timezone_id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(isset($opts["enable-profiler"])){
|
||||
if(function_exists("profiler_enable")){
|
||||
\profiler_enable();
|
||||
$logger->notice("Execution is being profiled");
|
||||
}else{
|
||||
$logger->notice("No profiler found. Please install https://github.com/krakjoe/profiler");
|
||||
}
|
||||
}
|
||||
|
||||
function kill($pid){
|
||||
switch(Utils::getOS()){
|
||||
case "win":
|
||||
exec("taskkill.exe /F /PID " . ((int) $pid) . " > NUL");
|
||||
break;
|
||||
case "mac":
|
||||
case "linux":
|
||||
default:
|
||||
if(function_exists("posix_kill")){
|
||||
posix_kill($pid, SIGKILL);
|
||||
}else{
|
||||
exec("kill -9 " . ((int) $pid) . " > /dev/null 2>&1");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object $value
|
||||
* @param bool $includeCurrent
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
function getReferenceCount($value, $includeCurrent = true){
|
||||
ob_start();
|
||||
debug_zval_dump($value);
|
||||
$ret = explode("\n", ob_get_contents());
|
||||
ob_end_clean();
|
||||
|
||||
if(count($ret) >= 1 and preg_match('/^.* refcount\\(([0-9]+)\\)\\{$/', trim($ret[0]), $m) > 0){
|
||||
return ((int) $m[1]) - ($includeCurrent ? 3 : 4); //$value + zval call + extra call
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $start
|
||||
* @param array|null $trace
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getTrace($start = 0, $trace = null){
|
||||
if($trace === null){
|
||||
if(function_exists("xdebug_get_function_stack")){
|
||||
$trace = array_reverse(xdebug_get_function_stack());
|
||||
}else{
|
||||
$e = new \Exception();
|
||||
$trace = $e->getTrace();
|
||||
}
|
||||
}
|
||||
|
||||
$messages = [];
|
||||
$j = 0;
|
||||
for($i = (int) $start; isset($trace[$i]); ++$i, ++$j){
|
||||
$params = "";
|
||||
if(isset($trace[$i]["args"]) or isset($trace[$i]["params"])){
|
||||
if(isset($trace[$i]["args"])){
|
||||
$args = $trace[$i]["args"];
|
||||
}else{
|
||||
$args = $trace[$i]["params"];
|
||||
}
|
||||
|
||||
$params = implode(", ", array_map(function($value){
|
||||
return (is_object($value) ? get_class($value) . " object" : gettype($value) . " " . (is_array($value) ? "Array()" : Utils::printable(@strval($value))));
|
||||
}, $args));
|
||||
}
|
||||
$messages[] = "#$j " . (isset($trace[$i]["file"]) ? cleanPath($trace[$i]["file"]) : "") . "(" . (isset($trace[$i]["line"]) ? $trace[$i]["line"] : "") . "): " . (isset($trace[$i]["class"]) ? $trace[$i]["class"] . (($trace[$i]["type"] === "dynamic" or $trace[$i]["type"] === "->") ? "->" : "::") : "") . $trace[$i]["function"] . "(" . Utils::printable($params) . ")";
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
function cleanPath($path){
|
||||
return str_replace(["\\", ".php", "phar://", str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PATH), str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PLUGIN_PATH)], ["/", "", "", "", ""], $path);
|
||||
}
|
||||
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
|
||||
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors
|
||||
|
||||
$exitCode = 0;
|
||||
|
||||
do{
|
||||
$errors = 0;
|
||||
|
||||
if(PHP_INT_SIZE < 8){
|
||||
$logger->critical("Running " . \pocketmine\NAME . " with 32-bit systems/PHP is no longer supported. Please upgrade to a 64-bit system or use a 64-bit PHP binary.");
|
||||
$exitCode = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(php_sapi_name() !== "cli"){
|
||||
$logger->critical("You must run " . \pocketmine\NAME . " using the CLI.");
|
||||
++$errors;
|
||||
}
|
||||
|
||||
$pthreads_version = phpversion("pthreads");
|
||||
if(substr_count($pthreads_version, ".") < 2){
|
||||
$pthreads_version = "0.$pthreads_version";
|
||||
}
|
||||
if(version_compare($pthreads_version, "3.1.7-dev") < 0){
|
||||
$logger->critical("pthreads >= 3.1.7-dev is required, while you have $pthreads_version.");
|
||||
++$errors;
|
||||
}
|
||||
|
||||
if(extension_loaded("leveldb")){
|
||||
$leveldb_version = phpversion("leveldb");
|
||||
if(version_compare($leveldb_version, "0.2.1") < 0){
|
||||
$logger->critical("php-leveldb >= 0.2.1 is required, while you have $leveldb_version");
|
||||
++$errors;
|
||||
}
|
||||
}
|
||||
|
||||
if(extension_loaded("pocketmine")){
|
||||
if(version_compare(phpversion("pocketmine"), "0.0.1") < 0){
|
||||
$logger->critical("You have the native PocketMine extension, but your version is lower than 0.0.1.");
|
||||
++$errors;
|
||||
}elseif(version_compare(phpversion("pocketmine"), "0.0.4") > 0){
|
||||
$logger->critical("You have the native PocketMine extension, but your version is higher than 0.0.4.");
|
||||
++$errors;
|
||||
}
|
||||
}
|
||||
|
||||
if(extension_loaded("xdebug")){
|
||||
$logger->warning(PHP_EOL . PHP_EOL . PHP_EOL . "\tYou are running " . \pocketmine\NAME . " with xdebug enabled. This has a major impact on performance." . PHP_EOL . PHP_EOL);
|
||||
}
|
||||
|
||||
$extensions = [
|
||||
"bcmath" => "BC Math",
|
||||
"curl" => "cURL",
|
||||
"json" => "JSON",
|
||||
"mbstring" => "Multibyte String",
|
||||
"yaml" => "YAML",
|
||||
"sockets" => "Sockets",
|
||||
"zip" => "Zip",
|
||||
"zlib" => "Zlib"
|
||||
];
|
||||
|
||||
foreach($extensions as $ext => $name){
|
||||
if(!extension_loaded($ext)){
|
||||
$logger->critical("Unable to find the $name ($ext) extension.");
|
||||
++$errors;
|
||||
}
|
||||
}
|
||||
|
||||
if($errors > 0){
|
||||
$logger->critical("Please use the installer provided on the homepage, or recompile PHP again.");
|
||||
$exitCode = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
$gitHash = str_repeat("00", 20);
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
if(Utils::execute("git rev-parse HEAD", $out) === 0){
|
||||
$gitHash = trim($out);
|
||||
if(Utils::execute("git diff --quiet") === 1 or Utils::execute("git diff --cached --quiet") === 1){ //Locally-modified
|
||||
$gitHash .= "-dirty";
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$phar = new \Phar(\Phar::running(false));
|
||||
$meta = $phar->getMetadata();
|
||||
if(isset($meta["git"])){
|
||||
$gitHash = $meta["git"];
|
||||
}
|
||||
}
|
||||
|
||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||
|
||||
|
||||
@define("ENDIANNESS", (pack("d", 1) === "\77\360\0\0\0\0\0\0" ? Binary::BIG_ENDIAN : Binary::LITTLE_ENDIAN));
|
||||
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
|
||||
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors
|
||||
|
||||
|
||||
if(!file_exists(\pocketmine\DATA . "server.properties") and !isset($opts["no-wizard"])){
|
||||
$installer = new SetupWizard();
|
||||
if(!$installer->run()){
|
||||
@ -545,25 +244,22 @@ namespace pocketmine {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
$logger->warning("Non-packaged " . \pocketmine\NAME . " installation detected. Consider using a phar in production for better performance.");
|
||||
}
|
||||
|
||||
//TODO: move this to a Server field
|
||||
define('pocketmine\START_TIME', microtime(true));
|
||||
ThreadManager::init();
|
||||
new Server($autoloader, $logger, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
|
||||
|
||||
$logger->info("Stopping other threads");
|
||||
|
||||
$killer = new ServerKiller(8);
|
||||
$killer->start();
|
||||
$killer->start(PTHREADS_INHERIT_NONE);
|
||||
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
|
||||
|
||||
if(ThreadManager::getInstance()->stopAll() > 0){
|
||||
if(\pocketmine\DEBUG > 1){
|
||||
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
|
||||
}
|
||||
kill(getmypid());
|
||||
Utils::kill(getmypid());
|
||||
}
|
||||
}while(false);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -28,8 +28,11 @@ namespace pocketmine;
|
||||
*/
|
||||
abstract class Thread extends \Thread{
|
||||
|
||||
/** @var \ClassLoader */
|
||||
/** @var \ClassLoader|null */
|
||||
protected $classLoader;
|
||||
/** @var string|null */
|
||||
protected $composerAutoloaderPath;
|
||||
|
||||
protected $isKilled = false;
|
||||
|
||||
public function getClassLoader(){
|
||||
@ -37,6 +40,8 @@ abstract class Thread extends \Thread{
|
||||
}
|
||||
|
||||
public function setClassLoader(\ClassLoader $loader = null){
|
||||
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
|
||||
|
||||
if($loader === null){
|
||||
$loader = Server::getInstance()->getLoader();
|
||||
}
|
||||
@ -51,10 +56,8 @@ abstract class Thread extends \Thread{
|
||||
* (unless you are using a custom autoloader).
|
||||
*/
|
||||
public function registerClassLoader(){
|
||||
require(\pocketmine\PATH . "vendor/autoload.php");
|
||||
if(!interface_exists("ClassLoader", false)){
|
||||
require(\pocketmine\PATH . "src/spl/ClassLoader.php");
|
||||
require(\pocketmine\PATH . "src/spl/BaseClassLoader.php");
|
||||
if($this->composerAutoloaderPath !== null){
|
||||
require $this->composerAutoloaderPath;
|
||||
}
|
||||
if($this->classLoader !== null){
|
||||
$this->classLoader->register(false);
|
||||
@ -64,14 +67,10 @@ abstract class Thread extends \Thread{
|
||||
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
||||
ThreadManager::getInstance()->add($this);
|
||||
|
||||
if(!$this->isRunning() and !$this->isJoined() and !$this->isTerminated()){
|
||||
if($this->getClassLoader() === null){
|
||||
$this->setClassLoader();
|
||||
}
|
||||
return parent::start($options);
|
||||
if($this->getClassLoader() === null){
|
||||
$this->setClassLoader();
|
||||
}
|
||||
|
||||
return false;
|
||||
return parent::start($options);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -80,12 +79,9 @@ abstract class Thread extends \Thread{
|
||||
public function quit(){
|
||||
$this->isKilled = true;
|
||||
|
||||
$this->notify();
|
||||
|
||||
if(!$this->isJoined()){
|
||||
if(!$this->isTerminated()){
|
||||
$this->join();
|
||||
}
|
||||
$this->notify();
|
||||
$this->join();
|
||||
}
|
||||
|
||||
ThreadManager::getInstance()->remove($this);
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\utils\MainLogger;
|
||||
use function spl_object_hash;
|
||||
|
||||
class ThreadManager extends \Volatile{
|
||||
|
||||
@ -89,4 +90,4 @@ class ThreadManager extends \Volatile{
|
||||
|
||||
return $erroredThreads;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,8 +28,10 @@ namespace pocketmine;
|
||||
*/
|
||||
abstract class Worker extends \Worker{
|
||||
|
||||
/** @var \ClassLoader */
|
||||
/** @var \ClassLoader|null */
|
||||
protected $classLoader;
|
||||
/** @var string|null */
|
||||
protected $composerAutoloaderPath;
|
||||
|
||||
protected $isKilled = false;
|
||||
|
||||
@ -38,6 +40,8 @@ abstract class Worker extends \Worker{
|
||||
}
|
||||
|
||||
public function setClassLoader(\ClassLoader $loader = null){
|
||||
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
|
||||
|
||||
if($loader === null){
|
||||
$loader = Server::getInstance()->getLoader();
|
||||
}
|
||||
@ -52,10 +56,8 @@ abstract class Worker extends \Worker{
|
||||
* (unless you are using a custom autoloader).
|
||||
*/
|
||||
public function registerClassLoader(){
|
||||
require(\pocketmine\PATH . "vendor/autoload.php");
|
||||
if(!interface_exists("ClassLoader", false)){
|
||||
require(\pocketmine\PATH . "src/spl/ClassLoader.php");
|
||||
require(\pocketmine\PATH . "src/spl/BaseClassLoader.php");
|
||||
if($this->composerAutoloaderPath !== null){
|
||||
require $this->composerAutoloaderPath;
|
||||
}
|
||||
if($this->classLoader !== null){
|
||||
$this->classLoader->register(false);
|
||||
@ -65,14 +67,10 @@ abstract class Worker extends \Worker{
|
||||
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
||||
ThreadManager::getInstance()->add($this);
|
||||
|
||||
if(!$this->isRunning() and !$this->isJoined() and !$this->isTerminated()){
|
||||
if($this->getClassLoader() === null){
|
||||
$this->setClassLoader();
|
||||
}
|
||||
return parent::start($options);
|
||||
if($this->getClassLoader() === null){
|
||||
$this->setClassLoader();
|
||||
}
|
||||
|
||||
return false;
|
||||
return parent::start($options);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,16 +79,10 @@ abstract class Worker extends \Worker{
|
||||
public function quit(){
|
||||
$this->isKilled = true;
|
||||
|
||||
$this->notify();
|
||||
|
||||
if($this->isRunning()){
|
||||
$this->shutdown();
|
||||
while($this->unstack() !== null);
|
||||
$this->notify();
|
||||
$this->unstack();
|
||||
}elseif(!$this->isJoined()){
|
||||
if(!$this->isTerminated()){
|
||||
$this->join();
|
||||
}
|
||||
$this->shutdown();
|
||||
}
|
||||
|
||||
ThreadManager::getInstance()->remove($this);
|
||||
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class ActivatorRail extends Rail{
|
||||
class ActivatorRail extends RedstoneRail{
|
||||
|
||||
protected $id = self::ACTIVATOR_RAIL;
|
||||
|
||||
|
@ -81,5 +81,4 @@ class Air extends Transparent{
|
||||
public function getBlastResistance() : float{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\inventory\AnvilInventory;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
@ -55,17 +54,25 @@ class Anvil extends Fallable{
|
||||
return 6000;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0x0c;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
static $names = [
|
||||
self::TYPE_NORMAL => "Anvil",
|
||||
self::TYPE_SLIGHTLY_DAMAGED => "Slightly Damaged Anvil",
|
||||
self::TYPE_VERY_DAMAGED => "Very Damaged Anvil"
|
||||
];
|
||||
return $names[$this->meta & 0x0c] ?? "Anvil";
|
||||
return $names[$this->getVariant()] ?? "Anvil";
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
@ -102,17 +109,7 @@ class Anvil extends Fallable{
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$direction = ($player !== null ? $player->getDirection() : 0) & 0x03;
|
||||
$this->meta = ($this->meta & 0x0c) | $direction;
|
||||
$this->meta = $this->getVariant() | $direction;
|
||||
return $this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return [
|
||||
ItemFactory::get($this->getItemId(), $this->getDamage() & 0x0c, 1)
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
273
src/pocketmine/block/BaseRail.php
Normal file
273
src/pocketmine/block/BaseRail.php
Normal file
@ -0,0 +1,273 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use function array_map;
|
||||
use function array_reverse;
|
||||
use function array_search;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function implode;
|
||||
use function in_array;
|
||||
|
||||
abstract class BaseRail extends Flowable{
|
||||
|
||||
public const STRAIGHT_NORTH_SOUTH = 0;
|
||||
public const STRAIGHT_EAST_WEST = 1;
|
||||
public const ASCENDING_EAST = 2;
|
||||
public const ASCENDING_WEST = 3;
|
||||
public const ASCENDING_NORTH = 4;
|
||||
public const ASCENDING_SOUTH = 5;
|
||||
|
||||
private const ASCENDING_SIDES = [
|
||||
self::ASCENDING_NORTH => Vector3::SIDE_NORTH,
|
||||
self::ASCENDING_EAST => Vector3::SIDE_EAST,
|
||||
self::ASCENDING_SOUTH => Vector3::SIDE_SOUTH,
|
||||
self::ASCENDING_WEST => Vector3::SIDE_WEST
|
||||
];
|
||||
|
||||
protected const FLAG_ASCEND = 1 << 24; //used to indicate direction-up
|
||||
|
||||
protected const CONNECTIONS = [
|
||||
//straights
|
||||
self::STRAIGHT_NORTH_SOUTH => [
|
||||
Vector3::SIDE_NORTH,
|
||||
Vector3::SIDE_SOUTH
|
||||
],
|
||||
self::STRAIGHT_EAST_WEST => [
|
||||
Vector3::SIDE_EAST,
|
||||
Vector3::SIDE_WEST
|
||||
],
|
||||
|
||||
//ascending
|
||||
self::ASCENDING_EAST => [
|
||||
Vector3::SIDE_WEST,
|
||||
Vector3::SIDE_EAST | self::FLAG_ASCEND
|
||||
],
|
||||
self::ASCENDING_WEST => [
|
||||
Vector3::SIDE_EAST,
|
||||
Vector3::SIDE_WEST | self::FLAG_ASCEND
|
||||
],
|
||||
self::ASCENDING_NORTH => [
|
||||
Vector3::SIDE_SOUTH,
|
||||
Vector3::SIDE_NORTH | self::FLAG_ASCEND
|
||||
],
|
||||
self::ASCENDING_SOUTH => [
|
||||
Vector3::SIDE_NORTH,
|
||||
Vector3::SIDE_SOUTH | self::FLAG_ASCEND
|
||||
]
|
||||
];
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.7;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
if(!$blockReplace->getSide(Vector3::SIDE_DOWN)->isTransparent() and $this->getLevel()->setBlock($blockReplace, $this, true, true)){
|
||||
$this->tryReconnect();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected static function searchState(array $connections, array $lookup) : int{
|
||||
$meta = array_search($connections, $lookup, true);
|
||||
if($meta === false){
|
||||
$meta = array_search(array_reverse($connections), $lookup, true);
|
||||
}
|
||||
if($meta === false){
|
||||
throw new \InvalidArgumentException("No meta value matches connections " . implode(", ", array_map('\dechex', $connections)));
|
||||
}
|
||||
|
||||
return $meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a meta value for the rail with the given connections.
|
||||
*
|
||||
* @param array $connections
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @throws \InvalidArgumentException if no state matches the given connections
|
||||
*/
|
||||
protected function getMetaForState(array $connections) : int{
|
||||
return self::searchState($connections, self::CONNECTIONS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the connection directions of this rail (depending on the current block state)
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
abstract protected function getConnectionsForState() : array;
|
||||
|
||||
/**
|
||||
* Returns all the directions this rail is already connected in.
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
private function getConnectedDirections() : array{
|
||||
/** @var int[] $connections */
|
||||
$connections = [];
|
||||
|
||||
/** @var int $connection */
|
||||
foreach($this->getConnectionsForState() as $connection){
|
||||
$other = $this->getSide($connection & ~self::FLAG_ASCEND);
|
||||
$otherConnection = Vector3::getOppositeSide($connection & ~self::FLAG_ASCEND);
|
||||
|
||||
if(($connection & self::FLAG_ASCEND) !== 0){
|
||||
$other = $other->getSide(Vector3::SIDE_UP);
|
||||
|
||||
}elseif(!($other instanceof BaseRail)){ //check for rail sloping up to meet this one
|
||||
$other = $other->getSide(Vector3::SIDE_DOWN);
|
||||
$otherConnection |= self::FLAG_ASCEND;
|
||||
}
|
||||
|
||||
if(
|
||||
$other instanceof BaseRail and
|
||||
in_array($otherConnection, $other->getConnectionsForState(), true)
|
||||
){
|
||||
$connections[] = $connection;
|
||||
}
|
||||
}
|
||||
|
||||
return $connections;
|
||||
}
|
||||
|
||||
private function getPossibleConnectionDirections(array $constraints) : array{
|
||||
switch(count($constraints)){
|
||||
case 0:
|
||||
//No constraints, can connect in any direction
|
||||
$possible = [
|
||||
Vector3::SIDE_NORTH => true,
|
||||
Vector3::SIDE_SOUTH => true,
|
||||
Vector3::SIDE_WEST => true,
|
||||
Vector3::SIDE_EAST => true
|
||||
];
|
||||
foreach($possible as $p => $_){
|
||||
$possible[$p | self::FLAG_ASCEND] = true;
|
||||
}
|
||||
|
||||
return $possible;
|
||||
case 1:
|
||||
return $this->getPossibleConnectionDirectionsOneConstraint(array_shift($constraints));
|
||||
case 2:
|
||||
return [];
|
||||
default:
|
||||
throw new \InvalidArgumentException("Expected at most 2 constraints, got " . count($constraints));
|
||||
}
|
||||
}
|
||||
|
||||
protected function getPossibleConnectionDirectionsOneConstraint(int $constraint) : array{
|
||||
$opposite = Vector3::getOppositeSide($constraint & ~self::FLAG_ASCEND);
|
||||
|
||||
$possible = [$opposite => true];
|
||||
|
||||
if(($constraint & self::FLAG_ASCEND) === 0){
|
||||
//We can slope the other way if this connection isn't already a slope
|
||||
$possible[$opposite | self::FLAG_ASCEND] = true;
|
||||
}
|
||||
|
||||
return $possible;
|
||||
}
|
||||
|
||||
private function tryReconnect() : void{
|
||||
$thisConnections = $this->getConnectedDirections();
|
||||
$changed = false;
|
||||
|
||||
do{
|
||||
$possible = $this->getPossibleConnectionDirections($thisConnections);
|
||||
$continue = false;
|
||||
|
||||
foreach($possible as $thisSide => $_){
|
||||
$otherSide = Vector3::getOppositeSide($thisSide & ~self::FLAG_ASCEND);
|
||||
|
||||
$other = $this->getSide($thisSide & ~self::FLAG_ASCEND);
|
||||
|
||||
if(($thisSide & self::FLAG_ASCEND) !== 0){
|
||||
$other = $other->getSide(Vector3::SIDE_UP);
|
||||
|
||||
}elseif(!($other instanceof BaseRail)){ //check if other rails can slope up to meet this one
|
||||
$other = $other->getSide(Vector3::SIDE_DOWN);
|
||||
$otherSide |= self::FLAG_ASCEND;
|
||||
}
|
||||
|
||||
if(!($other instanceof BaseRail) or count($otherConnections = $other->getConnectedDirections()) >= 2){
|
||||
//we can only connect to a rail that has less than 2 connections
|
||||
continue;
|
||||
}
|
||||
|
||||
$otherPossible = $other->getPossibleConnectionDirections($otherConnections);
|
||||
|
||||
if(isset($otherPossible[$otherSide])){
|
||||
$otherConnections[] = $otherSide;
|
||||
$other->updateState($otherConnections);
|
||||
|
||||
$changed = true;
|
||||
$thisConnections[] = $thisSide;
|
||||
$continue = count($thisConnections) < 2;
|
||||
|
||||
break; //force recomputing possible directions, since this connection could invalidate others
|
||||
}
|
||||
}
|
||||
}while($continue);
|
||||
|
||||
if($changed){
|
||||
$this->updateState($thisConnections);
|
||||
}
|
||||
}
|
||||
|
||||
private function updateState(array $connections) : void{
|
||||
if(count($connections) === 1){
|
||||
$connections[] = Vector3::getOppositeSide($connections[0] & ~self::FLAG_ASCEND);
|
||||
}elseif(count($connections) !== 2){
|
||||
throw new \InvalidArgumentException("Expected exactly 2 connections, got " . count($connections));
|
||||
}
|
||||
|
||||
$this->meta = $this->getMetaForState($connections);
|
||||
$this->level->setBlock($this, $this, false, false); //avoid recursion
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() or (
|
||||
isset(self::ASCENDING_SIDES[$this->meta & 0x07]) and
|
||||
$this->getSide(self::ASCENDING_SIDES[$this->meta & 0x07])->isTransparent()
|
||||
)){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -23,9 +23,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\event\TranslationContainer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
@ -85,7 +85,7 @@ class Bed extends Transparent{
|
||||
|
||||
$this->getLevel()->setBlock($this, $this, false, false);
|
||||
|
||||
if(($other = $this->getOtherHalf()) !== null and !$other->isOccupied()){
|
||||
if(($other = $this->getOtherHalf()) !== null and $other->isOccupied() !== $occupied){
|
||||
$other->setOccupied($occupied);
|
||||
}
|
||||
}
|
||||
@ -176,7 +176,7 @@ class Bed extends Transparent{
|
||||
if(!$down->isTransparent()){
|
||||
$meta = (($player instanceof Player ? $player->getDirection() : 0) - 1) & 0x03;
|
||||
$next = $this->getSide(self::getOtherHalfSide($meta));
|
||||
if($next->canBeReplaced() === true and !$next->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||
if($next->canBeReplaced() and !$next->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||
$this->getLevel()->setBlock($blockReplace, BlockFactory::get($this->id, $meta), true, true);
|
||||
$this->getLevel()->setBlock($next, BlockFactory::get($this->id, $meta | self::BITFLAG_HEAD), true, true);
|
||||
|
||||
@ -190,30 +190,36 @@ class Bed extends Transparent{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onBreak(Item $item, Player $player = null) : bool{
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
|
||||
if(($other = $this->getOtherHalf()) !== null){
|
||||
$this->getLevel()->useBreakOn($other, $item, null, $player !== null); //make sure tiles get removed
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
if($this->isHeadPart()){
|
||||
$tile = $this->getLevel()->getTile($this);
|
||||
if($tile instanceof TileBed){
|
||||
return [
|
||||
ItemFactory::get($this->getItemId(), $tile->getColor(), 1)
|
||||
];
|
||||
}else{
|
||||
return [
|
||||
ItemFactory::get($this->getItemId(), 14, 1) //Red
|
||||
];
|
||||
}
|
||||
return [$this->getItem()];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getPickedItem() : Item{
|
||||
return $this->getItem();
|
||||
}
|
||||
|
||||
private function getItem() : Item{
|
||||
$tile = $this->getLevel()->getTile($this);
|
||||
if($tile instanceof TileBed){
|
||||
return ItemFactory::get($this->getItemId(), $tile->getColor());
|
||||
}
|
||||
|
||||
return ItemFactory::get($this->getItemId(), 14); //Red
|
||||
}
|
||||
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getAffectedBlocks() : array{
|
||||
if(($other = $this->getOtherHalf()) !== null){
|
||||
return [$this, $other];
|
||||
}
|
||||
|
||||
return parent::getAffectedBlocks();
|
||||
}
|
||||
}
|
||||
|
@ -48,5 +48,4 @@ class Bedrock extends Solid{
|
||||
public function isBreakable(Item $item) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use function mt_rand;
|
||||
|
||||
class Beetroot extends Crops{
|
||||
|
||||
@ -38,20 +39,20 @@ class Beetroot extends Crops{
|
||||
return "Beetroot Block";
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
if($this->meta >= 0x07){
|
||||
return [
|
||||
ItemFactory::get(Item::BEETROOT, 0, 1),
|
||||
ItemFactory::get(Item::BEETROOT),
|
||||
ItemFactory::get(Item::BEETROOT_SEEDS, 0, mt_rand(0, 3))
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
ItemFactory::get(Item::BEETROOT_SEEDS, 0, 1)
|
||||
ItemFactory::get(Item::BEETROOT_SEEDS)
|
||||
];
|
||||
}
|
||||
|
||||
public function getPickedItem() : Item{
|
||||
return ItemFactory::get(Item::BEETROOT_SEEDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,18 +27,20 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\item\enchantment\Enchantment;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\level\MovingObjectPosition;
|
||||
use pocketmine\level\Position;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\RayTraceResult;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\metadata\Metadatable;
|
||||
use pocketmine\metadata\MetadataValue;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\plugin\Plugin;
|
||||
use function array_merge;
|
||||
use function get_class;
|
||||
use const PHP_INT_MAX;
|
||||
|
||||
class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
@ -110,6 +112,14 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
return $this->itemId ?? $this->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @return int
|
||||
*/
|
||||
public function getRuntimeId() : int{
|
||||
return BlockFactory::toStaticRuntimeId($this->getId(), $this->getDamage());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
@ -195,8 +205,49 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function canBeBrokenWith(Item $item) : bool{
|
||||
return $this->getHardness() !== -1;
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the level of tool required to harvest this block (for normal blocks). When the tool type matches the
|
||||
* block's required tool type, the tool must have a harvest level greater than or equal to this value to be able to
|
||||
* successfully harvest the block.
|
||||
*
|
||||
* If the block requires a specific minimum tier of tiered tool, the minimum tier required should be returned.
|
||||
* Otherwise, 1 should be returned if a tool is required, 0 if not.
|
||||
*
|
||||
* @see Item::getBlockToolHarvestLevel()
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getToolHarvestLevel() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the specified item is the proper tool to use for breaking this block. This checks tool type and
|
||||
* harvest level requirement.
|
||||
*
|
||||
* In most cases this is also used to determine whether block drops should be created or not, except in some
|
||||
* special cases such as vines.
|
||||
*
|
||||
* @param Item $tool
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isCompatibleWithTool(Item $tool) : bool{
|
||||
if($this->getHardness() < 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
$toolType = $this->getToolType();
|
||||
$harvestLevel = $this->getToolHarvestLevel();
|
||||
return $toolType === BlockToolType::TYPE_NONE or $harvestLevel === 0 or (
|
||||
($toolType & $tool->getBlockToolType()) !== 0 and $tool->getBlockToolHarvestLevel() >= $harvestLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -218,46 +269,32 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @param Item $item
|
||||
*
|
||||
* @return float
|
||||
* @throws \InvalidArgumentException if the item efficiency is not a positive number
|
||||
*/
|
||||
public function getBreakTime(Item $item) : float{
|
||||
$base = $this->getHardness() * 1.5;
|
||||
if($this->canBeBrokenWith($item)){
|
||||
if($this->getToolType() === Tool::TYPE_SHEARS and $item->isShears()){
|
||||
$base /= 15;
|
||||
}elseif(
|
||||
($this->getToolType() === Tool::TYPE_PICKAXE and ($tier = $item->isPickaxe()) !== false) or
|
||||
($this->getToolType() === Tool::TYPE_AXE and ($tier = $item->isAxe()) !== false) or
|
||||
($this->getToolType() === Tool::TYPE_SHOVEL and ($tier = $item->isShovel()) !== false)
|
||||
){
|
||||
switch($tier){
|
||||
case Tool::TIER_WOODEN:
|
||||
$base /= 2;
|
||||
break;
|
||||
case Tool::TIER_STONE:
|
||||
$base /= 4;
|
||||
break;
|
||||
case Tool::TIER_IRON:
|
||||
$base /= 6;
|
||||
break;
|
||||
case Tool::TIER_DIAMOND:
|
||||
$base /= 8;
|
||||
break;
|
||||
case Tool::TIER_GOLD:
|
||||
$base /= 12;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$base = $this->getHardness();
|
||||
if($this->isCompatibleWithTool($item)){
|
||||
$base *= 1.5;
|
||||
}else{
|
||||
$base *= 3.33;
|
||||
$base *= 5;
|
||||
}
|
||||
|
||||
if($item->isSword()){
|
||||
$base /= 1.5;
|
||||
$efficiency = $item->getMiningEfficiency($this);
|
||||
if($efficiency <= 0){
|
||||
throw new \InvalidArgumentException(get_class($item) . " has invalid mining efficiency: expected >= 0, got $efficiency");
|
||||
}
|
||||
|
||||
$base /= $efficiency;
|
||||
|
||||
return $base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this block or a block immediately adjacent to it changes state.
|
||||
*/
|
||||
public function onNearbyBlockChange() : void{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether random block updates will be done on this block.
|
||||
@ -269,14 +306,18 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires a block update on the Block
|
||||
*
|
||||
* @param int $type
|
||||
*
|
||||
* @return bool|int
|
||||
* Called when this block is randomly updated due to chunk ticking.
|
||||
* WARNING: This will not be called if ticksRandomly() does not return true!
|
||||
*/
|
||||
public function onUpdate(int $type){
|
||||
return false;
|
||||
public function onRandomTick() : void{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this block is updated by the delayed blockupdate scheduler in the level.
|
||||
*/
|
||||
public function onScheduledUpdate() : void{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -299,14 +340,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
return 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @return float
|
||||
*/
|
||||
public function getResistance() : float{
|
||||
return $this->getBlastResistance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the block's resistance to explosions. Usually 5x hardness.
|
||||
* @return float
|
||||
@ -315,13 +348,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
return $this->getHardness() * 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
@ -420,11 +446,77 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @return Item[]
|
||||
*/
|
||||
public function getDrops(Item $item) : array{
|
||||
if($this->isCompatibleWithTool($item)){
|
||||
if($this->isAffectedBySilkTouch() and $item->hasEnchantment(Enchantment::SILK_TOUCH)){
|
||||
return $this->getSilkTouchDrops($item);
|
||||
}
|
||||
|
||||
return $this->getDropsForCompatibleTool($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of Items to be dropped when the block is broken using the correct tool type.
|
||||
*
|
||||
* @param Item $item
|
||||
*
|
||||
* @return Item[]
|
||||
*/
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get($this->getItemId(), $this->getVariant(), 1)
|
||||
ItemFactory::get($this->getItemId(), $this->getVariant())
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of Items to be dropped when the block is broken using a compatible Silk Touch-enchanted tool.
|
||||
*
|
||||
* @param Item $item
|
||||
*
|
||||
* @return Item[]
|
||||
*/
|
||||
public function getSilkTouchDrops(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get($this->getItemId(), $this->getVariant())
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how much XP will be dropped by breaking this block with the given item.
|
||||
*
|
||||
* @param Item $item
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getXpDropForTool(Item $item) : int{
|
||||
if($item->hasEnchantment(Enchantment::SILK_TOUCH) or !$this->isCompatibleWithTool($item)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $this->getXpDropAmount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how much XP this block will drop when broken with an appropriate tool.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getXpDropAmount() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether Silk Touch enchanted tools will cause this block to drop as itself. Since most blocks drop
|
||||
* themselves anyway, this is implicitly true.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the item that players will equip when middle-clicking on this block.
|
||||
* @return Item
|
||||
@ -441,6 +533,50 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the chance that the block will catch fire from nearby fire sources. Higher values lead to faster catching
|
||||
* fire.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getFlameEncouragement() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base flammability of this block. Higher values lead to the block burning away more quickly.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getFlammability() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether fire lit on this block will burn indefinitely.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function burnsForever() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this block can catch fire.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isFlammable() : bool{
|
||||
return $this->getFlammability() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this block is burned away by being on fire.
|
||||
*/
|
||||
public function onIncinerate() : void{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Block on the side $side, works like Vector3::getSide()
|
||||
*
|
||||
@ -449,7 +585,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
*
|
||||
* @return Block
|
||||
*/
|
||||
public function getSide($side, $step = 1){
|
||||
public function getSide(int $side, int $step = 1){
|
||||
if($this->isValid()){
|
||||
return $this->getLevel()->getBlock(Vector3::getSide($side, $step));
|
||||
}
|
||||
@ -486,6 +622,16 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of blocks that this block is part of. In most cases, only contains the block itself, but in cases
|
||||
* such as double plants, beds and doors, will contain both halves.
|
||||
*
|
||||
* @return Block[]
|
||||
*/
|
||||
public function getAffectedBlocks() : array{
|
||||
return [$this];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
@ -501,9 +647,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @return bool
|
||||
*/
|
||||
public function collidesWithBB(AxisAlignedBB $bb) : bool{
|
||||
$bbs = $this->getCollisionBoxes();
|
||||
|
||||
foreach($bbs as $bb2){
|
||||
foreach($this->getCollisionBoxes() as $bb2){
|
||||
if($bb->intersectsWith($bb2)){
|
||||
return true;
|
||||
}
|
||||
@ -578,15 +722,15 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @param Vector3 $pos1
|
||||
* @param Vector3 $pos2
|
||||
*
|
||||
* @return MovingObjectPosition|null
|
||||
* @return RayTraceResult|null
|
||||
*/
|
||||
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?MovingObjectPosition{
|
||||
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{
|
||||
$bbs = $this->getCollisionBoxes();
|
||||
if(empty($bbs)){
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var MovingObjectPosition|null $currentHit */
|
||||
/** @var RayTraceResult|null $currentHit */
|
||||
$currentHit = null;
|
||||
/** @var int|float $currentDistance */
|
||||
$currentDistance = PHP_INT_MAX;
|
||||
@ -604,40 +748,34 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
}
|
||||
}
|
||||
|
||||
if($currentHit !== null){
|
||||
$currentHit->blockX = $this->x;
|
||||
$currentHit->blockY = $this->y;
|
||||
$currentHit->blockZ = $this->z;
|
||||
}
|
||||
|
||||
return $currentHit;
|
||||
}
|
||||
|
||||
public function setMetadata(string $metadataKey, MetadataValue $newMetadataValue){
|
||||
if($this->getLevel() instanceof Level){
|
||||
$this->getLevel()->getBlockMetadata()->setMetadata($this, $metadataKey, $newMetadataValue);
|
||||
if($this->isValid()){
|
||||
$this->level->getBlockMetadata()->setMetadata($this, $metadataKey, $newMetadataValue);
|
||||
}
|
||||
}
|
||||
|
||||
public function getMetadata(string $metadataKey){
|
||||
if($this->getLevel() instanceof Level){
|
||||
return $this->getLevel()->getBlockMetadata()->getMetadata($this, $metadataKey);
|
||||
if($this->isValid()){
|
||||
return $this->level->getBlockMetadata()->getMetadata($this, $metadataKey);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function hasMetadata(string $metadataKey) : bool{
|
||||
if($this->getLevel() instanceof Level){
|
||||
return $this->getLevel()->getBlockMetadata()->hasMetadata($this, $metadataKey);
|
||||
if($this->isValid()){
|
||||
return $this->level->getBlockMetadata()->hasMetadata($this, $metadataKey);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function removeMetadata(string $metadataKey, Plugin $owningPlugin){
|
||||
if($this->getLevel() instanceof Level){
|
||||
$this->getLevel()->getBlockMetadata()->removeMetadata($this, $metadataKey, $owningPlugin);
|
||||
if($this->isValid()){
|
||||
$this->level->getBlockMetadata()->removeMetadata($this, $metadataKey, $owningPlugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,13 +25,15 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Position;
|
||||
use function file_get_contents;
|
||||
use function json_decode;
|
||||
use function max;
|
||||
use function min;
|
||||
|
||||
/**
|
||||
* Manages block registration and instance creation
|
||||
*/
|
||||
class BlockFactory{
|
||||
/** @var \SplFixedArray<Block> */
|
||||
private static $list = null;
|
||||
/** @var \SplFixedArray<Block> */
|
||||
private static $fullList = null;
|
||||
|
||||
@ -50,284 +52,292 @@ class BlockFactory{
|
||||
/** @var \SplFixedArray<float> */
|
||||
public static $blastResistance = null;
|
||||
|
||||
/** @var int[] */
|
||||
public static $staticRuntimeIdMap = [];
|
||||
|
||||
/** @var int[] */
|
||||
public static $legacyIdMap = [];
|
||||
|
||||
/** @var int */
|
||||
private static $lastRuntimeId = 0;
|
||||
|
||||
/**
|
||||
* Initializes the block factory. By default this is called only once on server start, however you may wish to use
|
||||
* this if you need to reset the block factory back to its original defaults for whatever reason.
|
||||
*
|
||||
* @param bool $force
|
||||
*/
|
||||
public static function init(bool $force = false) : void{
|
||||
if(self::$list === null or $force){
|
||||
self::$list = new \SplFixedArray(256);
|
||||
self::$fullList = new \SplFixedArray(4096);
|
||||
public static function init() : void{
|
||||
self::$fullList = new \SplFixedArray(4096);
|
||||
|
||||
self::$light = new \SplFixedArray(256);
|
||||
self::$lightFilter = new \SplFixedArray(256);
|
||||
self::$solid = new \SplFixedArray(256);
|
||||
self::$hardness = new \SplFixedArray(256);
|
||||
self::$transparent = new \SplFixedArray(256);
|
||||
self::$diffusesSkyLight = new \SplFixedArray(256);
|
||||
self::$blastResistance = new \SplFixedArray(256);
|
||||
self::$light = new \SplFixedArray(256);
|
||||
self::$lightFilter = new \SplFixedArray(256);
|
||||
self::$solid = new \SplFixedArray(256);
|
||||
self::$hardness = new \SplFixedArray(256);
|
||||
self::$transparent = new \SplFixedArray(256);
|
||||
self::$diffusesSkyLight = new \SplFixedArray(256);
|
||||
self::$blastResistance = new \SplFixedArray(256);
|
||||
|
||||
self::registerBlock(new Air());
|
||||
self::registerBlock(new Stone());
|
||||
self::registerBlock(new Grass());
|
||||
self::registerBlock(new Dirt());
|
||||
self::registerBlock(new Cobblestone());
|
||||
self::registerBlock(new Planks());
|
||||
self::registerBlock(new Sapling());
|
||||
self::registerBlock(new Bedrock());
|
||||
self::registerBlock(new Water());
|
||||
self::registerBlock(new StillWater());
|
||||
self::registerBlock(new Lava());
|
||||
self::registerBlock(new StillLava());
|
||||
self::registerBlock(new Sand());
|
||||
self::registerBlock(new Gravel());
|
||||
self::registerBlock(new GoldOre());
|
||||
self::registerBlock(new IronOre());
|
||||
self::registerBlock(new CoalOre());
|
||||
self::registerBlock(new Wood());
|
||||
self::registerBlock(new Leaves());
|
||||
self::registerBlock(new Sponge());
|
||||
self::registerBlock(new Glass());
|
||||
self::registerBlock(new LapisOre());
|
||||
self::registerBlock(new Lapis());
|
||||
//TODO: DISPENSER
|
||||
self::registerBlock(new Sandstone());
|
||||
self::registerBlock(new NoteBlock());
|
||||
self::registerBlock(new Bed());
|
||||
self::registerBlock(new PoweredRail());
|
||||
self::registerBlock(new DetectorRail());
|
||||
//TODO: STICKY_PISTON
|
||||
self::registerBlock(new Cobweb());
|
||||
self::registerBlock(new TallGrass());
|
||||
self::registerBlock(new DeadBush());
|
||||
//TODO: PISTON
|
||||
//TODO: PISTONARMCOLLISION
|
||||
self::registerBlock(new Wool());
|
||||
self::registerBlock(new Air());
|
||||
self::registerBlock(new Stone());
|
||||
self::registerBlock(new Grass());
|
||||
self::registerBlock(new Dirt());
|
||||
self::registerBlock(new Cobblestone());
|
||||
self::registerBlock(new Planks());
|
||||
self::registerBlock(new Sapling());
|
||||
self::registerBlock(new Bedrock());
|
||||
self::registerBlock(new Water());
|
||||
self::registerBlock(new StillWater());
|
||||
self::registerBlock(new Lava());
|
||||
self::registerBlock(new StillLava());
|
||||
self::registerBlock(new Sand());
|
||||
self::registerBlock(new Gravel());
|
||||
self::registerBlock(new GoldOre());
|
||||
self::registerBlock(new IronOre());
|
||||
self::registerBlock(new CoalOre());
|
||||
self::registerBlock(new Wood());
|
||||
self::registerBlock(new Leaves());
|
||||
self::registerBlock(new Sponge());
|
||||
self::registerBlock(new Glass());
|
||||
self::registerBlock(new LapisOre());
|
||||
self::registerBlock(new Lapis());
|
||||
//TODO: DISPENSER
|
||||
self::registerBlock(new Sandstone());
|
||||
self::registerBlock(new NoteBlock());
|
||||
self::registerBlock(new Bed());
|
||||
self::registerBlock(new PoweredRail());
|
||||
self::registerBlock(new DetectorRail());
|
||||
//TODO: STICKY_PISTON
|
||||
self::registerBlock(new Cobweb());
|
||||
self::registerBlock(new TallGrass());
|
||||
self::registerBlock(new DeadBush());
|
||||
//TODO: PISTON
|
||||
//TODO: PISTONARMCOLLISION
|
||||
self::registerBlock(new Wool());
|
||||
|
||||
self::registerBlock(new Dandelion());
|
||||
self::registerBlock(new Flower());
|
||||
self::registerBlock(new BrownMushroom());
|
||||
self::registerBlock(new RedMushroom());
|
||||
self::registerBlock(new Gold());
|
||||
self::registerBlock(new Iron());
|
||||
self::registerBlock(new DoubleStoneSlab());
|
||||
self::registerBlock(new StoneSlab());
|
||||
self::registerBlock(new Bricks());
|
||||
self::registerBlock(new TNT());
|
||||
self::registerBlock(new Bookshelf());
|
||||
self::registerBlock(new MossyCobblestone());
|
||||
self::registerBlock(new Obsidian());
|
||||
self::registerBlock(new Torch());
|
||||
self::registerBlock(new Fire());
|
||||
self::registerBlock(new MonsterSpawner());
|
||||
self::registerBlock(new WoodenStairs(Block::OAK_STAIRS, 0, "Oak Stairs"));
|
||||
self::registerBlock(new Chest());
|
||||
//TODO: REDSTONE_WIRE
|
||||
self::registerBlock(new DiamondOre());
|
||||
self::registerBlock(new Diamond());
|
||||
self::registerBlock(new CraftingTable());
|
||||
self::registerBlock(new Wheat());
|
||||
self::registerBlock(new Farmland());
|
||||
self::registerBlock(new Furnace());
|
||||
self::registerBlock(new BurningFurnace());
|
||||
self::registerBlock(new SignPost());
|
||||
self::registerBlock(new WoodenDoor(Block::OAK_DOOR_BLOCK, 0, "Oak Door", Item::OAK_DOOR));
|
||||
self::registerBlock(new Ladder());
|
||||
self::registerBlock(new Rail());
|
||||
self::registerBlock(new CobblestoneStairs());
|
||||
self::registerBlock(new WallSign());
|
||||
self::registerBlock(new Lever());
|
||||
self::registerBlock(new StonePressurePlate());
|
||||
self::registerBlock(new IronDoor());
|
||||
self::registerBlock(new WoodenPressurePlate());
|
||||
self::registerBlock(new RedstoneOre());
|
||||
self::registerBlock(new GlowingRedstoneOre());
|
||||
self::registerBlock(new RedstoneTorchUnlit());
|
||||
self::registerBlock(new RedstoneTorch());
|
||||
self::registerBlock(new StoneButton());
|
||||
self::registerBlock(new SnowLayer());
|
||||
self::registerBlock(new Ice());
|
||||
self::registerBlock(new Snow());
|
||||
self::registerBlock(new Cactus());
|
||||
self::registerBlock(new Clay());
|
||||
self::registerBlock(new Sugarcane());
|
||||
//TODO: JUKEBOX
|
||||
self::registerBlock(new WoodenFence());
|
||||
self::registerBlock(new Pumpkin());
|
||||
self::registerBlock(new Netherrack());
|
||||
self::registerBlock(new SoulSand());
|
||||
self::registerBlock(new Glowstone());
|
||||
//TODO: PORTAL
|
||||
self::registerBlock(new LitPumpkin());
|
||||
self::registerBlock(new Cake());
|
||||
//TODO: REPEATER_BLOCK
|
||||
//TODO: POWERED_REPEATER
|
||||
//TODO: INVISIBLEBEDROCK
|
||||
self::registerBlock(new Trapdoor());
|
||||
//TODO: MONSTER_EGG
|
||||
self::registerBlock(new StoneBricks());
|
||||
self::registerBlock(new BrownMushroomBlock());
|
||||
self::registerBlock(new RedMushroomBlock());
|
||||
self::registerBlock(new IronBars());
|
||||
self::registerBlock(new GlassPane());
|
||||
self::registerBlock(new Melon());
|
||||
self::registerBlock(new PumpkinStem());
|
||||
self::registerBlock(new MelonStem());
|
||||
self::registerBlock(new Vine());
|
||||
self::registerBlock(new FenceGate(Block::OAK_FENCE_GATE, 0, "Oak Fence Gate"));
|
||||
self::registerBlock(new BrickStairs());
|
||||
self::registerBlock(new StoneBrickStairs());
|
||||
self::registerBlock(new Mycelium());
|
||||
self::registerBlock(new WaterLily());
|
||||
self::registerBlock(new NetherBrick(Block::NETHER_BRICK_BLOCK, 0, "Nether Bricks"));
|
||||
self::registerBlock(new NetherBrickFence());
|
||||
self::registerBlock(new NetherBrickStairs());
|
||||
self::registerBlock(new NetherWartPlant());
|
||||
self::registerBlock(new EnchantingTable());
|
||||
self::registerBlock(new BrewingStand());
|
||||
//TODO: CAULDRON_BLOCK
|
||||
//TODO: END_PORTAL
|
||||
self::registerBlock(new EndPortalFrame());
|
||||
self::registerBlock(new EndStone());
|
||||
//TODO: DRAGON_EGG
|
||||
self::registerBlock(new RedstoneLamp());
|
||||
self::registerBlock(new LitRedstoneLamp());
|
||||
//TODO: DROPPER
|
||||
self::registerBlock(new ActivatorRail());
|
||||
self::registerBlock(new CocoaBlock());
|
||||
self::registerBlock(new SandstoneStairs());
|
||||
self::registerBlock(new EmeraldOre());
|
||||
self::registerBlock(new EnderChest());
|
||||
self::registerBlock(new TripwireHook());
|
||||
self::registerBlock(new Tripwire());
|
||||
self::registerBlock(new Emerald());
|
||||
self::registerBlock(new WoodenStairs(Block::SPRUCE_STAIRS, 0, "Spruce Stairs"));
|
||||
self::registerBlock(new WoodenStairs(Block::BIRCH_STAIRS, 0, "Birch Stairs"));
|
||||
self::registerBlock(new WoodenStairs(Block::JUNGLE_STAIRS, 0, "Jungle Stairs"));
|
||||
//TODO: COMMAND_BLOCK
|
||||
//TODO: BEACON
|
||||
self::registerBlock(new CobblestoneWall());
|
||||
self::registerBlock(new FlowerPot());
|
||||
self::registerBlock(new Carrot());
|
||||
self::registerBlock(new Potato());
|
||||
self::registerBlock(new WoodenButton());
|
||||
self::registerBlock(new Skull());
|
||||
self::registerBlock(new Anvil());
|
||||
self::registerBlock(new TrappedChest());
|
||||
self::registerBlock(new WeightedPressurePlateLight());
|
||||
self::registerBlock(new WeightedPressurePlateHeavy());
|
||||
//TODO: COMPARATOR_BLOCK
|
||||
//TODO: POWERED_COMPARATOR
|
||||
self::registerBlock(new DaylightSensor());
|
||||
self::registerBlock(new Redstone());
|
||||
self::registerBlock(new NetherQuartzOre());
|
||||
//TODO: HOPPER_BLOCK
|
||||
self::registerBlock(new Quartz());
|
||||
self::registerBlock(new QuartzStairs());
|
||||
self::registerBlock(new DoubleWoodenSlab());
|
||||
self::registerBlock(new WoodenSlab());
|
||||
self::registerBlock(new StainedClay());
|
||||
self::registerBlock(new StainedGlassPane());
|
||||
self::registerBlock(new Leaves2());
|
||||
self::registerBlock(new Wood2());
|
||||
self::registerBlock(new WoodenStairs(Block::ACACIA_STAIRS, 0, "Acacia Stairs"));
|
||||
self::registerBlock(new WoodenStairs(Block::DARK_OAK_STAIRS, 0, "Dark Oak Stairs"));
|
||||
//TODO: SLIME
|
||||
self::registerBlock(new Dandelion());
|
||||
self::registerBlock(new Flower());
|
||||
self::registerBlock(new BrownMushroom());
|
||||
self::registerBlock(new RedMushroom());
|
||||
self::registerBlock(new Gold());
|
||||
self::registerBlock(new Iron());
|
||||
self::registerBlock(new DoubleStoneSlab());
|
||||
self::registerBlock(new StoneSlab());
|
||||
self::registerBlock(new Bricks());
|
||||
self::registerBlock(new TNT());
|
||||
self::registerBlock(new Bookshelf());
|
||||
self::registerBlock(new MossyCobblestone());
|
||||
self::registerBlock(new Obsidian());
|
||||
self::registerBlock(new Torch());
|
||||
self::registerBlock(new Fire());
|
||||
self::registerBlock(new MonsterSpawner());
|
||||
self::registerBlock(new WoodenStairs(Block::OAK_STAIRS, 0, "Oak Stairs"));
|
||||
self::registerBlock(new Chest());
|
||||
//TODO: REDSTONE_WIRE
|
||||
self::registerBlock(new DiamondOre());
|
||||
self::registerBlock(new Diamond());
|
||||
self::registerBlock(new CraftingTable());
|
||||
self::registerBlock(new Wheat());
|
||||
self::registerBlock(new Farmland());
|
||||
self::registerBlock(new Furnace());
|
||||
self::registerBlock(new BurningFurnace());
|
||||
self::registerBlock(new SignPost());
|
||||
self::registerBlock(new WoodenDoor(Block::OAK_DOOR_BLOCK, 0, "Oak Door", Item::OAK_DOOR));
|
||||
self::registerBlock(new Ladder());
|
||||
self::registerBlock(new Rail());
|
||||
self::registerBlock(new CobblestoneStairs());
|
||||
self::registerBlock(new WallSign());
|
||||
self::registerBlock(new Lever());
|
||||
self::registerBlock(new StonePressurePlate());
|
||||
self::registerBlock(new IronDoor());
|
||||
self::registerBlock(new WoodenPressurePlate());
|
||||
self::registerBlock(new RedstoneOre());
|
||||
self::registerBlock(new GlowingRedstoneOre());
|
||||
self::registerBlock(new RedstoneTorchUnlit());
|
||||
self::registerBlock(new RedstoneTorch());
|
||||
self::registerBlock(new StoneButton());
|
||||
self::registerBlock(new SnowLayer());
|
||||
self::registerBlock(new Ice());
|
||||
self::registerBlock(new Snow());
|
||||
self::registerBlock(new Cactus());
|
||||
self::registerBlock(new Clay());
|
||||
self::registerBlock(new Sugarcane());
|
||||
//TODO: JUKEBOX
|
||||
self::registerBlock(new WoodenFence());
|
||||
self::registerBlock(new Pumpkin());
|
||||
self::registerBlock(new Netherrack());
|
||||
self::registerBlock(new SoulSand());
|
||||
self::registerBlock(new Glowstone());
|
||||
//TODO: PORTAL
|
||||
self::registerBlock(new LitPumpkin());
|
||||
self::registerBlock(new Cake());
|
||||
//TODO: REPEATER_BLOCK
|
||||
//TODO: POWERED_REPEATER
|
||||
self::registerBlock(new InvisibleBedrock());
|
||||
self::registerBlock(new Trapdoor());
|
||||
//TODO: MONSTER_EGG
|
||||
self::registerBlock(new StoneBricks());
|
||||
self::registerBlock(new BrownMushroomBlock());
|
||||
self::registerBlock(new RedMushroomBlock());
|
||||
self::registerBlock(new IronBars());
|
||||
self::registerBlock(new GlassPane());
|
||||
self::registerBlock(new Melon());
|
||||
self::registerBlock(new PumpkinStem());
|
||||
self::registerBlock(new MelonStem());
|
||||
self::registerBlock(new Vine());
|
||||
self::registerBlock(new FenceGate(Block::OAK_FENCE_GATE, 0, "Oak Fence Gate"));
|
||||
self::registerBlock(new BrickStairs());
|
||||
self::registerBlock(new StoneBrickStairs());
|
||||
self::registerBlock(new Mycelium());
|
||||
self::registerBlock(new WaterLily());
|
||||
self::registerBlock(new NetherBrick(Block::NETHER_BRICK_BLOCK, 0, "Nether Bricks"));
|
||||
self::registerBlock(new NetherBrickFence());
|
||||
self::registerBlock(new NetherBrickStairs());
|
||||
self::registerBlock(new NetherWartPlant());
|
||||
self::registerBlock(new EnchantingTable());
|
||||
self::registerBlock(new BrewingStand());
|
||||
//TODO: CAULDRON_BLOCK
|
||||
//TODO: END_PORTAL
|
||||
self::registerBlock(new EndPortalFrame());
|
||||
self::registerBlock(new EndStone());
|
||||
//TODO: DRAGON_EGG
|
||||
self::registerBlock(new RedstoneLamp());
|
||||
self::registerBlock(new LitRedstoneLamp());
|
||||
//TODO: DROPPER
|
||||
self::registerBlock(new ActivatorRail());
|
||||
self::registerBlock(new CocoaBlock());
|
||||
self::registerBlock(new SandstoneStairs());
|
||||
self::registerBlock(new EmeraldOre());
|
||||
self::registerBlock(new EnderChest());
|
||||
self::registerBlock(new TripwireHook());
|
||||
self::registerBlock(new Tripwire());
|
||||
self::registerBlock(new Emerald());
|
||||
self::registerBlock(new WoodenStairs(Block::SPRUCE_STAIRS, 0, "Spruce Stairs"));
|
||||
self::registerBlock(new WoodenStairs(Block::BIRCH_STAIRS, 0, "Birch Stairs"));
|
||||
self::registerBlock(new WoodenStairs(Block::JUNGLE_STAIRS, 0, "Jungle Stairs"));
|
||||
//TODO: COMMAND_BLOCK
|
||||
//TODO: BEACON
|
||||
self::registerBlock(new CobblestoneWall());
|
||||
self::registerBlock(new FlowerPot());
|
||||
self::registerBlock(new Carrot());
|
||||
self::registerBlock(new Potato());
|
||||
self::registerBlock(new WoodenButton());
|
||||
self::registerBlock(new Skull());
|
||||
self::registerBlock(new Anvil());
|
||||
self::registerBlock(new TrappedChest());
|
||||
self::registerBlock(new WeightedPressurePlateLight());
|
||||
self::registerBlock(new WeightedPressurePlateHeavy());
|
||||
//TODO: COMPARATOR_BLOCK
|
||||
//TODO: POWERED_COMPARATOR
|
||||
self::registerBlock(new DaylightSensor());
|
||||
self::registerBlock(new Redstone());
|
||||
self::registerBlock(new NetherQuartzOre());
|
||||
//TODO: HOPPER_BLOCK
|
||||
self::registerBlock(new Quartz());
|
||||
self::registerBlock(new QuartzStairs());
|
||||
self::registerBlock(new DoubleWoodenSlab());
|
||||
self::registerBlock(new WoodenSlab());
|
||||
self::registerBlock(new StainedClay());
|
||||
self::registerBlock(new StainedGlassPane());
|
||||
self::registerBlock(new Leaves2());
|
||||
self::registerBlock(new Wood2());
|
||||
self::registerBlock(new WoodenStairs(Block::ACACIA_STAIRS, 0, "Acacia Stairs"));
|
||||
self::registerBlock(new WoodenStairs(Block::DARK_OAK_STAIRS, 0, "Dark Oak Stairs"));
|
||||
//TODO: SLIME
|
||||
|
||||
self::registerBlock(new IronTrapdoor());
|
||||
self::registerBlock(new Prismarine());
|
||||
self::registerBlock(new SeaLantern());
|
||||
self::registerBlock(new HayBale());
|
||||
self::registerBlock(new Carpet());
|
||||
self::registerBlock(new HardenedClay());
|
||||
self::registerBlock(new Coal());
|
||||
self::registerBlock(new PackedIce());
|
||||
self::registerBlock(new DoublePlant());
|
||||
self::registerBlock(new StandingBanner());
|
||||
self::registerBlock(new WallBanner());
|
||||
//TODO: DAYLIGHT_DETECTOR_INVERTED
|
||||
self::registerBlock(new RedSandstone());
|
||||
self::registerBlock(new RedSandstoneStairs());
|
||||
self::registerBlock(new DoubleStoneSlab2());
|
||||
self::registerBlock(new StoneSlab2());
|
||||
self::registerBlock(new FenceGate(Block::SPRUCE_FENCE_GATE, 0, "Spruce Fence Gate"));
|
||||
self::registerBlock(new FenceGate(Block::BIRCH_FENCE_GATE, 0, "Birch Fence Gate"));
|
||||
self::registerBlock(new FenceGate(Block::JUNGLE_FENCE_GATE, 0, "Jungle Fence Gate"));
|
||||
self::registerBlock(new FenceGate(Block::DARK_OAK_FENCE_GATE, 0, "Dark Oak Fence Gate"));
|
||||
self::registerBlock(new FenceGate(Block::ACACIA_FENCE_GATE, 0, "Acacia Fence Gate"));
|
||||
//TODO: REPEATING_COMMAND_BLOCK
|
||||
//TODO: CHAIN_COMMAND_BLOCK
|
||||
self::registerBlock(new IronTrapdoor());
|
||||
self::registerBlock(new Prismarine());
|
||||
self::registerBlock(new SeaLantern());
|
||||
self::registerBlock(new HayBale());
|
||||
self::registerBlock(new Carpet());
|
||||
self::registerBlock(new HardenedClay());
|
||||
self::registerBlock(new Coal());
|
||||
self::registerBlock(new PackedIce());
|
||||
self::registerBlock(new DoublePlant());
|
||||
self::registerBlock(new StandingBanner());
|
||||
self::registerBlock(new WallBanner());
|
||||
//TODO: DAYLIGHT_DETECTOR_INVERTED
|
||||
self::registerBlock(new RedSandstone());
|
||||
self::registerBlock(new RedSandstoneStairs());
|
||||
self::registerBlock(new DoubleStoneSlab2());
|
||||
self::registerBlock(new StoneSlab2());
|
||||
self::registerBlock(new FenceGate(Block::SPRUCE_FENCE_GATE, 0, "Spruce Fence Gate"));
|
||||
self::registerBlock(new FenceGate(Block::BIRCH_FENCE_GATE, 0, "Birch Fence Gate"));
|
||||
self::registerBlock(new FenceGate(Block::JUNGLE_FENCE_GATE, 0, "Jungle Fence Gate"));
|
||||
self::registerBlock(new FenceGate(Block::DARK_OAK_FENCE_GATE, 0, "Dark Oak Fence Gate"));
|
||||
self::registerBlock(new FenceGate(Block::ACACIA_FENCE_GATE, 0, "Acacia Fence Gate"));
|
||||
//TODO: REPEATING_COMMAND_BLOCK
|
||||
//TODO: CHAIN_COMMAND_BLOCK
|
||||
|
||||
self::registerBlock(new WoodenDoor(Block::SPRUCE_DOOR_BLOCK, 0, "Spruce Door", Item::SPRUCE_DOOR));
|
||||
self::registerBlock(new WoodenDoor(Block::BIRCH_DOOR_BLOCK, 0, "Birch Door", Item::BIRCH_DOOR));
|
||||
self::registerBlock(new WoodenDoor(Block::JUNGLE_DOOR_BLOCK, 0, "Jungle Door", Item::JUNGLE_DOOR));
|
||||
self::registerBlock(new WoodenDoor(Block::ACACIA_DOOR_BLOCK, 0, "Acacia Door", Item::ACACIA_DOOR));
|
||||
self::registerBlock(new WoodenDoor(Block::DARK_OAK_DOOR_BLOCK, 0, "Dark Oak Door", Item::DARK_OAK_DOOR));
|
||||
self::registerBlock(new GrassPath());
|
||||
self::registerBlock(new ItemFrame());
|
||||
//TODO: CHORUS_FLOWER
|
||||
self::registerBlock(new Purpur());
|
||||
self::registerBlock(new WoodenDoor(Block::SPRUCE_DOOR_BLOCK, 0, "Spruce Door", Item::SPRUCE_DOOR));
|
||||
self::registerBlock(new WoodenDoor(Block::BIRCH_DOOR_BLOCK, 0, "Birch Door", Item::BIRCH_DOOR));
|
||||
self::registerBlock(new WoodenDoor(Block::JUNGLE_DOOR_BLOCK, 0, "Jungle Door", Item::JUNGLE_DOOR));
|
||||
self::registerBlock(new WoodenDoor(Block::ACACIA_DOOR_BLOCK, 0, "Acacia Door", Item::ACACIA_DOOR));
|
||||
self::registerBlock(new WoodenDoor(Block::DARK_OAK_DOOR_BLOCK, 0, "Dark Oak Door", Item::DARK_OAK_DOOR));
|
||||
self::registerBlock(new GrassPath());
|
||||
self::registerBlock(new ItemFrame());
|
||||
//TODO: CHORUS_FLOWER
|
||||
self::registerBlock(new Purpur());
|
||||
|
||||
self::registerBlock(new PurpurStairs());
|
||||
self::registerBlock(new PurpurStairs());
|
||||
|
||||
//TODO: UNDYED_SHULKER_BOX
|
||||
self::registerBlock(new EndStoneBricks());
|
||||
//TODO: FROSTED_ICE
|
||||
self::registerBlock(new EndRod());
|
||||
//TODO: END_GATEWAY
|
||||
//TODO: UNDYED_SHULKER_BOX
|
||||
self::registerBlock(new EndStoneBricks());
|
||||
//TODO: FROSTED_ICE
|
||||
self::registerBlock(new EndRod());
|
||||
//TODO: END_GATEWAY
|
||||
|
||||
self::registerBlock(new Magma());
|
||||
self::registerBlock(new NetherWartBlock());
|
||||
self::registerBlock(new NetherBrick(Block::RED_NETHER_BRICK, 0, "Red Nether Bricks"));
|
||||
self::registerBlock(new BoneBlock());
|
||||
self::registerBlock(new Magma());
|
||||
self::registerBlock(new NetherWartBlock());
|
||||
self::registerBlock(new NetherBrick(Block::RED_NETHER_BRICK, 0, "Red Nether Bricks"));
|
||||
self::registerBlock(new BoneBlock());
|
||||
|
||||
//TODO: SHULKER_BOX
|
||||
self::registerBlock(new GlazedTerracotta(Block::PURPLE_GLAZED_TERRACOTTA, 0, "Purple Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::WHITE_GLAZED_TERRACOTTA, 0, "White Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::ORANGE_GLAZED_TERRACOTTA, 0, "Orange Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::MAGENTA_GLAZED_TERRACOTTA, 0, "Magenta Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::LIGHT_BLUE_GLAZED_TERRACOTTA, 0, "Light Blue Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::YELLOW_GLAZED_TERRACOTTA, 0, "Yellow Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::LIME_GLAZED_TERRACOTTA, 0, "Lime Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::PINK_GLAZED_TERRACOTTA, 0, "Pink Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::GRAY_GLAZED_TERRACOTTA, 0, "Grey Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::SILVER_GLAZED_TERRACOTTA, 0, "Light Grey Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::CYAN_GLAZED_TERRACOTTA, 0, "Cyan Glazed Terracotta"));
|
||||
//TODO: SHULKER_BOX
|
||||
self::registerBlock(new GlazedTerracotta(Block::PURPLE_GLAZED_TERRACOTTA, 0, "Purple Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::WHITE_GLAZED_TERRACOTTA, 0, "White Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::ORANGE_GLAZED_TERRACOTTA, 0, "Orange Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::MAGENTA_GLAZED_TERRACOTTA, 0, "Magenta Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::LIGHT_BLUE_GLAZED_TERRACOTTA, 0, "Light Blue Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::YELLOW_GLAZED_TERRACOTTA, 0, "Yellow Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::LIME_GLAZED_TERRACOTTA, 0, "Lime Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::PINK_GLAZED_TERRACOTTA, 0, "Pink Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::GRAY_GLAZED_TERRACOTTA, 0, "Grey Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::SILVER_GLAZED_TERRACOTTA, 0, "Light Grey Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::CYAN_GLAZED_TERRACOTTA, 0, "Cyan Glazed Terracotta"));
|
||||
|
||||
self::registerBlock(new GlazedTerracotta(Block::BLUE_GLAZED_TERRACOTTA, 0, "Blue Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::BROWN_GLAZED_TERRACOTTA, 0, "Brown Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::GREEN_GLAZED_TERRACOTTA, 0, "Green Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::RED_GLAZED_TERRACOTTA, 0, "Red Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::BLACK_GLAZED_TERRACOTTA, 0, "Black Glazed Terracotta"));
|
||||
self::registerBlock(new Concrete());
|
||||
self::registerBlock(new ConcretePowder());
|
||||
self::registerBlock(new GlazedTerracotta(Block::BLUE_GLAZED_TERRACOTTA, 0, "Blue Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::BROWN_GLAZED_TERRACOTTA, 0, "Brown Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::GREEN_GLAZED_TERRACOTTA, 0, "Green Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::RED_GLAZED_TERRACOTTA, 0, "Red Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::BLACK_GLAZED_TERRACOTTA, 0, "Black Glazed Terracotta"));
|
||||
self::registerBlock(new Concrete());
|
||||
self::registerBlock(new ConcretePowder());
|
||||
|
||||
//TODO: CHORUS_PLANT
|
||||
self::registerBlock(new StainedGlass());
|
||||
//TODO: CHORUS_PLANT
|
||||
self::registerBlock(new StainedGlass());
|
||||
|
||||
self::registerBlock(new Podzol());
|
||||
self::registerBlock(new Beetroot());
|
||||
self::registerBlock(new Stonecutter());
|
||||
self::registerBlock(new GlowingObsidian());
|
||||
self::registerBlock(new NetherReactor());
|
||||
//TODO: INFO_UPDATE
|
||||
//TODO: INFO_UPDATE2
|
||||
//TODO: MOVINGBLOCK
|
||||
//TODO: OBSERVER
|
||||
//TODO: STRUCTURE_BLOCK
|
||||
self::registerBlock(new Podzol());
|
||||
self::registerBlock(new Beetroot());
|
||||
self::registerBlock(new Stonecutter());
|
||||
self::registerBlock(new GlowingObsidian());
|
||||
self::registerBlock(new NetherReactor());
|
||||
self::registerBlock(new InfoUpdate(Block::INFO_UPDATE, 0, "update!"));
|
||||
self::registerBlock(new InfoUpdate(Block::INFO_UPDATE2, 0, "ate!upd"));
|
||||
//TODO: MOVINGBLOCK
|
||||
//TODO: OBSERVER
|
||||
//TODO: STRUCTURE_BLOCK
|
||||
|
||||
//TODO: RESERVED6
|
||||
self::registerBlock(new Reserved6(Block::RESERVED6, 0, "reserved6"));
|
||||
|
||||
foreach(self::$list as $id => $block){
|
||||
if($block === null){
|
||||
self::registerBlock(new UnknownBlock($id));
|
||||
}
|
||||
for($id = 0, $size = self::$fullList->getSize() >> 4; $id < $size; ++$id){
|
||||
if(self::$fullList[$id << 4] === null){
|
||||
self::registerBlock(new UnknownBlock($id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function isInit() : bool{
|
||||
return self::$fullList !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a block type into the index. Plugins may use this method to register new block types or override
|
||||
* existing ones.
|
||||
@ -348,8 +358,6 @@ class BlockFactory{
|
||||
throw new \RuntimeException("Trying to overwrite an already registered block");
|
||||
}
|
||||
|
||||
self::$list[$id] = clone $block;
|
||||
|
||||
for($meta = 0; $meta < 16; ++$meta){
|
||||
$variant = clone $block;
|
||||
$variant->setDamage($meta);
|
||||
@ -360,7 +368,7 @@ class BlockFactory{
|
||||
self::$transparent[$id] = $block->isTransparent();
|
||||
self::$hardness[$id] = $block->getHardness();
|
||||
self::$light[$id] = $block->getLightLevel();
|
||||
self::$lightFilter[$id] = $block->getLightFilter() + 1; //opacity plus 1 standard light filter
|
||||
self::$lightFilter[$id] = min(15, $block->getLightFilter() + 1); //opacity plus 1 standard light filter
|
||||
self::$diffusesSkyLight[$id] = $block->diffusesSkyLight();
|
||||
self::$blastResistance[$id] = $block->getBlastResistance();
|
||||
}
|
||||
@ -390,9 +398,9 @@ class BlockFactory{
|
||||
}
|
||||
|
||||
if($pos !== null){
|
||||
$block->x = $pos->x;
|
||||
$block->y = $pos->y;
|
||||
$block->z = $pos->z;
|
||||
$block->x = $pos->getFloorX();
|
||||
$block->y = $pos->getFloorY();
|
||||
$block->z = $pos->getFloorZ();
|
||||
$block->level = $pos->level;
|
||||
}
|
||||
|
||||
@ -411,10 +419,59 @@ class BlockFactory{
|
||||
* Returns whether a specified block ID is already registered in the block factory.
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isRegistered(int $id) : bool{
|
||||
$b = self::$list[$id];
|
||||
$b = self::$fullList[$id << 4];
|
||||
return $b !== null and !($b instanceof UnknownBlock);
|
||||
}
|
||||
}
|
||||
|
||||
public static function registerStaticRuntimeIdMappings() : void{
|
||||
/** @var mixed[] $runtimeIdMap */
|
||||
$runtimeIdMap = json_decode(file_get_contents(\pocketmine\RESOURCE_PATH . "runtimeid_table.json"), true);
|
||||
$legacyIdMap = json_decode(file_get_contents(\pocketmine\RESOURCE_PATH . "legacy_id_map.json"), true);
|
||||
foreach($runtimeIdMap as $k => $obj){
|
||||
//this has to use the json offset to make sure the mapping is consistent with what we send over network, even though we aren't using all the entries
|
||||
if(!isset($legacyIdMap[$obj["name"]])){
|
||||
continue;
|
||||
}
|
||||
self::registerMapping($k, $legacyIdMap[$obj["name"]], $obj["data"]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $meta
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function toStaticRuntimeId(int $id, int $meta = 0) : int{
|
||||
/*
|
||||
* try id+meta first
|
||||
* if not found, try id+0 (strip meta)
|
||||
* if still not found, return update! block
|
||||
*/
|
||||
return self::$staticRuntimeIdMap[($id << 4) | $meta] ?? self::$staticRuntimeIdMap[$id << 4] ?? self::$staticRuntimeIdMap[BlockIds::INFO_UPDATE << 4];
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @param int $runtimeId
|
||||
*
|
||||
* @return int[] [id, meta]
|
||||
*/
|
||||
public static function fromStaticRuntimeId(int $runtimeId) : array{
|
||||
$v = self::$legacyIdMap[$runtimeId];
|
||||
return [$v >> 4, $v & 0xf];
|
||||
}
|
||||
|
||||
private static function registerMapping(int $staticRuntimeId, int $legacyId, int $legacyMeta) : void{
|
||||
self::$staticRuntimeIdMap[($legacyId << 4) | $legacyMeta] = $staticRuntimeId;
|
||||
self::$legacyIdMap[$staticRuntimeId] = ($legacyId << 4) | $legacyMeta;
|
||||
self::$lastRuntimeId = max(self::$lastRuntimeId, $staticRuntimeId);
|
||||
}
|
||||
}
|
||||
|
@ -21,21 +21,19 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
/**
|
||||
* Math related classes, like matrices, bounding boxes and vector
|
||||
* Types of tools that can be used to break blocks
|
||||
* Blocks may allow multiple tool types by combining these bitflags
|
||||
*/
|
||||
namespace pocketmine\math;
|
||||
interface BlockToolType{
|
||||
|
||||
public const TYPE_NONE = 0;
|
||||
public const TYPE_SWORD = 1 << 0;
|
||||
public const TYPE_SHOVEL = 1 << 1;
|
||||
public const TYPE_PICKAXE = 1 << 2;
|
||||
public const TYPE_AXE = 1 << 3;
|
||||
public const TYPE_SHEARS = 1 << 4;
|
||||
|
||||
abstract class Math{
|
||||
|
||||
public static function floorFloat($n) : int{
|
||||
$i = (int) $n;
|
||||
return $n >= $i ? $i : $i - 1;
|
||||
}
|
||||
|
||||
public static function ceilFloat($n) : int{
|
||||
$i = (int) ($n + 1);
|
||||
return $n >= $i ? $i : $i - 1;
|
||||
}
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\PillarRotationHelper;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
@ -46,7 +46,11 @@ class BoneBlock extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
@ -57,13 +61,4 @@ class BoneBlock extends Solid{
|
||||
public function getVariantBitmask() : int{
|
||||
return 0x03;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
|
||||
class Bookshelf extends Solid{
|
||||
|
||||
@ -44,10 +43,10 @@ class Bookshelf extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_AXE;
|
||||
return BlockToolType::TYPE_AXE;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::BOOK, 0, 3)
|
||||
];
|
||||
@ -57,4 +56,11 @@ class Bookshelf extends Solid{
|
||||
return 300;
|
||||
}
|
||||
|
||||
}
|
||||
public function getFlameEncouragement() : int{
|
||||
return 30;
|
||||
}
|
||||
|
||||
public function getFlammability() : int{
|
||||
return 20;
|
||||
}
|
||||
}
|
||||
|
@ -23,12 +23,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class BrewingStand extends Transparent{
|
||||
|
||||
protected $id = self::BREWING_STAND_BLOCK;
|
||||
|
||||
protected $itemId = Item::BREWING_STAND;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
@ -42,7 +45,11 @@ class BrewingStand extends Transparent{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
@ -50,4 +57,4 @@ class BrewingStand extends Transparent{
|
||||
}
|
||||
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class BrickStairs extends Stair{
|
||||
|
||||
@ -42,11 +42,14 @@ class BrickStairs extends Stair{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Brick Stairs";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class Bricks extends Solid{
|
||||
|
||||
@ -43,18 +42,14 @@ class Bricks extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Bricks";
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,4 +34,4 @@ class BrownMushroom extends RedMushroom{
|
||||
public function getLightLevel() : int{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use function mt_rand;
|
||||
|
||||
class BrownMushroomBlock extends RedMushroomBlock{
|
||||
|
||||
@ -33,9 +34,9 @@ class BrownMushroomBlock extends RedMushroomBlock{
|
||||
return "Brown Mushroom Block";
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
Item::get(Item::BROWN_MUSHROOM, 0, mt_rand(0, 2))
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,9 +24,8 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\tile\Furnace as TileFurnace;
|
||||
use pocketmine\tile\Tile;
|
||||
@ -35,6 +34,8 @@ class BurningFurnace extends Solid{
|
||||
|
||||
protected $id = self::BURNING_FURNACE;
|
||||
|
||||
protected $itemId = self::FURNACE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
@ -48,7 +49,11 @@ class BurningFurnace extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getLightLevel() : int{
|
||||
@ -77,7 +82,7 @@ class BurningFurnace extends Solid{
|
||||
$furnace = Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this));
|
||||
}
|
||||
|
||||
if($furnace->namedtag->hasTag("Lock", StringTag::class) and $furnace->namedtag->getString("Lock") !== $item->getCustomName()){
|
||||
if(!$furnace->canOpenWith($item->getCustomName())){
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -90,12 +95,4 @@ class BurningFurnace extends Solid{
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,4 +48,4 @@ abstract class Button extends Flowable{
|
||||
//TODO
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,11 +28,9 @@ use pocketmine\event\block\BlockGrowEvent;
|
||||
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\Server;
|
||||
|
||||
class Cactus extends Transparent{
|
||||
|
||||
@ -66,50 +64,53 @@ class Cactus extends Transparent{
|
||||
);
|
||||
}
|
||||
|
||||
public function ticksRandomly() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onEntityCollide(Entity $entity) : void{
|
||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_CONTACT, 1);
|
||||
$entity->attack($ev);
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() !== self::SAND and $down->getId() !== self::CACTUS){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
}else{
|
||||
for($side = 2; $side <= 5; ++$side){
|
||||
$b = $this->getSide($side);
|
||||
if(!$b->canBeFlowedInto()){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::CACTUS){
|
||||
if($this->meta === 0x0f){
|
||||
for($y = 1; $y < 3; ++$y){
|
||||
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z);
|
||||
if($b->getId() === self::AIR){
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS)));
|
||||
if(!$ev->isCancelled()){
|
||||
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->meta = 0;
|
||||
$this->getLevel()->setBlock($this, $this);
|
||||
}else{
|
||||
++$this->meta;
|
||||
$this->getLevel()->setBlock($this, $this);
|
||||
public function onNearbyBlockChange() : void{
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() !== self::SAND and $down->getId() !== self::CACTUS){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
}else{
|
||||
for($side = 2; $side <= 5; ++$side){
|
||||
$b = $this->getSide($side);
|
||||
if($b->isSolid()){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
public function ticksRandomly() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::CACTUS){
|
||||
if($this->meta === 0x0f){
|
||||
for($y = 1; $y < 3; ++$y){
|
||||
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z);
|
||||
if($b->getId() === self::AIR){
|
||||
$ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS));
|
||||
$ev->call();
|
||||
if($ev->isCancelled()){
|
||||
break;
|
||||
}
|
||||
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->meta = 0;
|
||||
$this->getLevel()->setBlock($this, $this);
|
||||
}else{
|
||||
++$this->meta;
|
||||
$this->getLevel()->setBlock($this, $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
@ -119,7 +120,7 @@ class Cactus extends Transparent{
|
||||
$block1 = $this->getSide(Vector3::SIDE_SOUTH);
|
||||
$block2 = $this->getSide(Vector3::SIDE_WEST);
|
||||
$block3 = $this->getSide(Vector3::SIDE_EAST);
|
||||
if($block0->isTransparent() === true and $block1->isTransparent() === true and $block2->isTransparent() === true and $block3->isTransparent() === true){
|
||||
if(!$block0->isSolid() and !$block1->isSolid() and !$block2->isSolid() and !$block3->isSolid()){
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
|
||||
return true;
|
||||
@ -132,4 +133,4 @@ class Cactus extends Transparent{
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,11 +23,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Effect;
|
||||
use pocketmine\event\entity\EntityEatBlockEvent;
|
||||
use pocketmine\entity\EffectInstance;
|
||||
use pocketmine\entity\Living;
|
||||
use pocketmine\item\FoodSource;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
@ -36,6 +35,8 @@ class Cake extends Transparent implements FoodSource{
|
||||
|
||||
protected $id = self::CAKE_BLOCK;
|
||||
|
||||
protected $itemId = Item::CAKE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
@ -45,7 +46,7 @@ class Cake extends Transparent implements FoodSource{
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Cake Block";
|
||||
return "Cake";
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
@ -73,37 +74,24 @@ class Cake extends Transparent implements FoodSource{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
//TODO: refactor this into generic food handling
|
||||
if($player instanceof Player and $player->getFood() < $player->getMaxFood()){
|
||||
$player->getServer()->getPluginManager()->callEvent($ev = new EntityEatBlockEvent($player, $this));
|
||||
|
||||
if(!$ev->isCancelled()){
|
||||
$player->addFood($ev->getFoodRestore());
|
||||
$player->addSaturation($ev->getSaturationRestore());
|
||||
foreach($ev->getAdditionalEffects() as $effect){
|
||||
$player->addEffect($effect);
|
||||
}
|
||||
|
||||
$this->getLevel()->setBlock($this, $ev->getResidue());
|
||||
return true;
|
||||
}
|
||||
if($player !== null){
|
||||
$player->consumeObject($this);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -117,6 +105,13 @@ class Cake extends Transparent implements FoodSource{
|
||||
return 0.4;
|
||||
}
|
||||
|
||||
public function requiresHunger() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Block
|
||||
*/
|
||||
public function getResidue(){
|
||||
$clone = clone $this;
|
||||
$clone->meta++;
|
||||
@ -127,9 +122,13 @@ class Cake extends Transparent implements FoodSource{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Effect[]
|
||||
* @return EffectInstance[]
|
||||
*/
|
||||
public function getAdditionalEffects() : array{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function onConsume(Living $consumer) : void{
|
||||
$this->level->setBlock($this, $this->getResidue());
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
@ -73,16 +72,17 @@ class Carpet extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
public function getFlameEncouragement() : int{
|
||||
return 30;
|
||||
}
|
||||
|
||||
public function getFlammability() : int{
|
||||
return 20;
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use function mt_rand;
|
||||
|
||||
class Carrot extends Crops{
|
||||
|
||||
@ -38,7 +39,7 @@ class Carrot extends Crops{
|
||||
return "Carrot Block";
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::CARROT, 0, $this->meta >= 0x07 ? mt_rand(1, 4) : 1)
|
||||
];
|
||||
@ -47,4 +48,4 @@ class Carrot extends Crops{
|
||||
public function getPickedItem() : Item{
|
||||
return ItemFactory::get(Item::CARROT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,10 +24,8 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\tile\Chest as TileChest;
|
||||
use pocketmine\tile\Tile;
|
||||
@ -49,7 +47,7 @@ class Chest extends Transparent{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_AXE;
|
||||
return BlockToolType::TYPE_AXE;
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
@ -102,16 +100,6 @@ class Chest extends Transparent{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onBreak(Item $item, Player $player = null) : bool{
|
||||
$t = $this->getLevel()->getTile($this);
|
||||
if($t instanceof TileChest){
|
||||
$t->unpair();
|
||||
}
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($player instanceof Player){
|
||||
|
||||
@ -126,7 +114,7 @@ class Chest extends Transparent{
|
||||
if(
|
||||
!$this->getSide(Vector3::SIDE_UP)->isTransparent() or
|
||||
($chest->isPaired() and !$chest->getPair()->getBlock()->getSide(Vector3::SIDE_UP)->isTransparent()) or
|
||||
($chest->namedtag->hasTag("Lock", StringTag::class) and $chest->namedtag->getString("Lock") !== $item->getCustomName())
|
||||
!$chest->canOpenWith($item->getCustomName())
|
||||
){
|
||||
return true;
|
||||
}
|
||||
@ -144,4 +132,4 @@ class Chest extends Transparent{
|
||||
public function getFuelTime() : int{
|
||||
return 300;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
|
||||
class Clay extends Solid{
|
||||
|
||||
@ -40,16 +39,16 @@ class Clay extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SHOVEL;
|
||||
return BlockToolType::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Clay Block";
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::CLAY_BALL, 0, 4)
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class Coal extends Solid{
|
||||
|
||||
@ -39,22 +38,26 @@ class Coal extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Coal Block";
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
return 16000;
|
||||
}
|
||||
}
|
||||
|
||||
public function getFlameEncouragement() : int{
|
||||
return 5;
|
||||
}
|
||||
|
||||
public function getFlammability() : int{
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,8 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
use function mt_rand;
|
||||
|
||||
class CoalOre extends Solid{
|
||||
|
||||
@ -40,21 +41,24 @@ class CoalOre extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Coal Ore";
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return [
|
||||
ItemFactory::get(Item::COAL, 0, 1)
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::COAL)
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
protected function getXpDropAmount() : int{
|
||||
return mt_rand(0, 2);
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class Cobblestone extends Solid{
|
||||
|
||||
@ -35,7 +34,11 @@ class Cobblestone extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
@ -45,12 +48,4 @@ class Cobblestone extends Solid{
|
||||
public function getHardness() : float{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class CobblestoneStairs extends Stair{
|
||||
|
||||
@ -38,11 +38,14 @@ class CobblestoneStairs extends Stair{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Cobblestone Stairs";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -23,13 +23,25 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
|
||||
class CobblestoneWall extends Transparent{
|
||||
public const NONE_MOSSY_WALL = 0;
|
||||
public const MOSSY_WALL = 1;
|
||||
public const GRANITE_WALL = 2;
|
||||
public const DIORITE_WALL = 3;
|
||||
public const ANDESITE_WALL = 4;
|
||||
public const SANDSTONE_WALL = 5;
|
||||
public const BRICK_WALL = 6;
|
||||
public const STONE_BRICK_WALL = 7;
|
||||
public const MOSSY_STONE_BRICK_WALL = 8;
|
||||
public const NETHER_BRICK_WALL = 9;
|
||||
public const END_STONE_BRICK_WALL = 10;
|
||||
public const PRISMARINE_WALL = 11;
|
||||
public const RED_SANDSTONE_WALL = 12;
|
||||
public const RED_NETHER_BRICK_WALL = 13;
|
||||
|
||||
protected $id = self::COBBLESTONE_WALL;
|
||||
|
||||
@ -38,7 +50,11 @@ class CobblestoneWall extends Transparent{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
@ -46,11 +62,23 @@ class CobblestoneWall extends Transparent{
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
if($this->meta === 0x01){
|
||||
return "Mossy Cobblestone Wall";
|
||||
}
|
||||
|
||||
return "Cobblestone Wall";
|
||||
static $names = [
|
||||
self::NONE_MOSSY_WALL => "Cobblestone",
|
||||
self::MOSSY_WALL => "Mossy Cobblestone",
|
||||
self::GRANITE_WALL => "Granite",
|
||||
self::DIORITE_WALL => "Diorite",
|
||||
self::ANDESITE_WALL => "Andesite",
|
||||
self::SANDSTONE_WALL => "Sandstone",
|
||||
self::BRICK_WALL => "Brick",
|
||||
self::STONE_BRICK_WALL => "Stone Brick",
|
||||
self::MOSSY_STONE_BRICK_WALL => "Mossy Stone Brick",
|
||||
self::NETHER_BRICK_WALL => "Nether Brick",
|
||||
self::END_STONE_BRICK_WALL => "End Stone Brick",
|
||||
self::PRISMARINE_WALL => "Prismarine",
|
||||
self::RED_SANDSTONE_WALL => "Red Sandstone",
|
||||
self::RED_NETHER_BRICK_WALL => "Red Nether Brick"
|
||||
];
|
||||
return ($names[$this->getVariant()] ?? "Unknown") . " Wall";
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
@ -86,5 +114,4 @@ class CobblestoneWall extends Transparent{
|
||||
public function canConnect(Block $block){
|
||||
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\ItemFactory;
|
||||
|
||||
class Cobweb extends Flowable{
|
||||
|
||||
@ -48,19 +48,24 @@ class Cobweb extends Flowable{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SWORD;
|
||||
return BlockToolType::TYPE_SWORD | BlockToolType::TYPE_SHEARS;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function onEntityCollide(Entity $entity) : void{
|
||||
$entity->resetFallDistance();
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
//TODO: correct drops
|
||||
return [];
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::STRING)
|
||||
];
|
||||
}
|
||||
|
||||
public function diffusesSkyLight() : bool{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,5 +35,17 @@ class CocoaBlock extends Transparent{
|
||||
return "Cocoa Block";
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.2;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_AXE;
|
||||
}
|
||||
|
||||
//TODO
|
||||
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class Concrete extends Solid{
|
||||
|
||||
@ -44,15 +43,10 @@ class Concrete extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,6 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\level\Level;
|
||||
|
||||
class ConcretePowder extends Fallable{
|
||||
|
||||
@ -44,16 +42,15 @@ class ConcretePowder extends Fallable{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SHOVEL;
|
||||
return BlockToolType::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL and ($block = $this->checkAdjacentWater()) !== null){
|
||||
public function onNearbyBlockChange() : void{
|
||||
if(($block = $this->checkAdjacentWater()) !== null){
|
||||
$this->level->setBlock($this, $block);
|
||||
return $type;
|
||||
}else{
|
||||
parent::onNearbyBlockChange();
|
||||
}
|
||||
|
||||
return parent::onUpdate($type);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,10 +66,10 @@ class ConcretePowder extends Fallable{
|
||||
private function checkAdjacentWater() : ?Block{
|
||||
for($i = 1; $i < 6; ++$i){ //Do not check underneath
|
||||
if($this->getSide($i) instanceof Water){
|
||||
return Block::get(Block::CONCRETE, $this->meta);
|
||||
return BlockFactory::get(Block::CONCRETE, $this->meta);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,9 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\inventory\BigCraftingGrid;
|
||||
use pocketmine\inventory\CraftingGrid;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\Player;
|
||||
|
||||
class CraftingTable extends Solid{
|
||||
@ -45,12 +44,12 @@ class CraftingTable extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_AXE;
|
||||
return BlockToolType::TYPE_AXE;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($player instanceof Player){
|
||||
$player->setCraftingGrid(new BigCraftingGrid($player));
|
||||
$player->setCraftingGrid(new CraftingGrid($player, CraftingGrid::SIZE_BIG));
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -59,4 +58,4 @@ class CraftingTable extends Solid{
|
||||
public function getFuelTime() : int{
|
||||
return 300;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,10 +25,9 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\event\block\BlockGrowEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\Server;
|
||||
use function mt_rand;
|
||||
|
||||
abstract class Crops extends Flowable{
|
||||
|
||||
@ -44,15 +43,15 @@ abstract class Crops extends Flowable{
|
||||
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
||||
if($this->meta < 7 and $item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
||||
$block = clone $this;
|
||||
$block->meta += mt_rand(2, 5);
|
||||
if($block->meta > 7){
|
||||
$block->meta = 7;
|
||||
}
|
||||
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
||||
|
||||
$ev = new BlockGrowEvent($this, $block);
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
|
||||
}
|
||||
@ -65,34 +64,31 @@ abstract class Crops extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function ticksRandomly() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
||||
if(mt_rand(0, 2) === 1){
|
||||
if($this->meta < 0x07){
|
||||
$block = clone $this;
|
||||
++$block->meta;
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
||||
|
||||
if(!$ev->isCancelled()){
|
||||
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
|
||||
}else{
|
||||
return Level::BLOCK_UPDATE_RANDOM;
|
||||
}
|
||||
public function onRandomTick() : void{
|
||||
if(mt_rand(0, 2) === 1){
|
||||
if($this->meta < 0x07){
|
||||
$block = clone $this;
|
||||
++$block->meta;
|
||||
$ev = new BlockGrowEvent($this, $block);
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
|
||||
}
|
||||
}else{
|
||||
return Level::BLOCK_UPDATE_RANDOM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
@ -52,15 +51,17 @@ class Dandelion extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getFlameEncouragement() : int{
|
||||
return 60;
|
||||
}
|
||||
|
||||
public function getFlammability() : int{
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
|
@ -43,5 +43,9 @@ class DaylightSensor extends Transparent{
|
||||
return 300;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_AXE;
|
||||
}
|
||||
|
||||
//TODO
|
||||
}
|
||||
|
@ -25,9 +25,9 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use function mt_rand;
|
||||
|
||||
class DeadBush extends Flowable{
|
||||
|
||||
@ -41,29 +41,43 @@ class DeadBush extends Flowable{
|
||||
return "Dead Bush";
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
if(!$this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SHEARS;
|
||||
return BlockToolType::TYPE_SHEARS;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isShears()){
|
||||
return parent::getDrops($item);
|
||||
if(!$this->isCompatibleWithTool($item)){
|
||||
return [
|
||||
ItemFactory::get(Item::STICK, 0, mt_rand(0, 2))
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
ItemFactory::get(Item::STICK, 0, mt_rand(0, 2))
|
||||
];
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
}
|
||||
|
||||
public function getFlameEncouragement() : int{
|
||||
return 60;
|
||||
}
|
||||
|
||||
public function getFlammability() : int{
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class DetectorRail extends Rail{
|
||||
class DetectorRail extends RedstoneRail{
|
||||
|
||||
protected $id = self::DETECTOR_RAIL;
|
||||
|
||||
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class Diamond extends Solid{
|
||||
|
||||
@ -43,14 +42,10 @@ class Diamond extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_IRON;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,8 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
use function mt_rand;
|
||||
|
||||
class DiamondOre extends Solid{
|
||||
|
||||
@ -44,16 +45,20 @@ class DiamondOre extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
||||
return [
|
||||
ItemFactory::get(Item::DIAMOND, 0, 1)
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_IRON;
|
||||
}
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::DIAMOND)
|
||||
];
|
||||
}
|
||||
|
||||
protected function getXpDropAmount() : int{
|
||||
return mt_rand(3, 7);
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Hoe;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Dirt extends Solid{
|
||||
@ -40,7 +40,7 @@ class Dirt extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SHOVEL;
|
||||
return BlockToolType::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
@ -51,8 +51,8 @@ class Dirt extends Solid{
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($item->isHoe()){
|
||||
$item->useOn($this);
|
||||
if($item instanceof Hoe){
|
||||
$item->applyDamage(1);
|
||||
if($this->meta === 1){
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
||||
}else{
|
||||
@ -64,4 +64,4 @@ class Dirt extends Solid{
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\level\sound\DoorSound;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
@ -201,26 +200,20 @@ abstract class Door extends Transparent{
|
||||
return $bb;
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false);
|
||||
if($this->getSide(Vector3::SIDE_UP) instanceof Door){
|
||||
$this->getLevel()->setBlock($this->getSide(Vector3::SIDE_UP), BlockFactory::get(Block::AIR), false);
|
||||
}
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false);
|
||||
if($this->getSide(Vector3::SIDE_UP) instanceof Door){
|
||||
$this->getLevel()->setBlock($this->getSide(Vector3::SIDE_UP), BlockFactory::get(Block::AIR), false);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
if($face === Vector3::SIDE_UP){
|
||||
$blockUp = $this->getSide(Vector3::SIDE_UP);
|
||||
$blockDown = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($blockUp->canBeReplaced() === false or $blockDown->isTransparent() === true){
|
||||
if(!$blockUp->canBeReplaced() or $blockDown->isTransparent()){
|
||||
return false;
|
||||
}
|
||||
$direction = $player instanceof Player ? $player->getDirection() : 0;
|
||||
@ -233,36 +226,19 @@ abstract class Door extends Transparent{
|
||||
$next = $this->getSide($faces[($direction + 2) % 4]);
|
||||
$next2 = $this->getSide($faces[$direction]);
|
||||
$metaUp = 0x08;
|
||||
if($next->getId() === $this->getId() or ($next2->isTransparent() === false and $next->isTransparent() === true)){ //Door hinge
|
||||
if($next->getId() === $this->getId() or (!$next2->isTransparent() and $next->isTransparent())){ //Door hinge
|
||||
$metaUp |= 0x01;
|
||||
}
|
||||
|
||||
$this->setDamage($player->getDirection() & 0x03);
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true); //Bottom
|
||||
$this->getLevel()->setBlock($blockUp, $b = BlockFactory::get($this->getId(), $metaUp), true); //Top
|
||||
$this->getLevel()->setBlock($blockUp, BlockFactory::get($this->getId(), $metaUp), true); //Top
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onBreak(Item $item, Player $player = null) : bool{
|
||||
if(($this->getDamage() & 0x08) === 0x08){
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() === $this->getId()){
|
||||
$this->getLevel()->setBlock($down, BlockFactory::get(Block::AIR), true);
|
||||
}
|
||||
}else{
|
||||
$up = $this->getSide(Vector3::SIDE_UP);
|
||||
if($up->getId() === $this->getId()){
|
||||
$this->getLevel()->setBlock($up, BlockFactory::get(Block::AIR), true);
|
||||
}
|
||||
}
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if(($this->getDamage() & 0x08) === 0x08){ //Top
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
@ -286,4 +262,32 @@ abstract class Door extends Transparent{
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
if(($this->meta & 0x08) === 0){ //bottom half only
|
||||
return parent::getDropsForCompatibleTool($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getAffectedBlocks() : array{
|
||||
if(($this->getDamage() & 0x08) === 0x08){
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() === $this->getId()){
|
||||
return [$this, $down];
|
||||
}
|
||||
}else{
|
||||
$up = $this->getSide(Vector3::SIDE_UP);
|
||||
if($up->getId() === $this->getId()){
|
||||
return [$this, $up];
|
||||
}
|
||||
}
|
||||
|
||||
return parent::getAffectedBlocks();
|
||||
}
|
||||
}
|
||||
|
@ -25,9 +25,9 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use function mt_rand;
|
||||
|
||||
class DoublePlant extends Flowable{
|
||||
public const BITFLAG_TOP = 0x08;
|
||||
@ -84,46 +84,45 @@ class DoublePlant extends Flowable{
|
||||
);
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if(!$this->isValidHalfPlant() or (($this->meta & self::BITFLAG_TOP) === 0 and $down->isTransparent())){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
public function onNearbyBlockChange() : void{
|
||||
if(!$this->isValidHalfPlant() or (($this->meta & self::BITFLAG_TOP) === 0 and $this->getSide(Vector3::SIDE_DOWN)->isTransparent())){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onBreak(Item $item, Player $player = null) : bool{
|
||||
if(parent::onBreak($item, $player) and $this->isValidHalfPlant()){
|
||||
$this->getLevel()->useBreakOn($this->getSide(($this->meta & self::BITFLAG_TOP) !== 0 ? Vector3::SIDE_DOWN : Vector3::SIDE_UP), $item, $player, $player !== null);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0x07;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return ($this->meta === 2 or $this->meta === 3) ? BlockToolType::TYPE_SHEARS : BlockToolType::TYPE_NONE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return ($this->meta === 2 or $this->meta === 3) ? 1 : 0; //only grass or fern require shears
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($this->meta & self::BITFLAG_TOP){
|
||||
if(!$item->isShears() and ($this->meta === 2 or $this->meta === 3)){ //grass or fern
|
||||
if(mt_rand(0, 24) === 0){
|
||||
return [
|
||||
ItemFactory::get(Item::SEEDS, 0, 1)
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
if($this->isCompatibleWithTool($item)){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return parent::getDrops($item);
|
||||
if(mt_rand(0, 24) === 0){
|
||||
return [
|
||||
ItemFactory::get(Item::SEEDS)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public function getAffectedBlocks() : array{
|
||||
if($this->isValidHalfPlant()){
|
||||
return [$this, $this->getSide(($this->meta & self::BITFLAG_TOP) !== 0 ? Vector3::SIDE_DOWN : Vector3::SIDE_UP)];
|
||||
}
|
||||
|
||||
return parent::getAffectedBlocks();
|
||||
}
|
||||
}
|
||||
|
@ -35,13 +35,20 @@ abstract class DoubleSlab extends Solid{
|
||||
abstract public function getSlabId() : int;
|
||||
|
||||
public function getName() : string{
|
||||
return "Double " . BlockFactory::get($this->getSlabId(), $this->getVariant())->getName() . " Slab";
|
||||
return "Double " . BlockFactory::get($this->getSlabId(), $this->getVariant())->getName();
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get($this->getSlabId(), $this->getVariant(), 2)
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getPickedItem() : Item{
|
||||
return ItemFactory::get($this->getSlabId(), $this->getVariant());
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class DoubleStoneSlab extends DoubleSlab{
|
||||
|
||||
@ -39,15 +38,10 @@ class DoubleStoneSlab extends DoubleSlab{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -30,5 +30,4 @@ class DoubleStoneSlab2 extends DoubleStoneSlab{
|
||||
public function getSlabId() : int{
|
||||
return self::STONE_SLAB2;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
|
||||
class DoubleWoodenSlab extends DoubleSlab{
|
||||
|
||||
protected $id = self::DOUBLE_WOODEN_SLAB;
|
||||
@ -38,6 +36,14 @@ class DoubleWoodenSlab extends DoubleSlab{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_AXE;
|
||||
return BlockToolType::TYPE_AXE;
|
||||
}
|
||||
}
|
||||
|
||||
public function getFlameEncouragement() : int{
|
||||
return 5;
|
||||
}
|
||||
|
||||
public function getFlammability() : int{
|
||||
return 20;
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class Emerald extends Solid{
|
||||
|
||||
@ -39,18 +38,14 @@ class Emerald extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_IRON;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Emerald Block";
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,8 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
use function mt_rand;
|
||||
|
||||
class EmeraldOre extends Solid{
|
||||
|
||||
@ -40,20 +41,24 @@ class EmeraldOre extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_IRON;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 3;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
||||
return [
|
||||
ItemFactory::get(Item::EMERALD, 0, 1)
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::EMERALD)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
protected function getXpDropAmount() : int{
|
||||
return mt_rand(3, 7);
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\inventory\EnchantInventory;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\tile\EnchantTable as TileEnchantTable;
|
||||
@ -60,7 +60,11 @@ class EnchantingTable extends Transparent{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
@ -72,12 +76,4 @@ class EnchantingTable extends Transparent{
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,4 +65,4 @@ class EndPortalFrame extends Solid{
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,4 +101,4 @@ class EndRod extends Flowable{
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class EndStone extends Solid{
|
||||
|
||||
@ -38,10 +38,14 @@ class EndStone extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class EndStoneBricks extends Solid{
|
||||
|
||||
@ -43,15 +42,10 @@ class EndStoneBricks extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\tile\EnderChest as TileEnderChest;
|
||||
@ -52,7 +52,11 @@ class EnderChest extends Chest{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
@ -71,10 +75,6 @@ class EnderChest extends Chest{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onBreak(Item $item, Player $player = null) : bool{
|
||||
return Block::onBreak($item, $player);
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($player instanceof Player){
|
||||
|
||||
@ -97,16 +97,13 @@ class EnderChest extends Chest{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return [ItemFactory::get(Item::OBSIDIAN, 0, 8)];
|
||||
}
|
||||
|
||||
return [];
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::OBSIDIAN, 0, 8)
|
||||
];
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -24,26 +24,23 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
|
||||
abstract class Fallable extends Solid{
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() === self::AIR or $down instanceof Liquid or $down instanceof Fire){
|
||||
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||
public function onNearbyBlockChange() : void{
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() === self::AIR or $down instanceof Liquid or $down instanceof Fire){
|
||||
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||
|
||||
$nbt = Entity::createBaseNBT($this->add(0.5, 0, 0.5));
|
||||
$nbt->setInt("TileID", $this->getId());
|
||||
$nbt->setByte("Data", $this->getDamage());
|
||||
$nbt = Entity::createBaseNBT($this->add(0.5, 0, 0.5));
|
||||
$nbt->setInt("TileID", $this->getId());
|
||||
$nbt->setByte("Data", $this->getDamage());
|
||||
|
||||
$fall = Entity::createEntity("FallingSand", $this->getLevel(), $nbt);
|
||||
$fall = Entity::createEntity("FallingSand", $this->getLevel(), $nbt);
|
||||
|
||||
if($fall !== null){
|
||||
$fall->spawnToAll();
|
||||
}
|
||||
if($fall !== null){
|
||||
$fall->spawnToAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -54,4 +51,4 @@ abstract class Fallable extends Solid{
|
||||
public function tickFalling() : ?Block{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,6 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
|
||||
@ -47,12 +45,9 @@ class Farmland extends Transparent{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SHOVEL;
|
||||
return BlockToolType::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
public function ticksRandomly() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return new AxisAlignedBB(
|
||||
@ -65,29 +60,28 @@ class Farmland extends Transparent{
|
||||
);
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL and $this->getSide(Vector3::SIDE_UP)->isSolid()){
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_UP)->isSolid()){
|
||||
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
||||
return $type;
|
||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
||||
if(!$this->canHydrate()){
|
||||
if($this->meta > 0){
|
||||
$this->meta--;
|
||||
$this->level->setBlock($this, $this, false, false);
|
||||
}else{
|
||||
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), false, true);
|
||||
}
|
||||
|
||||
return $type;
|
||||
}elseif($this->meta < 7){
|
||||
$this->meta = 7;
|
||||
$this->level->setBlock($this, $this, false, false);
|
||||
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
public function ticksRandomly() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
if(!$this->canHydrate()){
|
||||
if($this->meta > 0){
|
||||
$this->meta--;
|
||||
$this->level->setBlock($this, $this, false, false);
|
||||
}else{
|
||||
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), false, true);
|
||||
}
|
||||
}elseif($this->meta < 7){
|
||||
$this->meta = 7;
|
||||
$this->level->setBlock($this, $this, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
protected function canHydrate() : bool{
|
||||
@ -108,9 +102,17 @@ class Farmland extends Transparent{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::DIRT, 0, 1)
|
||||
ItemFactory::get(Item::DIRT)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getPickedItem() : Item{
|
||||
return ItemFactory::get(Item::DIRT);
|
||||
}
|
||||
}
|
||||
|
@ -105,5 +105,4 @@ abstract class Fence extends Transparent{
|
||||
public function canConnect(Block $block){
|
||||
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\level\sound\DoorSound;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
@ -37,7 +36,7 @@ class FenceGate extends Transparent{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_AXE;
|
||||
return BlockToolType::TYPE_AXE;
|
||||
}
|
||||
|
||||
|
||||
@ -95,4 +94,12 @@ class FenceGate extends Transparent{
|
||||
public function getFuelTime() : int{
|
||||
return 300;
|
||||
}
|
||||
|
||||
public function getFlameEncouragement() : int{
|
||||
return 5;
|
||||
}
|
||||
|
||||
public function getFlammability() : int{
|
||||
return 20;
|
||||
}
|
||||
}
|
||||
|
@ -25,13 +25,14 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\projectile\Arrow;
|
||||
use pocketmine\event\block\BlockBurnEvent;
|
||||
use pocketmine\event\entity\EntityCombustByBlockEvent;
|
||||
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Server;
|
||||
use function min;
|
||||
use function mt_rand;
|
||||
|
||||
class Fire extends Flowable{
|
||||
|
||||
@ -61,10 +62,6 @@ class Fire extends Flowable{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function ticksRandomly() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onEntityCollide(Entity $entity) : void{
|
||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, 1);
|
||||
$entity->attack($ev);
|
||||
@ -73,45 +70,101 @@ class Fire extends Flowable{
|
||||
if($entity instanceof Arrow){
|
||||
$ev->setCancelled();
|
||||
}
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev);
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$entity->setOnFire($ev->getDuration());
|
||||
}
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
for($s = 0; $s <= 5; ++$s){
|
||||
$side = $this->getSide($s);
|
||||
if($side->getId() !== self::AIR and !($side instanceof Liquid)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public function onNearbyBlockChange() : void{
|
||||
if(!$this->getSide(Vector3::SIDE_DOWN)->isSolid() and !$this->hasAdjacentFlammableBlocks()){
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||
}else{
|
||||
$this->level->scheduleDelayedBlockUpdate($this, mt_rand(30, 40));
|
||||
}
|
||||
}
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::NETHERRACK){
|
||||
if(mt_rand(0, 2) === 0){
|
||||
if($this->meta === 0x0F){
|
||||
$this->level->setBlock($this, BlockFactory::get(Block::AIR));
|
||||
}else{
|
||||
$this->meta++;
|
||||
$this->level->setBlock($this, $this);
|
||||
}
|
||||
public function ticksRandomly() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
public function onRandomTick() : void{
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
|
||||
$result = null;
|
||||
if($this->meta < 15 and mt_rand(0, 2) === 0){
|
||||
$this->meta++;
|
||||
$result = $this;
|
||||
}
|
||||
$canSpread = true;
|
||||
|
||||
if(!$down->burnsForever()){
|
||||
//TODO: check rain
|
||||
if($this->meta === 15){
|
||||
if(!$down->isFlammable() and mt_rand(0, 3) === 3){ //1/4 chance to extinguish
|
||||
$canSpread = false;
|
||||
$result = BlockFactory::get(Block::AIR);
|
||||
}
|
||||
}elseif(!$this->hasAdjacentFlammableBlocks()){
|
||||
$canSpread = false;
|
||||
if(!$down->isSolid() or $this->meta > 3){ //fire older than 3, or without a solid block below
|
||||
$result = BlockFactory::get(Block::AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($result !== null){
|
||||
$this->level->setBlock($this, $result);
|
||||
}
|
||||
|
||||
$this->level->scheduleDelayedBlockUpdate($this, mt_rand(30, 40));
|
||||
|
||||
if($canSpread){
|
||||
//TODO: raise upper bound for chance in humid biomes
|
||||
|
||||
foreach($this->getHorizontalSides() as $side){
|
||||
$this->burnBlock($side, 300);
|
||||
}
|
||||
|
||||
//vanilla uses a 250 upper bound here, but I don't think they intended to increase the chance of incineration
|
||||
$this->burnBlock($this->getSide(Vector3::SIDE_UP), 350);
|
||||
$this->burnBlock($this->getSide(Vector3::SIDE_DOWN), 350);
|
||||
|
||||
//TODO: fire spread
|
||||
}
|
||||
}
|
||||
|
||||
public function onScheduledUpdate() : void{
|
||||
$this->onRandomTick();
|
||||
}
|
||||
|
||||
private function hasAdjacentFlammableBlocks() : bool{
|
||||
for($i = 0; $i <= 5; ++$i){
|
||||
if($this->getSide($i)->isFlammable()){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
private function burnBlock(Block $block, int $chanceBound) : void{
|
||||
if(mt_rand(0, $chanceBound) < $block->getFlammability()){
|
||||
$ev = new BlockBurnEvent($block, $this);
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$block->onIncinerate();
|
||||
|
||||
if(mt_rand(0, $this->meta + 9) < 5){ //TODO: check rain
|
||||
$this->level->setBlock($block, BlockFactory::get(Block::FIRE, min(15, $this->meta + (mt_rand(0, 4) >> 2))));
|
||||
}else{
|
||||
$this->level->setBlock($block, BlockFactory::get(Block::AIR));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,4 +42,4 @@ abstract class Flowable extends Transparent{
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
@ -71,15 +70,17 @@ class Flower extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getFlameEncouragement() : int{
|
||||
return 60;
|
||||
}
|
||||
|
||||
public function getFlammability() : int{
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
@ -68,16 +67,10 @@ class FlowerPot extends Flowable{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
@ -96,8 +89,12 @@ class FlowerPot extends Flowable{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
$items = parent::getDrops($item);
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
$items = parent::getDropsForCompatibleTool($item);
|
||||
|
||||
$tile = $this->getLevel()->getTile($this);
|
||||
if($tile instanceof TileFlowerPot){
|
||||
@ -110,4 +107,7 @@ class FlowerPot extends Flowable{
|
||||
return $items;
|
||||
}
|
||||
|
||||
}
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -35,4 +35,4 @@ class Furnace extends BurningFurnace{
|
||||
public function getLightLevel() : int{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ class Glass extends Transparent{
|
||||
return 0.3;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ class GlassPane extends Thin{
|
||||
return 0.3;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
@ -36,7 +36,11 @@ class GlazedTerracotta extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
@ -56,12 +60,4 @@ class GlazedTerracotta extends Solid{
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class GlowingObsidian extends Solid{
|
||||
|
||||
protected $id = self::GLOWING_OBSIDIAN;
|
||||
@ -47,4 +49,12 @@ class GlowingObsidian extends Solid{
|
||||
public function getBlastResistance() : float{
|
||||
return 50;
|
||||
}
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_DIAMOND;
|
||||
}
|
||||
}
|
||||
|
@ -23,12 +23,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\Player;
|
||||
|
||||
class GlowingRedstoneOre extends RedstoneOre{
|
||||
|
||||
protected $id = self::GLOWING_REDSTONE_ORE;
|
||||
|
||||
protected $itemId = self::REDSTONE_ORE;
|
||||
|
||||
public function getName() : string{
|
||||
return "Glowing Redstone Ore";
|
||||
}
|
||||
@ -37,13 +40,19 @@ class GlowingRedstoneOre extends RedstoneOre{
|
||||
return 9;
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_SCHEDULED or $type === Level::BLOCK_UPDATE_RANDOM){
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::REDSTONE_ORE, $this->meta), false, false);
|
||||
|
||||
return Level::BLOCK_UPDATE_WEAK;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
|
||||
}
|
||||
|
||||
public function ticksRandomly() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::REDSTONE_ORE, $this->meta), false, false);
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
use function mt_rand;
|
||||
|
||||
class Glowstone extends Transparent{
|
||||
|
||||
@ -44,16 +44,16 @@ class Glowstone extends Transparent{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getLightLevel() : int{
|
||||
return 15;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::GLOWSTONE_DUST, 0, mt_rand(2, 4))
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class Gold extends Solid{
|
||||
|
||||
@ -43,14 +42,10 @@ class Gold extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_IRON;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class GoldOre extends Solid{
|
||||
|
||||
@ -43,14 +42,10 @@ class GoldOre extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_IRON;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,14 +24,15 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\event\block\BlockSpreadEvent;
|
||||
use pocketmine\item\Hoe;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\Shovel;
|
||||
use pocketmine\level\generator\object\TallGrass as TallGrassObject;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\Random;
|
||||
use function mt_rand;
|
||||
|
||||
class Grass extends Solid{
|
||||
|
||||
@ -50,12 +51,12 @@ class Grass extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SHOVEL;
|
||||
return BlockToolType::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::DIRT, 0, 1)
|
||||
ItemFactory::get(Item::DIRT)
|
||||
];
|
||||
}
|
||||
|
||||
@ -63,43 +64,37 @@ class Grass extends Solid{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_RANDOM){
|
||||
$lightAbove = $this->level->getFullLightAt($this->x, $this->y + 1, $this->z);
|
||||
if($lightAbove < 4 and BlockFactory::$lightFilter[$this->level->getBlockIdAt($this->x, $this->y + 1, $this->z)] >= 3){ //2 plus 1 standard filter amount
|
||||
//grass dies
|
||||
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($this, $this, BlockFactory::get(Block::DIRT)));
|
||||
public function onRandomTick() : void{
|
||||
$lightAbove = $this->level->getFullLightAt($this->x, $this->y + 1, $this->z);
|
||||
if($lightAbove < 4 and BlockFactory::$lightFilter[$this->level->getBlockIdAt($this->x, $this->y + 1, $this->z)] >= 3){ //2 plus 1 standard filter amount
|
||||
//grass dies
|
||||
$ev = new BlockSpreadEvent($this, $this, BlockFactory::get(Block::DIRT));
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->level->setBlock($this, $ev->getNewState(), false, false);
|
||||
}
|
||||
}elseif($lightAbove >= 9){
|
||||
//try grass spread
|
||||
for($i = 0; $i < 4; ++$i){
|
||||
$x = mt_rand($this->x - 1, $this->x + 1);
|
||||
$y = mt_rand($this->y - 3, $this->y + 1);
|
||||
$z = mt_rand($this->z - 1, $this->z + 1);
|
||||
if(
|
||||
$this->level->getBlockIdAt($x, $y, $z) !== Block::DIRT or
|
||||
$this->level->getBlockDataAt($x, $y, $z) === 1 or
|
||||
$this->level->getFullLightAt($x, $y + 1, $z) < 4 or
|
||||
BlockFactory::$lightFilter[$this->level->getBlockIdAt($x, $y + 1, $z)] >= 3
|
||||
){
|
||||
continue;
|
||||
}
|
||||
|
||||
$ev = new BlockSpreadEvent($b = $this->level->getBlockAt($x, $y, $z), $this, BlockFactory::get(Block::GRASS));
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->level->setBlock($this, $ev->getNewState(), false, false);
|
||||
$this->level->setBlock($b, $ev->getNewState(), false, false);
|
||||
}
|
||||
|
||||
return Level::BLOCK_UPDATE_RANDOM;
|
||||
}elseif($lightAbove >= 9){
|
||||
//try grass spread
|
||||
for($i = 0; $i < 4; ++$i){
|
||||
$x = mt_rand($this->x - 1, $this->x + 1);
|
||||
$y = mt_rand($this->y - 3, $this->y + 1);
|
||||
$z = mt_rand($this->z - 1, $this->z + 1);
|
||||
if(
|
||||
$this->level->getBlockIdAt($x, $y, $z) !== Block::DIRT or
|
||||
$this->level->getBlockDataAt($x, $y, $z) === 1 or
|
||||
$this->level->getFullLightAt($x, $y + 1, $z) < 4 or
|
||||
BlockFactory::$lightFilter[$this->level->getBlockIdAt($x, $y + 1, $z)] >= 3
|
||||
){
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($b = $this->level->getBlockAt($x, $y, $z), $this, BlockFactory::get(Block::GRASS)));
|
||||
if(!$ev->isCancelled()){
|
||||
$this->level->setBlock($b, $ev->getNewState(), false, false);
|
||||
}
|
||||
}
|
||||
|
||||
return Level::BLOCK_UPDATE_RANDOM;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
@ -108,13 +103,13 @@ class Grass extends Solid{
|
||||
TallGrassObject::growGrass($this->getLevel(), $this, new Random(mt_rand()), 8, 2);
|
||||
|
||||
return true;
|
||||
}elseif($item->isHoe()){
|
||||
$item->useOn($this);
|
||||
}elseif($item instanceof Hoe){
|
||||
$item->applyDamage(1);
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND));
|
||||
|
||||
return true;
|
||||
}elseif($item->isShovel() and $this->getSide(Vector3::SIDE_UP)->getId() === Block::AIR){
|
||||
$item->useOn($this);
|
||||
}elseif($item instanceof Shovel and $this->getSide(Vector3::SIDE_UP)->getId() === Block::AIR){
|
||||
$item->applyDamage(1);
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::GRASS_PATH));
|
||||
|
||||
return true;
|
||||
|
@ -25,8 +25,6 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
|
||||
@ -43,7 +41,7 @@ class GrassPath extends Transparent{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SHOVEL;
|
||||
return BlockToolType::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
@ -61,18 +59,15 @@ class GrassPath extends Transparent{
|
||||
return 0.6;
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL and $this->getSide(Vector3::SIDE_UP)->isSolid()){
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Vector3::SIDE_UP)->isSolid()){
|
||||
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
||||
return $type;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::DIRT, 0, 1)
|
||||
ItemFactory::get(Item::DIRT)
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
use function mt_rand;
|
||||
|
||||
class Gravel extends Fallable{
|
||||
|
||||
@ -44,17 +44,16 @@ class Gravel extends Fallable{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SHOVEL;
|
||||
return BlockToolType::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
if(mt_rand(1, 10) === 1){
|
||||
return [
|
||||
ItemFactory::get(Item::FLINT, 0, 1)
|
||||
ItemFactory::get(Item::FLINT)
|
||||
];
|
||||
}
|
||||
|
||||
return parent::getDrops($item);
|
||||
return parent::getDropsForCompatibleTool($item);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class HardenedClay extends Solid{
|
||||
|
||||
@ -38,10 +38,14 @@ class HardenedClay extends Solid{
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 1.25;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user