mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-09 11:16:57 +00:00
Compare commits
1548 Commits
api/3.0.0-
...
3.8.0
Author | SHA1 | Date | |
---|---|---|---|
088fbf65b1 | |||
fa70127241 | |||
fc76d04dcb | |||
15ae323bcb | |||
353bae87a7 | |||
dc7be3fd52 | |||
f28a0740a0 | |||
df990fb47a | |||
98ca28d96e | |||
db896b9faf | |||
76c234e4e6 | |||
2ef3962028 | |||
1e5941c98c | |||
9ca7c0c883 | |||
b4a8f8391b | |||
142d750b9f | |||
948b0b4cbc | |||
d6b596a8ac | |||
eab2d4d704 | |||
8114551600 | |||
8e1d1993c5 | |||
82bf5f6193 | |||
76a86e51f7 | |||
d1e803685a | |||
0a884aa5fb | |||
c410e676b3 | |||
8f1f5fde47 | |||
0f268df2e0 | |||
86108e7010 | |||
5ea448ef36 | |||
389e7767d1 | |||
4c268acc00 | |||
e34a4f6b98 | |||
3925e598d6 | |||
383ec8a8e3 | |||
95313e0a90 | |||
e9a87978a6 | |||
612e9e162c | |||
fdc3faadc9 | |||
9644e72acf | |||
2c678dcf0d | |||
7bd9a2b2e0 | |||
5c26deb517 | |||
8fcb44de7d | |||
bd2e7db3b9 | |||
f4480c07ee | |||
c09e2301c8 | |||
8e9f787d33 | |||
89833b3b68 | |||
a10a656a5d | |||
2659ed8d91 | |||
9c01ecbe7e | |||
6a55021779 | |||
6ada261b04 | |||
14a6779e08 | |||
cce99b07af | |||
c3d80d711d | |||
1a8b33dafe | |||
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 | |||
54f7a88fbb |
@ -4,3 +4,7 @@ root = yes
|
|||||||
[*]
|
[*]
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
|
|
||||||
|
[*.yml]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
48
.github/ISSUE_TEMPLATE.md
vendored
48
.github/ISSUE_TEMPLATE.md
vendored
@ -1,48 +0,0 @@
|
|||||||
### Issue description
|
|
||||||
<!---
|
|
||||||
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
|
|
||||||
|
|
||||||
Any issues requesting updates to new versions of MCPE will be treated as spam.
|
|
||||||
Please do not create issues for missing/un-implemented gameplay features - they will be closed.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!--- Write a short description about the issue -->
|
|
||||||
|
|
||||||
<!--- If you are reporting a regression or unexpected behaviour, please include the below information: -->
|
|
||||||
- Expected result: What were you expecting to happen?
|
|
||||||
- Actual result: What actually happened?
|
|
||||||
|
|
||||||
### Steps to reproduce the issue
|
|
||||||
<!--- help us find the problem by adding steps to reproduce the issue -->
|
|
||||||
1. ...
|
|
||||||
2. ...
|
|
||||||
|
|
||||||
### OS and versions
|
|
||||||
<!--- use the 'version' command in PocketMine-MP
|
|
||||||
|
|
||||||
NOTE: LATEST is not a valid version. PocketMine-MP version should include Jenkins build number and/or git commit hash.
|
|
||||||
|
|
||||||
NO support whatsoever will be provided for third-party modified variants of PocketMine-MP. Issues relating to third-party modifications will be closed as spam.
|
|
||||||
|
|
||||||
Note that 32-bit platforms are no longer supported by PocketMine-MP and issues concerning 32-bit platforms will be closed.
|
|
||||||
-->
|
|
||||||
* PocketMine-MP:
|
|
||||||
* PHP:
|
|
||||||
* Server OS:
|
|
||||||
* Game version: PE/Win10 (delete as appropriate)
|
|
||||||
|
|
||||||
### Plugins
|
|
||||||
- Test on a clean server without plugins: is the issue reproducible without any plugins loaded?
|
|
||||||
|
|
||||||
If the issue is **not** reproducible without plugins:
|
|
||||||
- Have you asked for help on our forums before creating an issue?
|
|
||||||
- Can you provide sample, *minimal* reproducing code for the issue? If so, paste it in the bottom section
|
|
||||||
- Paste your list of plugins here (use the 'plugins' command in PocketMine-MP)
|
|
||||||
|
|
||||||
### 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
|
|
||||||
|
|
||||||
* ...
|
|
19
.github/ISSUE_TEMPLATE/api-change-request.md
vendored
Normal file
19
.github/ISSUE_TEMPLATE/api-change-request.md
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
name: API change request
|
||||||
|
about: Suggest a change, addition or removal to the plugin API
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--- tell us what you want -->
|
||||||
|
## Description
|
||||||
|
|
||||||
|
|
||||||
|
<!--- explain why you want this and why it's a good idea -->
|
||||||
|
## Justification
|
||||||
|
|
||||||
|
|
||||||
|
<!--- (optional) describe alternative methods you've explored to achieve your goal -->
|
||||||
|
## Alternative methods
|
36
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
36
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Unexpected non-crash behaviour (except missing gameplay features)
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Issue description
|
||||||
|
|
||||||
|
- Expected result: What were you expecting to happen?
|
||||||
|
- Actual result: What actually happened?
|
||||||
|
|
||||||
|
### Steps to reproduce the issue
|
||||||
|
1. ...
|
||||||
|
2. ...
|
||||||
|
|
||||||
|
### OS and versions
|
||||||
|
<!-- try the `version` command | LATEST IS NOT A VALID VERSION -->
|
||||||
|
* PocketMine-MP:
|
||||||
|
* PHP:
|
||||||
|
* Server OS:
|
||||||
|
* Game version: PE/Win10 (delete as appropriate)
|
||||||
|
|
||||||
|
### Plugins
|
||||||
|
<!--- use the `plugins` command and paste the output below -->
|
||||||
|
|
||||||
|
- If you remove all plugins, does the issue still occur?
|
||||||
|
- If the issue is **not** reproducible without plugins:
|
||||||
|
- Have you asked for help on our forums before creating an issue?
|
||||||
|
- Can you provide sample, *minimal* reproducing code for the issue? If so, paste it in the bottom section
|
||||||
|
|
||||||
|
### Crashdump, backtrace or other files
|
||||||
|
<!--- Submit crashdumps at https://crash.pmmp.io and paste a link -->
|
||||||
|
<!--- Use gist or anything else to add other files and add links here -->
|
15
.github/ISSUE_TEMPLATE/crash.md
vendored
Normal file
15
.github/ISSUE_TEMPLATE/crash.md
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
name: Crash
|
||||||
|
about: Report a crash in PocketMine-MP (not plugins)
|
||||||
|
title: Server crashed
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--- submit crashdump files to https://crash.pmmp.io -->
|
||||||
|
<!--- or, copy the data between ===BEGIN CRASH DUMP=== and ===END CRASH DUMP and paste it on a site like https://pastebin.com -->
|
||||||
|
Link to crashdump:
|
||||||
|
|
||||||
|
<!--- write additional information about the crash to help us find the problem -->
|
||||||
|
### Additional comments (optional)
|
14
.github/ISSUE_TEMPLATE/help---support.md
vendored
Normal file
14
.github/ISSUE_TEMPLATE/help---support.md
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
name: Help & support
|
||||||
|
about: We don't accept support requests here. Try the links on the README.
|
||||||
|
title: ''
|
||||||
|
labels: Support request
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
We don't accept support requests on the issue tracker. Please try the following links instead:
|
||||||
|
|
||||||
|
Documentation: http://pmmp.rtfd.io
|
||||||
|
Forums: https://forums.pmmp.io
|
||||||
|
Discord: https://discord.gg/bge7dYQ
|
12
.github/ISSUE_TEMPLATE/security-dos-vulnerability.md
vendored
Normal file
12
.github/ISSUE_TEMPLATE/security-dos-vulnerability.md
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
name: Security/DoS vulnerability
|
||||||
|
about: 'Bug or exploit that can be used to attack servers (hint: don''t report it
|
||||||
|
on a public issue tracker)'
|
||||||
|
title: ''
|
||||||
|
labels: 'Auto: Spam'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Please DO NOT report security vulnerabilities here.
|
||||||
|
Instead, send an email to team@pmmp.io or contact a developer directly, IN PRIVATE.
|
16
.github/support.yml
vendored
Normal file
16
.github/support.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Configuration for support-requests - https://github.com/dessant/support-requests
|
||||||
|
|
||||||
|
# Label used to mark issues as support requests
|
||||||
|
supportLabel: "Support request"
|
||||||
|
# Comment to post on issues marked as support requests. Add a link
|
||||||
|
# to a support page, or set to `false` to disable
|
||||||
|
supportComment: >
|
||||||
|
Thanks, but this issue tracker not intended for support requests. Please read the guidelines on [submitting an issue](https://github.com/pmmp/PocketMine-MP/blob/master/CONTRIBUTING.md#creating-an-issue).
|
||||||
|
|
||||||
|
|
||||||
|
[Docs](https://pmmp.rtfd.io) | [Discord](https://discord.gg/bge7dYQ) | [Forums](https://forums.pmmp.io)
|
||||||
|
|
||||||
|
# Whether to close issues marked as support requests
|
||||||
|
close: true
|
||||||
|
# Whether to lock issues marked as support requests
|
||||||
|
lock: false
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,5 +1,6 @@
|
|||||||
players/*
|
players/*
|
||||||
worlds/*
|
worlds/*
|
||||||
|
plugin_data/*
|
||||||
plugins/*
|
plugins/*
|
||||||
bin*/*
|
bin*/*
|
||||||
timings/*
|
timings/*
|
||||||
@ -9,8 +10,9 @@ crashdumps/*
|
|||||||
*.phar
|
*.phar
|
||||||
server.properties
|
server.properties
|
||||||
/pocketmine.yml
|
/pocketmine.yml
|
||||||
memoryDump_*/*
|
memory_dumps/*
|
||||||
resource_packs/
|
resource_packs/
|
||||||
|
server.lock
|
||||||
|
|
||||||
# Common IDEs
|
# Common IDEs
|
||||||
.idea/
|
.idea/
|
||||||
|
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -7,6 +7,6 @@
|
|||||||
[submodule "tests/plugins/PocketMine-DevTools"]
|
[submodule "tests/plugins/PocketMine-DevTools"]
|
||||||
path = tests/plugins/PocketMine-DevTools
|
path = tests/plugins/PocketMine-DevTools
|
||||||
url = https://github.com/pmmp/PocketMine-DevTools.git
|
url = https://github.com/pmmp/PocketMine-DevTools.git
|
||||||
[submodule "tests/plugins/PocketMine-TesterPlugin"]
|
[submodule "src/pocketmine/resources/vanilla"]
|
||||||
path = tests/plugins/PocketMine-TesterPlugin
|
path = src/pocketmine/resources/vanilla
|
||||||
url = https://github.com/pmmp/PocketMine-TesterPlugin.git
|
url = https://github.com/pmmp/BedrockData.git
|
||||||
|
@ -2,13 +2,14 @@ language: php
|
|||||||
|
|
||||||
php:
|
php:
|
||||||
- 7.2
|
- 7.2
|
||||||
|
- 7.3
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
# - pecl install channel://pecl.php.net/pthreads-3.1.6
|
# - pecl install channel://pecl.php.net/pthreads-3.1.6
|
||||||
- echo | pecl install channel://pecl.php.net/yaml-2.0.2
|
- echo | pecl install channel://pecl.php.net/yaml-2.0.4
|
||||||
- git clone https://github.com/krakjoe/pthreads.git
|
- git clone https://github.com/pmmp/pthreads.git
|
||||||
- cd pthreads
|
- cd pthreads
|
||||||
- git checkout d32079fb4a88e6e008104d36dbbf0c2dd7deb403
|
- git checkout 6ca019c58b4fa09ee2ff490f2444e34bef0773d0
|
||||||
- phpize
|
- phpize
|
||||||
- ./configure
|
- ./configure
|
||||||
- make
|
- make
|
||||||
@ -18,7 +19,7 @@ before_script:
|
|||||||
- composer install
|
- composer install
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- ./tests/travis.sh
|
- ./tests/travis.sh -t4
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
email: false
|
email: false
|
||||||
|
@ -42,7 +42,7 @@ We try to ensure that our project's codebase is as clean as possible and ensure
|
|||||||
- **Details should be provided of tests done.** Simply saying "Tested" or equivalent is not acceptable.
|
- **Details should be provided of tests done.** Simply saying "Tested" or equivalent is not acceptable.
|
||||||
|
|
||||||
### Code contributions
|
### Code contributions
|
||||||
- **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/)**.
|
- **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`.
|
- **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.
|
- **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.
|
- **Code should use the same style as in PocketMine-MP.** See [below](#code-syntax) for an example.
|
||||||
|
22
README.md
22
README.md
@ -1,6 +1,6 @@
|
|||||||
# [](https://pmmp.io)
|
# [](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)
|
[](https://travis-ci.org/pmmp/PocketMine-MP)
|
||||||
|
|
||||||
@ -10,13 +10,15 @@ If you don't find what you're looking for there, [talk to a human](#discussion).
|
|||||||
|
|
||||||
### Discussion
|
### Discussion
|
||||||
- [Forums](https://forums.pmmp.io/)
|
- [Forums](https://forums.pmmp.io/)
|
||||||
|
- [Community Discord](https://discord.gg/bge7dYQ)
|
||||||
|
|
||||||
### Plugins
|
### 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.
|
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.
|
||||||
|
|
||||||
### For developers
|
### For developers
|
||||||
* [Latest API documentation](https://jenkins.pmmp.io/job/PocketMine-MP-doc/doxygen/) - Doxygen documentation generated from development
|
* [Latest API documentation](https://jenkins.pmmp.io/job/PocketMine-MP-doc/doxygen/) - Doxygen documentation generated from development
|
||||||
* [DevTools](https://github.com/pmmp/PocketMine-DevTools/) - A development tools plugin for creating plugins.
|
* [DevTools](https://github.com/pmmp/PocketMine-DevTools/) - Development tools plugin for creating plugins
|
||||||
|
* [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
|
||||||
|
|
||||||
### Can I contribute?
|
### Can I contribute?
|
||||||
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.
|
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.
|
||||||
@ -27,17 +29,11 @@ Yes you can! Contributions are welcomed provided that they comply with our [Cont
|
|||||||
|
|
||||||
**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.
|
**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.
|
||||||
|
|
||||||
## Third-party Libraries/Protocols Used
|
### Donate
|
||||||
* __[PHP Sockets](http://php.net/manual/en/book.sockets.php)__
|
Donations help support the development of the project and pay for our expenses.
|
||||||
* __[PHP mbstring](http://php.net/manual/en/book.mbstring.php)__
|
- Bitcoin Cash (BCH): `qz9p8dqkv0r7aahdatu5uewqfkvstrglv58f8yle07`
|
||||||
* __[PHP BCMath](http://php.net/manual/en/book.bc.php)__
|
- Bitcoin (BTC): `1PVAyDJ2g7kcjCxAC3C89oxpV2ZYcLad8T`
|
||||||
* __[PHP pthreads](http://pthreads.org/)__ by _[krakjoe](https://github.com/krakjoe)_: Threading for PHP - Share Nothing, Do Everything.
|
- [Patreon](https://www.patreon.com/pocketminemp)
|
||||||
* __[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)__
|
|
||||||
|
|
||||||
## Licensing information
|
## Licensing information
|
||||||
|
|
||||||
|
@ -5,9 +5,12 @@
|
|||||||
"homepage": "https://pmmp.io",
|
"homepage": "https://pmmp.io",
|
||||||
"license": "LGPL-3.0",
|
"license": "LGPL-3.0",
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.2.0RC3",
|
"php": ">=7.2.0",
|
||||||
|
"php-64bit": "*",
|
||||||
"ext-bcmath": "*",
|
"ext-bcmath": "*",
|
||||||
"ext-curl": "*",
|
"ext-curl": "*",
|
||||||
|
"ext-ctype": "*",
|
||||||
|
"ext-date": "*",
|
||||||
"ext-hash": "*",
|
"ext-hash": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-mbstring": "*",
|
"ext-mbstring": "*",
|
||||||
@ -21,16 +24,25 @@
|
|||||||
"ext-yaml": ">=2.0.0",
|
"ext-yaml": ">=2.0.0",
|
||||||
"ext-zip": "*",
|
"ext-zip": "*",
|
||||||
"ext-zlib": ">=1.2.11",
|
"ext-zlib": ">=1.2.11",
|
||||||
"pocketmine/raklib": "dev-master#eaa85c2b23bbc1a85030a621d4644c0e33e05950",
|
"pocketmine/raklib": "^0.12.0",
|
||||||
"pocketmine/pocketmine-spl": "^0.2.0",
|
"pocketmine/spl": "^0.3.0",
|
||||||
"pocketmine/pocketmine-binaryutils": "dev-master#a7cd5303a3b215d26bf9be76682ce9311f40e887",
|
"pocketmine/binaryutils": "^0.1.0",
|
||||||
"pocketmine/pocketmine-nbt": "dev-master#f8934c0aed90d1f55452588f7ebef7c4519518a5"
|
"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": {
|
"autoload": {
|
||||||
"psr-0": {
|
"psr-4": {
|
||||||
"": ["src"]
|
"": ["src"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"pocketmine\\": "tests/phpunit/"
|
||||||
|
}
|
||||||
|
},
|
||||||
"repositories": [
|
"repositories": [
|
||||||
{
|
{
|
||||||
"type": "vcs",
|
"type": "vcs",
|
||||||
@ -38,15 +50,23 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "vcs",
|
"type": "vcs",
|
||||||
"url": "https://github.com/pmmp/PocketMine-SPL"
|
"url": "https://github.com/pmmp/SPL"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "vcs",
|
"type": "vcs",
|
||||||
"url": "https://github.com/pmmp/PocketMine-BinaryUtils"
|
"url": "https://github.com/pmmp/BinaryUtils"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "vcs",
|
"type": "vcs",
|
||||||
"url": "https://github.com/pmmp/PocketMine-NBT"
|
"url": "https://github.com/pmmp/NBT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "vcs",
|
||||||
|
"url": "https://github.com/pmmp/Math"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "vcs",
|
||||||
|
"url": "https://github.com/pmmp/Snooze"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
309
composer.lock
generated
309
composer.lock
generated
@ -1,27 +1,112 @@
|
|||||||
{
|
{
|
||||||
"_readme": [
|
"_readme": [
|
||||||
"This file locks the dependencies of your project to a known state",
|
"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"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "5997f272811ed1148e7699a33335a0d2",
|
"content-hash": "2f5313e4ebd7b62c785cf683b27464b4",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "pocketmine/pocketmine-binaryutils",
|
"name": "adhocore/json-comment",
|
||||||
"version": "dev-master",
|
"version": "v0.0.7",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/pmmp/PocketMine-BinaryUtils.git",
|
"url": "https://github.com/adhocore/php-json-comment.git",
|
||||||
"reference": "a7cd5303a3b215d26bf9be76682ce9311f40e887"
|
"reference": "135356c7e7336ef59924f1d921c770045f937a76"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/pmmp/PocketMine-BinaryUtils/zipball/a7cd5303a3b215d26bf9be76682ce9311f40e887",
|
"url": "https://api.github.com/repos/adhocore/php-json-comment/zipball/135356c7e7336ef59924f1d921c770045f937a76",
|
||||||
"reference": "a7cd5303a3b215d26bf9be76682ce9311f40e887",
|
"reference": "135356c7e7336ef59924f1d921c770045f937a76",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.2"
|
"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",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -34,28 +119,64 @@
|
|||||||
],
|
],
|
||||||
"description": "Classes and methods for conveniently handling binary data",
|
"description": "Classes and methods for conveniently handling binary data",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/pmmp/PocketMine-BinaryUtils/tree/master",
|
"source": "https://github.com/pmmp/BinaryUtils/tree/0.1.8",
|
||||||
"issues": "https://github.com/pmmp/PocketMine-BinaryUtils/issues"
|
"issues": "https://github.com/pmmp/BinaryUtils/issues"
|
||||||
},
|
},
|
||||||
"time": "2018-01-14T18:53:25+00:00"
|
"time": "2019-01-16T17:31:44+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pocketmine/pocketmine-nbt",
|
"name": "pocketmine/math",
|
||||||
"version": "dev-master",
|
"version": "0.2.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/pmmp/PocketMine-NBT.git",
|
"url": "https://github.com/pmmp/Math.git",
|
||||||
"reference": "f8934c0aed90d1f55452588f7ebef7c4519518a5"
|
"reference": "b755d3fb7025c4ddb7d9d6df0ba7e0b65125e51c"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/pmmp/PocketMine-NBT/zipball/f8934c0aed90d1f55452588f7ebef7c4519518a5",
|
"url": "https://api.github.com/repos/pmmp/Math/zipball/b755d3fb7025c4ddb7d9d6df0ba7e0b65125e51c",
|
||||||
"reference": "f8934c0aed90d1f55452588f7ebef7c4519518a5",
|
"reference": "b755d3fb7025c4ddb7d9d6df0ba7e0b65125e51c",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.2.0",
|
"php": ">=7.2.0",
|
||||||
"pocketmine/pocketmine-binaryutils": "dev-master#8bb34e771fee69abcc5482d17d2fa0b4f0e15a5e"
|
"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.7",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/pmmp/NBT.git",
|
||||||
|
"reference": "2f176c9f2fd9b31db8bc2ada2f38990157ec8f1a"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/pmmp/NBT/zipball/2f176c9f2fd9b31db8bc2ada2f38990157ec8f1a",
|
||||||
|
"reference": "2f176c9f2fd9b31db8bc2ada2f38990157ec8f1a",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-zlib": "*",
|
||||||
|
"php": ">=7.2.0",
|
||||||
|
"php-64bit": "*",
|
||||||
|
"pocketmine/binaryutils": "^0.1.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -63,28 +184,108 @@
|
|||||||
"pocketmine\\nbt\\": "src/"
|
"pocketmine\\nbt\\": "src/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"pocketmine\\nbt\\": "tests/phpunit/"
|
||||||
|
}
|
||||||
|
},
|
||||||
"license": [
|
"license": [
|
||||||
"LGPL-3.0"
|
"LGPL-3.0"
|
||||||
],
|
],
|
||||||
"description": "PHP library for working with Named Binary Tags",
|
"description": "PHP library for working with Named Binary Tags",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/pmmp/PocketMine-NBT/tree/master",
|
"source": "https://github.com/pmmp/NBT/tree/0.2.7",
|
||||||
"issues": "https://github.com/pmmp/PocketMine-NBT/issues"
|
"issues": "https://github.com/pmmp/NBT/issues"
|
||||||
},
|
},
|
||||||
"time": "2018-01-11T13:51:50+00:00"
|
"time": "2019-03-29T19:39:42+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pocketmine/pocketmine-spl",
|
"name": "pocketmine/raklib",
|
||||||
"version": "0.2.0",
|
"version": "0.12.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/pmmp/PocketMine-SPL.git",
|
"url": "https://github.com/pmmp/RakLib.git",
|
||||||
"reference": "70c591a44b6c5aa541a1a55585764bed2b23148c"
|
"reference": "9df7dbcdafeb29403af6a7fa22c8785f758a1145"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/pmmp/PocketMine-SPL/zipball/70c591a44b6c5aa541a1a55585764bed2b23148c",
|
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/9df7dbcdafeb29403af6a7fa22c8785f758a1145",
|
||||||
"reference": "70c591a44b6c5aa541a1a55585764bed2b23148c",
|
"reference": "9df7dbcdafeb29403af6a7fa22c8785f758a1145",
|
||||||
|
"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.3",
|
||||||
|
"issues": "https://github.com/pmmp/RakLib/issues"
|
||||||
|
},
|
||||||
|
"time": "2019-04-21T12:15:38+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": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
@ -101,65 +302,27 @@
|
|||||||
],
|
],
|
||||||
"description": "Standard library files required by PocketMine-MP and related projects",
|
"description": "Standard library files required by PocketMine-MP and related projects",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/pmmp/PocketMine-SPL/tree/master"
|
"source": "https://github.com/pmmp/SPL/tree/0.3.2"
|
||||||
},
|
},
|
||||||
"time": "2018-01-11T13:03:01+00:00"
|
"time": "2018-08-12T15:17:39+00:00"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "pocketmine/raklib",
|
|
||||||
"version": "dev-master",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/pmmp/RakLib.git",
|
|
||||||
"reference": "eaa85c2b23bbc1a85030a621d4644c0e33e05950"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/eaa85c2b23bbc1a85030a621d4644c0e33e05950",
|
|
||||||
"reference": "eaa85c2b23bbc1a85030a621d4644c0e33e05950",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"ext-bcmath": "*",
|
|
||||||
"ext-pthreads": ">=3.1.7dev",
|
|
||||||
"ext-sockets": "*",
|
|
||||||
"php": ">=7.2.0RC3",
|
|
||||||
"pocketmine/pocketmine-binaryutils": "dev-master#a7cd5303a3b215d26bf9be76682ce9311f40e887",
|
|
||||||
"pocketmine/pocketmine-spl": "^0.2.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": "2018-01-27T15:38:43+00:00"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [],
|
"packages-dev": [],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
"stability-flags": {
|
"stability-flags": {
|
||||||
"php": 5,
|
|
||||||
"ext-pthreads": 20,
|
"ext-pthreads": 20,
|
||||||
"pocketmine/raklib": 20,
|
"daverandom/callback-validator": 20
|
||||||
"pocketmine/pocketmine-binaryutils": 20,
|
|
||||||
"pocketmine/pocketmine-nbt": 20
|
|
||||||
},
|
},
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": {
|
"platform": {
|
||||||
"php": ">=7.2.0RC3",
|
"php": ">=7.2.0",
|
||||||
|
"php-64bit": "*",
|
||||||
"ext-bcmath": "*",
|
"ext-bcmath": "*",
|
||||||
"ext-curl": "*",
|
"ext-curl": "*",
|
||||||
|
"ext-ctype": "*",
|
||||||
|
"ext-date": "*",
|
||||||
"ext-hash": "*",
|
"ext-hash": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-mbstring": "*",
|
"ext-mbstring": "*",
|
||||||
|
File diff suppressed because it is too large
Load Diff
10
doxygen/index.md
Normal file
10
doxygen/index.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
## PocketMine-MP API Documentation
|
||||||
|
|
||||||
|
This site contains auto-generated API documentation for PocketMine-MP (and dependencies which are not outsourced). Documentation here is regenerated for every release.
|
||||||
|
|
||||||
|
This site can be accessed via https://apidoc.pmmp.io.
|
||||||
|
|
||||||
|
### Additional developer resources
|
||||||
|
- [DevTools](https://github.com/pmmp/PocketMine-DevTools/) - Development tools plugin for creating plugins
|
||||||
|
- [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
|
||||||
|
- [DeveloperDocs](https://github.com/pmmp/DeveloperDocs/) - Reference, guides and specifications for the PocketMine-MP API
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine;
|
namespace pocketmine;
|
||||||
|
|
||||||
use pocketmine\event\TranslationContainer;
|
use pocketmine\lang\TranslationContainer;
|
||||||
use pocketmine\utils\TextFormat;
|
use pocketmine\utils\TextFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -116,7 +116,7 @@ abstract class Achievement{
|
|||||||
public static function broadcast(Player $player, string $achievementId) : bool{
|
public static function broadcast(Player $player, string $achievementId) : bool{
|
||||||
if(isset(Achievement::$list[$achievementId])){
|
if(isset(Achievement::$list[$achievementId])){
|
||||||
$translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"] . TextFormat::RESET]);
|
$translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"] . TextFormat::RESET]);
|
||||||
if(Server::getInstance()->getConfigBool("announce-player-achievements", true) === true){
|
if(Server::getInstance()->getConfigBool("announce-player-achievements", true)){
|
||||||
Server::getInstance()->broadcastMessage($translation);
|
Server::getInstance()->broadcastMessage($translation);
|
||||||
}else{
|
}else{
|
||||||
$player->sendMessage($translation);
|
$player->sendMessage($translation);
|
||||||
@ -147,6 +147,4 @@ abstract class Achievement{
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,9 +30,70 @@ use pocketmine\plugin\PluginManager;
|
|||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
use pocketmine\utils\VersionString;
|
use pocketmine\utils\VersionString;
|
||||||
use raklib\RakLib;
|
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{
|
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 */
|
/** @var Server */
|
||||||
private $server;
|
private $server;
|
||||||
private $fp;
|
private $fp;
|
||||||
@ -54,6 +115,7 @@ class CrashDump{
|
|||||||
if(!is_resource($this->fp)){
|
if(!is_resource($this->fp)){
|
||||||
throw new \RuntimeException("Could not create Crash Dump");
|
throw new \RuntimeException("Could not create Crash Dump");
|
||||||
}
|
}
|
||||||
|
$this->data["format_version"] = self::FORMAT_VERSION;
|
||||||
$this->data["time"] = $this->time;
|
$this->data["time"] = $this->time;
|
||||||
$this->addLine($this->server->getName() . " Crash Dump " . date("D M j H:i:s T Y", $this->time));
|
$this->addLine($this->server->getName() . " Crash Dump " . date("D M j H:i:s T Y", $this->time));
|
||||||
$this->addLine();
|
$this->addLine();
|
||||||
@ -64,6 +126,8 @@ class CrashDump{
|
|||||||
$this->extraData();
|
$this->extraData();
|
||||||
|
|
||||||
$this->encodeData();
|
$this->encodeData();
|
||||||
|
|
||||||
|
fclose($this->fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPath() : string{
|
public function getPath() : string{
|
||||||
@ -83,7 +147,11 @@ class CrashDump{
|
|||||||
$this->addLine("----------------------REPORT THE DATA BELOW THIS LINE-----------------------");
|
$this->addLine("----------------------REPORT THE DATA BELOW THIS LINE-----------------------");
|
||||||
$this->addLine();
|
$this->addLine();
|
||||||
$this->addLine("===BEGIN CRASH DUMP===");
|
$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){
|
foreach(str_split(base64_encode($this->encodedData), 76) as $line){
|
||||||
$this->addLine($line);
|
$this->addLine($line);
|
||||||
}
|
}
|
||||||
@ -115,10 +183,10 @@ class CrashDump{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function extraData(){
|
private function extraData(){
|
||||||
global $arguments;
|
global $argv;
|
||||||
|
|
||||||
if($this->server->getProperty("auto-report.send-settings", true) !== false){
|
if($this->server->getProperty("auto-report.send-settings", true) !== false){
|
||||||
$this->data["parameters"] = (array) $arguments;
|
$this->data["parameters"] = (array) $argv;
|
||||||
$this->data["server.properties"] = @file_get_contents($this->server->getDataPath() . "server.properties");
|
$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["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");
|
$this->data["pocketmine.yml"] = @file_get_contents($this->server->getDataPath() . "pocketmine.yml");
|
||||||
@ -148,7 +216,7 @@ class CrashDump{
|
|||||||
$error = $lastExceptionError;
|
$error = $lastExceptionError;
|
||||||
}else{
|
}else{
|
||||||
$error = (array) error_get_last();
|
$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 = [
|
$errorConversion = [
|
||||||
E_ERROR => "E_ERROR",
|
E_ERROR => "E_ERROR",
|
||||||
E_WARNING => "E_WARNING",
|
E_WARNING => "E_WARNING",
|
||||||
@ -167,7 +235,7 @@ class CrashDump{
|
|||||||
E_USER_DEPRECATED => "E_USER_DEPRECATED"
|
E_USER_DEPRECATED => "E_USER_DEPRECATED"
|
||||||
];
|
];
|
||||||
$error["fullFile"] = $error["file"];
|
$error["fullFile"] = $error["file"];
|
||||||
$error["file"] = cleanPath($error["file"]);
|
$error["file"] = Utils::cleanPath($error["file"]);
|
||||||
$error["type"] = $errorConversion[$error["type"]] ?? $error["type"];
|
$error["type"] = $errorConversion[$error["type"]] ?? $error["type"];
|
||||||
if(($pos = strpos($error["message"], "\n")) !== false){
|
if(($pos = strpos($error["message"], "\n")) !== false){
|
||||||
$error["message"] = substr($error["message"], 0, $pos);
|
$error["message"] = substr($error["message"], 0, $pos);
|
||||||
@ -175,6 +243,9 @@ class CrashDump{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(isset($lastError)){
|
if(isset($lastError)){
|
||||||
|
if(isset($lastError["trace"])){
|
||||||
|
$lastError["trace"] = Utils::printableTrace($lastError["trace"]);
|
||||||
|
}
|
||||||
$this->data["lastError"] = $lastError;
|
$this->data["lastError"] = $lastError;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,54 +257,74 @@ class CrashDump{
|
|||||||
$this->addLine("Line: " . $error["line"]);
|
$this->addLine("Line: " . $error["line"]);
|
||||||
$this->addLine("Type: " . $error["type"]);
|
$this->addLine("Type: " . $error["type"]);
|
||||||
|
|
||||||
if(strpos($error["file"], "src/pocketmine/") === false and strpos($error["file"], "vendor/pocketmine/") === false and file_exists($error["fullFile"])){
|
$this->data["plugin_involvement"] = self::PLUGIN_INVOLVEMENT_NONE;
|
||||||
$this->addLine();
|
if(!$this->determinePluginFromFile($error["fullFile"], true)){ //fatal errors won't leave any stack trace
|
||||||
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
|
foreach($error["trace"] as $frame){
|
||||||
$this->data["plugin"] = true;
|
if(!isset($frame["file"])){
|
||||||
|
continue; //PHP core
|
||||||
$reflection = new \ReflectionClass(PluginBase::class);
|
}
|
||||||
$file = $reflection->getProperty("file");
|
if($this->determinePluginFromFile($frame["file"], false)){
|
||||||
$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());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
|
||||||
$this->data["plugin"] = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->addLine();
|
$this->addLine();
|
||||||
$this->addLine("Code:");
|
$this->addLine("Code:");
|
||||||
$this->data["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);
|
$file = @file($error["fullFile"], FILE_IGNORE_NEW_LINES);
|
||||||
for($l = max(0, $error["line"] - 10); $l < $error["line"] + 10; ++$l){
|
for($l = max(0, $error["line"] - 10); $l < $error["line"] + 10 and isset($file[$l]); ++$l){
|
||||||
$this->addLine("[" . ($l + 1) . "] " . @$file[$l]);
|
$this->addLine("[" . ($l + 1) . "] " . $file[$l]);
|
||||||
$this->data["code"][$l + 1] = @$file[$l];
|
$this->data["code"][$l + 1] = $file[$l];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->addLine();
|
$this->addLine();
|
||||||
$this->addLine("Backtrace:");
|
$this->addLine("Backtrace:");
|
||||||
foreach(($this->data["trace"] = $error["trace"]) as $line){
|
foreach(($this->data["trace"] = Utils::printableTrace($error["trace"])) as $line){
|
||||||
$this->addLine($line);
|
$this->addLine($line);
|
||||||
}
|
}
|
||||||
$this->addLine();
|
$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(){
|
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"] = [];
|
||||||
$this->data["general"]["name"] = $this->server->getName();
|
$this->data["general"]["name"] = $this->server->getName();
|
||||||
$this->data["general"]["version"] = $version->get(false);
|
$this->data["general"]["base_version"] = \pocketmine\BASE_VERSION;
|
||||||
$this->data["general"]["build"] = $version->getBuild();
|
$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"]["protocol"] = ProtocolInfo::CURRENT_PROTOCOL;
|
||||||
$this->data["general"]["api"] = \pocketmine\API_VERSION;
|
|
||||||
$this->data["general"]["git"] = \pocketmine\GIT_COMMIT;
|
$this->data["general"]["git"] = \pocketmine\GIT_COMMIT;
|
||||||
$this->data["general"]["raklib"] = RakLib::VERSION;
|
$this->data["general"]["raklib"] = RakLib::VERSION;
|
||||||
$this->data["general"]["uname"] = php_uname("a");
|
$this->data["general"]["uname"] = php_uname("a");
|
||||||
@ -241,7 +332,7 @@ class CrashDump{
|
|||||||
$this->data["general"]["zend"] = zend_version();
|
$this->data["general"]["zend"] = zend_version();
|
||||||
$this->data["general"]["php_os"] = PHP_OS;
|
$this->data["general"]["php_os"] = PHP_OS;
|
||||||
$this->data["general"]["os"] = Utils::getOS();
|
$this->data["general"]["os"] = Utils::getOS();
|
||||||
$this->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("Git commit: " . GIT_COMMIT);
|
||||||
$this->addLine("uname -a: " . php_uname("a"));
|
$this->addLine("uname -a: " . php_uname("a"));
|
||||||
$this->addLine("PHP Version: " . phpversion());
|
$this->addLine("PHP Version: " . phpversion());
|
||||||
@ -256,5 +347,4 @@ class CrashDump{
|
|||||||
public function add($str){
|
public function add($str){
|
||||||
fwrite($this->fp, $str);
|
fwrite($this->fp, $str);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,11 +24,43 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine;
|
namespace pocketmine;
|
||||||
|
|
||||||
use pocketmine\event\server\LowMemoryEvent;
|
use pocketmine\event\server\LowMemoryEvent;
|
||||||
use pocketmine\event\Timings;
|
|
||||||
use pocketmine\scheduler\DumpWorkerMemoryTask;
|
use pocketmine\scheduler\DumpWorkerMemoryTask;
|
||||||
use pocketmine\scheduler\GarbageCollectionTask;
|
use pocketmine\scheduler\GarbageCollectionTask;
|
||||||
use pocketmine\utils\MainLogger;
|
use pocketmine\timings\Timings;
|
||||||
use pocketmine\utils\Utils;
|
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{
|
class MemoryManager{
|
||||||
|
|
||||||
@ -186,7 +218,7 @@ class MemoryManager{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$ev = new LowMemoryEvent($memory, $limit, $global, $triggerCount);
|
$ev = new LowMemoryEvent($memory, $limit, $global, $triggerCount);
|
||||||
$this->server->getPluginManager()->callEvent($ev);
|
$ev->call();
|
||||||
|
|
||||||
$cycles = 0;
|
$cycles = 0;
|
||||||
if($this->garbageCollectionTrigger){
|
if($this->garbageCollectionTrigger){
|
||||||
@ -243,9 +275,12 @@ class MemoryManager{
|
|||||||
Timings::$garbageCollectorTimer->startTiming();
|
Timings::$garbageCollectorTimer->startTiming();
|
||||||
|
|
||||||
if($this->garbageCollectionAsync){
|
if($this->garbageCollectionAsync){
|
||||||
$size = $this->server->getScheduler()->getAsyncTaskPoolSize();
|
$pool = $this->server->getAsyncPool();
|
||||||
for($i = 0; $i < $size; ++$i){
|
if(($w = $pool->shutdownUnusedWorkers()) > 0){
|
||||||
$this->server->getScheduler()->scheduleAsyncTaskToWorker(new GarbageCollectionTask(), $i);
|
$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
|
* @param int $maxStringSize
|
||||||
*/
|
*/
|
||||||
public function dumpServerMemory(string $outputFolder, int $maxNesting, 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");
|
$this->server->getLogger()->notice("[Dump] After the memory dump is done, the server might crash");
|
||||||
self::dumpMemory($this->server, $outputFolder, $maxNesting, $maxStringSize);
|
self::dumpMemory($this->server, $outputFolder, $maxNesting, $maxStringSize, $this->server->getLogger());
|
||||||
|
|
||||||
if($this->dumpWorkers){
|
if($this->dumpWorkers){
|
||||||
$scheduler = $this->server->getScheduler();
|
$pool = $this->server->getAsyncPool();
|
||||||
for($i = 0, $size = $scheduler->getAsyncTaskPoolSize(); $i < $size; ++$i){
|
foreach($pool->getRunningWorkers() as $i){
|
||||||
$scheduler->scheduleAsyncTaskToWorker(new DumpWorkerMemoryTask($outputFolder, $maxNesting, $maxStringSize), $i);
|
$pool->submitTaskToWorker(new DumpWorkerMemoryTask($outputFolder, $maxNesting, $maxStringSize), $i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -278,14 +313,15 @@ class MemoryManager{
|
|||||||
/**
|
/**
|
||||||
* Static memory dumper accessible from any thread.
|
* Static memory dumper accessible from any thread.
|
||||||
*
|
*
|
||||||
* @param mixed $startingObject
|
* @param mixed $startingObject
|
||||||
* @param string $outputFolder
|
* @param string $outputFolder
|
||||||
* @param int $maxNesting
|
* @param int $maxNesting
|
||||||
* @param int $maxStringSize
|
* @param int $maxStringSize
|
||||||
|
* @param \Logger $logger
|
||||||
*
|
*
|
||||||
* @throws \ReflectionException
|
* @throws \ReflectionException
|
||||||
*/
|
*/
|
||||||
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize){
|
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger){
|
||||||
$hardLimit = ini_get('memory_limit');
|
$hardLimit = ini_get('memory_limit');
|
||||||
ini_set('memory_limit', '-1');
|
ini_set('memory_limit', '-1');
|
||||||
gc_disable();
|
gc_disable();
|
||||||
@ -329,7 +365,7 @@ class MemoryManager{
|
|||||||
}
|
}
|
||||||
|
|
||||||
file_put_contents($outputFolder . "/staticProperties.js", json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
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(isset($GLOBALS)){ //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 = [];
|
$globalVariables = [];
|
||||||
@ -357,7 +393,7 @@ class MemoryManager{
|
|||||||
}
|
}
|
||||||
|
|
||||||
file_put_contents($outputFolder . "/globalVariables.js", json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
file_put_contents($outputFolder . "/globalVariables.js", json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||||
MainLogger::getLogger()->info("[Dump] Wrote $globalCount global variables");
|
$logger->info("[Dump] Wrote $globalCount global variables");
|
||||||
}
|
}
|
||||||
|
|
||||||
self::continueDump($startingObject, $data, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
self::continueDump($startingObject, $data, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||||
@ -394,15 +430,22 @@ class MemoryManager{
|
|||||||
$info["implements"] = implode(", ", $reflection->getInterfaceNames());
|
$info["implements"] = implode(", ", $reflection->getInterfaceNames());
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($reflection->getProperties() as $property){
|
for($original = $reflection; $reflection !== false; $reflection = $reflection->getParentClass()){
|
||||||
if($property->isStatic()){
|
foreach($reflection->getProperties() as $property){
|
||||||
continue;
|
if($property->isStatic()){
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(!$property->isPublic()){
|
$name = $property->getName();
|
||||||
$property->setAccessible(true);
|
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");
|
fwrite($obData, "$hash@$className: " . json_encode($info, JSON_UNESCAPED_SLASHES) . "\n");
|
||||||
@ -411,7 +454,7 @@ class MemoryManager{
|
|||||||
|
|
||||||
}while($continue);
|
}while($continue);
|
||||||
|
|
||||||
MainLogger::getLogger()->info("[Dump] Wrote " . count($objects) . " objects");
|
$logger->info("[Dump] Wrote " . count($objects) . " objects");
|
||||||
|
|
||||||
fclose($obData);
|
fclose($obData);
|
||||||
|
|
||||||
@ -421,7 +464,7 @@ class MemoryManager{
|
|||||||
arsort($instanceCounts, SORT_NUMERIC);
|
arsort($instanceCounts, SORT_NUMERIC);
|
||||||
file_put_contents($outputFolder . "/instanceCounts.js", json_encode($instanceCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
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);
|
ini_set('memory_limit', $hardLimit);
|
||||||
gc_enable();
|
gc_enable();
|
||||||
@ -463,7 +506,7 @@ class MemoryManager{
|
|||||||
self::continueDump($value, $data[$key], $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize);
|
self::continueDump($value, $data[$key], $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize);
|
||||||
}
|
}
|
||||||
}elseif(is_string($from)){
|
}elseif(is_string($from)){
|
||||||
$data = "(string) len(". strlen($from) .") " . substr(Utils::printable($from), 0, $maxStringSize);
|
$data = "(string) len(" . strlen($from) . ") " . substr(Utils::printable($from), 0, $maxStringSize);
|
||||||
}elseif(is_resource($from)){
|
}elseif(is_resource($from)){
|
||||||
$data = "(resource) " . print_r($from, true);
|
$data = "(resource) " . print_r($from, true);
|
||||||
}else{
|
}else{
|
||||||
|
@ -35,7 +35,7 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
|||||||
/** @var Server */
|
/** @var Server */
|
||||||
private $server;
|
private $server;
|
||||||
/** @var CompoundTag|null */
|
/** @var CompoundTag|null */
|
||||||
private $namedtag;
|
private $namedtag = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Server $server
|
* @param Server $server
|
||||||
@ -44,10 +44,8 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
|||||||
public function __construct(Server $server, string $name){
|
public function __construct(Server $server, string $name){
|
||||||
$this->server = $server;
|
$this->server = $server;
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
if(file_exists($this->server->getDataPath() . "players/" . strtolower($this->getName()) . ".dat")){
|
if($this->server->hasOfflinePlayerData($this->name)){
|
||||||
$this->namedtag = $this->server->getOfflinePlayerData($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{
|
public function isOp() : bool{
|
||||||
return $this->server->isOp(strtolower($this->getName()));
|
return $this->server->isOp($this->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setOp(bool $value){
|
public function setOp(bool $value){
|
||||||
@ -72,39 +70,39 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($value === true){
|
if($value){
|
||||||
$this->server->addOp(strtolower($this->getName()));
|
$this->server->addOp($this->name);
|
||||||
}else{
|
}else{
|
||||||
$this->server->removeOp(strtolower($this->getName()));
|
$this->server->removeOp($this->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isBanned() : bool{
|
public function isBanned() : bool{
|
||||||
return $this->server->getNameBans()->isBanned(strtolower($this->getName()));
|
return $this->server->getNameBans()->isBanned($this->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setBanned(bool $value){
|
public function setBanned(bool $value){
|
||||||
if($value === true){
|
if($value){
|
||||||
$this->server->getNameBans()->addBan($this->getName(), null, null, null);
|
$this->server->getNameBans()->addBan($this->name, null, null, null);
|
||||||
}else{
|
}else{
|
||||||
$this->server->getNameBans()->remove($this->getName());
|
$this->server->getNameBans()->remove($this->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isWhitelisted() : bool{
|
public function isWhitelisted() : bool{
|
||||||
return $this->server->isWhitelisted(strtolower($this->getName()));
|
return $this->server->isWhitelisted($this->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setWhitelisted(bool $value){
|
public function setWhitelisted(bool $value){
|
||||||
if($value === true){
|
if($value){
|
||||||
$this->server->addWhitelist(strtolower($this->getName()));
|
$this->server->addWhitelist($this->name);
|
||||||
}else{
|
}else{
|
||||||
$this->server->removeWhitelist(strtolower($this->getName()));
|
$this->server->removeWhitelist($this->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPlayer(){
|
public function getPlayer(){
|
||||||
return $this->server->getPlayerExact($this->getName());
|
return $this->server->getPlayerExact($this->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFirstPlayed(){
|
public function getFirstPlayed(){
|
||||||
@ -134,6 +132,4 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
|||||||
public function removeMetadata(string $metadataKey, Plugin $owningPlugin){
|
public function removeMetadata(string $metadataKey, Plugin $owningPlugin){
|
||||||
$this->server->getPlayerMetadata()->removeMetadata($this, $metadataKey, $owningPlugin);
|
$this->server->getPlayerMetadata()->removeMetadata($this, $metadataKey, $owningPlugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -24,134 +24,141 @@ declare(strict_types=1);
|
|||||||
namespace {
|
namespace {
|
||||||
const INT32_MIN = -0x80000000;
|
const INT32_MIN = -0x80000000;
|
||||||
const INT32_MAX = 0x7fffffff;
|
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 {
|
namespace pocketmine {
|
||||||
|
|
||||||
use pocketmine\utils\Binary;
|
|
||||||
use pocketmine\utils\MainLogger;
|
use pocketmine\utils\MainLogger;
|
||||||
use pocketmine\utils\ServerKiller;
|
use pocketmine\utils\ServerKiller;
|
||||||
use pocketmine\utils\Terminal;
|
use pocketmine\utils\Terminal;
|
||||||
|
use pocketmine\utils\Timezone;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
|
use pocketmine\utils\VersionString;
|
||||||
use pocketmine\wizard\SetupWizard;
|
use pocketmine\wizard\SetupWizard;
|
||||||
use raklib\RakLib;
|
|
||||||
|
|
||||||
const NAME = "PocketMine-MP";
|
require_once __DIR__ . '/VersionInfo.php';
|
||||||
const VERSION = "1.7dev";
|
|
||||||
const API_VERSION = "3.0.0-ALPHA11";
|
|
||||||
const CODENAME = "[REDACTED]";
|
|
||||||
|
|
||||||
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.
|
* 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.
|
* 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.
|
* 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;
|
* @return string[]
|
||||||
echo "[CRITICAL] Please use the installer provided on the homepage, or update to a newer PHP version." . PHP_EOL;
|
*/
|
||||||
exit(1);
|
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")){
|
if(!empty($messages = check_platform_dependencies())){
|
||||||
echo "[CRITICAL] Unable to find the pthreads extension." . PHP_EOL;
|
echo PHP_EOL;
|
||||||
echo "[CRITICAL] Please use the installer provided on the homepage." . 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);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
unset($messages);
|
||||||
|
|
||||||
error_reporting(-1);
|
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) !== ""){
|
if(\Phar::running(true) !== ""){
|
||||||
define('pocketmine\PATH', \Phar::running(true) . "/");
|
define('pocketmine\PATH', \Phar::running(true) . "/");
|
||||||
}else{
|
}else{
|
||||||
define('pocketmine\PATH', dirname(__FILE__, 3) . DIRECTORY_SEPARATOR);
|
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){
|
if(\pocketmine\COMPOSER_AUTOLOADER_PATH !== false and is_file(\pocketmine\COMPOSER_AUTOLOADER_PATH)){
|
||||||
echo "[CRITICAL] $message" . PHP_EOL;
|
require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH);
|
||||||
echo "[CRITICAL] Please install/update Composer dependencies or use provided builds." . PHP_EOL;
|
}else{
|
||||||
|
critical_error("Composer autoloader not found at " . $bootstrap);
|
||||||
|
critical_error("Please install/update Composer dependencies or use provided builds.");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_file(\pocketmine\COMPOSER_AUTOLOADER_PATH)){
|
set_error_handler([Utils::class, 'errorExceptionHandler']);
|
||||||
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.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
|
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
|
||||||
@ -167,378 +174,76 @@ namespace pocketmine {
|
|||||||
ini_set("default_charset", "utf-8");
|
ini_set("default_charset", "utf-8");
|
||||||
|
|
||||||
ini_set("memory_limit", '-1');
|
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);
|
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 : \realpath(\getcwd()) . DIRECTORY_SEPARATOR);
|
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);
|
define('pocketmine\PLUGIN_PATH', isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR);
|
||||||
|
|
||||||
Terminal::init();
|
|
||||||
|
|
||||||
define('pocketmine\ANSI', Terminal::hasFormattingCodes());
|
|
||||||
|
|
||||||
if(!file_exists(\pocketmine\DATA)){
|
if(!file_exists(\pocketmine\DATA)){
|
||||||
mkdir(\pocketmine\DATA, 0777, true);
|
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.
|
define('pocketmine\LOCK_FILE_PATH', \pocketmine\DATA . 'server.lock');
|
||||||
date_default_timezone_set("UTC");
|
define('pocketmine\LOCK_FILE', fopen(\pocketmine\LOCK_FILE_PATH, "cb"));
|
||||||
|
if(!flock(\pocketmine\LOCK_FILE, LOCK_EX | LOCK_NB)){
|
||||||
|
critical_error("Another " . \pocketmine\NAME . " instance is already using this folder (" . realpath(\pocketmine\DATA) . ").");
|
||||||
|
critical_error("Please stop the other server first before running a new one.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Logger has a dependency on timezone
|
||||||
|
$tzError = Timezone::init();
|
||||||
|
|
||||||
$logger = new MainLogger(\pocketmine\DATA . "server.log");
|
$logger = new MainLogger(\pocketmine\DATA . "server.log");
|
||||||
$logger->registerStatic();
|
$logger->registerStatic();
|
||||||
|
|
||||||
do{
|
foreach($tzError as $e){
|
||||||
$timezone = ini_get("date.timezone");
|
$logger->warning($e);
|
||||||
if($timezone !== ""){
|
}
|
||||||
/*
|
unset($tzError);
|
||||||
* 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(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(strpos($timezone, "/") === false){
|
}
|
||||||
$default_timezone = timezone_name_from_abbr($timezone);
|
if(!extension_loaded("pocketmine_chunkutils")){
|
||||||
if($default_timezone !== false){
|
$logger->warning("ChunkUtils extension is missing. Anvil-format worlds will experience degraded performance.");
|
||||||
ini_set("date.timezone", $default_timezone);
|
}
|
||||||
date_default_timezone_set($default_timezone);
|
|
||||||
break;
|
if(\Phar::running(true) === ""){
|
||||||
}else{
|
$logger->warning("Non-packaged " . \pocketmine\NAME . " installation detected. Consider using a phar in production for better performance.");
|
||||||
//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");
|
|
||||||
}
|
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
|
||||||
}else{
|
define('pocketmine\VERSION', $version->getFullVersion(true));
|
||||||
date_default_timezone_set($timezone);
|
|
||||||
break;
|
$gitHash = str_repeat("00", 20);
|
||||||
|
|
||||||
|
if(\Phar::running(true) === ""){
|
||||||
|
if(Utils::execute("git rev-parse HEAD", $out) === 0 and $out !== false and strlen($out = trim($out)) === 40){
|
||||||
|
$gitHash = trim($out);
|
||||||
|
if(Utils::execute("git diff --quiet") === 1 or Utils::execute("git diff --cached --quiet") === 1){ //Locally-modified
|
||||||
|
$gitHash .= "-dirty";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
if(($timezone = detect_system_timezone()) and date_default_timezone_set($timezone)){
|
$phar = new \Phar(\Phar::running(false));
|
||||||
//Success! Timezone has already been set and validated in the if statement.
|
$meta = $phar->getMetadata();
|
||||||
//This here is just for redundancy just in case some program wants to read timezone data from the ini.
|
if(isset($meta["git"])){
|
||||||
ini_set("date.timezone", $timezone);
|
$gitHash = $meta["git"];
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||||
* @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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$parsed = date_parse($offset);
|
|
||||||
$offset = $parsed['hour'] * 3600 + $parsed['minute'] * 60 + $parsed['second'];
|
|
||||||
|
|
||||||
//After date_parse is done, put the sign back
|
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
|
||||||
if($negative_offset == true){
|
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors
|
||||||
$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){
|
|
||||||
global $logger;
|
|
||||||
if($logger instanceof MainLogger){
|
|
||||||
$logger->syncFlushBuffer();
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
$exitCode = 0;
|
$exitCode = 0;
|
||||||
|
|
||||||
do{
|
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",
|
|
||||||
"openssl" => "OpenSSL",
|
|
||||||
"sockets" => "Sockets",
|
|
||||||
"yaml" => "YAML",
|
|
||||||
"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("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"])){
|
if(!file_exists(\pocketmine\DATA . "server.properties") and !isset($opts["no-wizard"])){
|
||||||
$installer = new SetupWizard();
|
$installer = new SetupWizard();
|
||||||
if(!$installer->run()){
|
if(!$installer->run()){
|
||||||
@ -547,25 +252,22 @@ namespace pocketmine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: move this to a Server field
|
||||||
if(\Phar::running(true) === ""){
|
define('pocketmine\START_TIME', microtime(true));
|
||||||
$logger->warning("Non-packaged " . \pocketmine\NAME . " installation detected. Consider using a phar in production for better performance.");
|
|
||||||
}
|
|
||||||
|
|
||||||
ThreadManager::init();
|
ThreadManager::init();
|
||||||
new Server($autoloader, $logger, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
|
new Server($autoloader, $logger, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
|
||||||
|
|
||||||
$logger->info("Stopping other threads");
|
$logger->info("Stopping other threads");
|
||||||
|
|
||||||
$killer = new ServerKiller(8);
|
$killer = new ServerKiller(8);
|
||||||
$killer->start();
|
$killer->start(PTHREADS_INHERIT_NONE);
|
||||||
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
|
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
|
||||||
|
|
||||||
if(ThreadManager::getInstance()->stopAll() > 0){
|
if(ThreadManager::getInstance()->stopAll() > 0){
|
||||||
if(\pocketmine\DEBUG > 1){
|
if(\pocketmine\DEBUG > 1){
|
||||||
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
|
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
|
||||||
}
|
}
|
||||||
kill(getmypid());
|
Utils::kill(getmypid());
|
||||||
}
|
}
|
||||||
}while(false);
|
}while(false);
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -28,7 +28,7 @@ namespace pocketmine;
|
|||||||
*/
|
*/
|
||||||
abstract class Thread extends \Thread{
|
abstract class Thread extends \Thread{
|
||||||
|
|
||||||
/** @var \ClassLoader */
|
/** @var \ClassLoader|null */
|
||||||
protected $classLoader;
|
protected $classLoader;
|
||||||
/** @var string|null */
|
/** @var string|null */
|
||||||
protected $composerAutoloaderPath;
|
protected $composerAutoloaderPath;
|
||||||
@ -67,14 +67,10 @@ abstract class Thread extends \Thread{
|
|||||||
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
||||||
ThreadManager::getInstance()->add($this);
|
ThreadManager::getInstance()->add($this);
|
||||||
|
|
||||||
if(!$this->isRunning() and !$this->isJoined() and !$this->isTerminated()){
|
if($this->getClassLoader() === null){
|
||||||
if($this->getClassLoader() === null){
|
$this->setClassLoader();
|
||||||
$this->setClassLoader();
|
|
||||||
}
|
|
||||||
return parent::start($options);
|
|
||||||
}
|
}
|
||||||
|
return parent::start($options);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,12 +79,9 @@ abstract class Thread extends \Thread{
|
|||||||
public function quit(){
|
public function quit(){
|
||||||
$this->isKilled = true;
|
$this->isKilled = true;
|
||||||
|
|
||||||
$this->notify();
|
|
||||||
|
|
||||||
if(!$this->isJoined()){
|
if(!$this->isJoined()){
|
||||||
if(!$this->isTerminated()){
|
$this->notify();
|
||||||
$this->join();
|
$this->join();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadManager::getInstance()->remove($this);
|
ThreadManager::getInstance()->remove($this);
|
||||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine;
|
namespace pocketmine;
|
||||||
|
|
||||||
use pocketmine\utils\MainLogger;
|
use pocketmine\utils\MainLogger;
|
||||||
|
use function spl_object_hash;
|
||||||
|
|
||||||
class ThreadManager extends \Volatile{
|
class ThreadManager extends \Volatile{
|
||||||
|
|
||||||
|
27
src/pocketmine/VersionInfo.php
Normal file
27
src/pocketmine/VersionInfo.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?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/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace pocketmine;
|
||||||
|
|
||||||
|
const NAME = "PocketMine-MP";
|
||||||
|
const BASE_VERSION = "3.8.0";
|
||||||
|
const IS_DEVELOPMENT_BUILD = false;
|
||||||
|
const BUILD_NUMBER = 0;
|
@ -28,7 +28,7 @@ namespace pocketmine;
|
|||||||
*/
|
*/
|
||||||
abstract class Worker extends \Worker{
|
abstract class Worker extends \Worker{
|
||||||
|
|
||||||
/** @var \ClassLoader */
|
/** @var \ClassLoader|null */
|
||||||
protected $classLoader;
|
protected $classLoader;
|
||||||
/** @var string|null */
|
/** @var string|null */
|
||||||
protected $composerAutoloaderPath;
|
protected $composerAutoloaderPath;
|
||||||
@ -67,14 +67,10 @@ abstract class Worker extends \Worker{
|
|||||||
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
||||||
ThreadManager::getInstance()->add($this);
|
ThreadManager::getInstance()->add($this);
|
||||||
|
|
||||||
if(!$this->isRunning() and !$this->isJoined() and !$this->isTerminated()){
|
if($this->getClassLoader() === null){
|
||||||
if($this->getClassLoader() === null){
|
$this->setClassLoader();
|
||||||
$this->setClassLoader();
|
|
||||||
}
|
|
||||||
return parent::start($options);
|
|
||||||
}
|
}
|
||||||
|
return parent::start($options);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,16 +79,10 @@ abstract class Worker extends \Worker{
|
|||||||
public function quit(){
|
public function quit(){
|
||||||
$this->isKilled = true;
|
$this->isKilled = true;
|
||||||
|
|
||||||
$this->notify();
|
|
||||||
|
|
||||||
if($this->isRunning()){
|
if($this->isRunning()){
|
||||||
$this->shutdown();
|
while($this->unstack() !== null);
|
||||||
$this->notify();
|
$this->notify();
|
||||||
$this->unstack();
|
$this->shutdown();
|
||||||
}elseif(!$this->isJoined()){
|
|
||||||
if(!$this->isTerminated()){
|
|
||||||
$this->join();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadManager::getInstance()->remove($this);
|
ThreadManager::getInstance()->remove($this);
|
||||||
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
class ActivatorRail extends Rail{
|
class ActivatorRail extends RedstoneRail{
|
||||||
|
|
||||||
protected $id = self::ACTIVATOR_RAIL;
|
protected $id = self::ACTIVATOR_RAIL;
|
||||||
|
|
||||||
|
@ -81,5 +81,4 @@ class Air extends Transparent{
|
|||||||
public function getBlastResistance() : float{
|
public function getBlastResistance() : float{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\inventory\AnvilInventory;
|
use pocketmine\inventory\AnvilInventory;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
|
||||||
use pocketmine\item\TieredTool;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
@ -55,13 +54,17 @@ class Anvil extends Fallable{
|
|||||||
return 6000;
|
return 6000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getVariantBitmask() : int{
|
||||||
|
return 0x0c;
|
||||||
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
static $names = [
|
static $names = [
|
||||||
self::TYPE_NORMAL => "Anvil",
|
self::TYPE_NORMAL => "Anvil",
|
||||||
self::TYPE_SLIGHTLY_DAMAGED => "Slightly Damaged Anvil",
|
self::TYPE_SLIGHTLY_DAMAGED => "Slightly Damaged Anvil",
|
||||||
self::TYPE_VERY_DAMAGED => "Very Damaged Anvil"
|
self::TYPE_VERY_DAMAGED => "Very Damaged Anvil"
|
||||||
];
|
];
|
||||||
return $names[$this->meta & 0x0c] ?? "Anvil";
|
return $names[$this->getVariant()] ?? "Anvil";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
@ -106,13 +109,7 @@ class Anvil extends Fallable{
|
|||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
$direction = ($player !== null ? $player->getDirection() : 0) & 0x03;
|
$direction = ($player !== null ? $player->getDirection() : 0) & 0x03;
|
||||||
$this->meta = ($this->meta & 0x0c) | $direction;
|
$this->meta = $this->getVariant() | $direction;
|
||||||
return $this->getLevel()->setBlock($blockReplace, $this, true, true);
|
return $this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
|
||||||
return [
|
|
||||||
ItemFactory::get($this->getItemId(), $this->getDamage() & 0x0c)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\event\TranslationContainer;
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
|
use pocketmine\lang\TranslationContainer;
|
||||||
use pocketmine\level\Level;
|
use pocketmine\level\Level;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
@ -85,7 +85,7 @@ class Bed extends Transparent{
|
|||||||
|
|
||||||
$this->getLevel()->setBlock($this, $this, false, false);
|
$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);
|
$other->setOccupied($occupied);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -176,7 +176,7 @@ class Bed extends Transparent{
|
|||||||
if(!$down->isTransparent()){
|
if(!$down->isTransparent()){
|
||||||
$meta = (($player instanceof Player ? $player->getDirection() : 0) - 1) & 0x03;
|
$meta = (($player instanceof Player ? $player->getDirection() : 0) - 1) & 0x03;
|
||||||
$next = $this->getSide(self::getOtherHalfSide($meta));
|
$next = $this->getSide(self::getOtherHalfSide($meta));
|
||||||
if($next->canBeReplaced() === 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($blockReplace, BlockFactory::get($this->id, $meta), true, true);
|
||||||
$this->getLevel()->setBlock($next, BlockFactory::get($this->id, $meta | self::BITFLAG_HEAD), true, true);
|
$this->getLevel()->setBlock($next, BlockFactory::get($this->id, $meta | self::BITFLAG_HEAD), true, true);
|
||||||
|
|
||||||
@ -192,21 +192,25 @@ class Bed extends Transparent{
|
|||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
if($this->isHeadPart()){
|
if($this->isHeadPart()){
|
||||||
$tile = $this->getLevel()->getTile($this);
|
return [$this->getItem()];
|
||||||
if($tile instanceof TileBed){
|
|
||||||
return [
|
|
||||||
ItemFactory::get($this->getItemId(), $tile->getColor())
|
|
||||||
];
|
|
||||||
}else{
|
|
||||||
return [
|
|
||||||
ItemFactory::get($this->getItemId(), 14) //Red
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [];
|
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{
|
public function isAffectedBySilkTouch() : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -48,5 +48,4 @@ class Bedrock extends Solid{
|
|||||||
public function isBreakable(Item $item) : bool{
|
public function isBreakable(Item $item) : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class Beetroot extends Crops{
|
class Beetroot extends Crops{
|
||||||
|
|
||||||
|
@ -30,15 +30,18 @@ use pocketmine\entity\Entity;
|
|||||||
use pocketmine\item\enchantment\Enchantment;
|
use pocketmine\item\enchantment\Enchantment;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\level\Position;
|
use pocketmine\level\Position;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\RayTraceResult;
|
use pocketmine\math\RayTraceResult;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\metadata\Metadatable;
|
use pocketmine\metadata\Metadatable;
|
||||||
use pocketmine\metadata\MetadataValue;
|
use pocketmine\metadata\MetadataValue;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\plugin\Plugin;
|
use pocketmine\plugin\Plugin;
|
||||||
|
use function array_merge;
|
||||||
|
use function get_class;
|
||||||
|
use const PHP_INT_MAX;
|
||||||
|
|
||||||
class Block extends Position implements BlockIds, Metadatable{
|
class Block extends Position implements BlockIds, Metadatable{
|
||||||
|
|
||||||
@ -110,6 +113,14 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
return $this->itemId ?? $this->getId();
|
return $this->itemId ?? $this->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getRuntimeId() : int{
|
||||||
|
return RuntimeBlockMapping::toStaticRuntimeId($this->getId(), $this->getDamage());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
@ -259,6 +270,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
* @param Item $item
|
* @param Item $item
|
||||||
*
|
*
|
||||||
* @return float
|
* @return float
|
||||||
|
* @throws \InvalidArgumentException if the item efficiency is not a positive number
|
||||||
*/
|
*/
|
||||||
public function getBreakTime(Item $item) : float{
|
public function getBreakTime(Item $item) : float{
|
||||||
$base = $this->getHardness();
|
$base = $this->getHardness();
|
||||||
@ -270,7 +282,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
|
|
||||||
$efficiency = $item->getMiningEfficiency($this);
|
$efficiency = $item->getMiningEfficiency($this);
|
||||||
if($efficiency <= 0){
|
if($efficiency <= 0){
|
||||||
throw new \RuntimeException("Item efficiency is invalid");
|
throw new \InvalidArgumentException(get_class($item) . " has invalid mining efficiency: expected >= 0, got $efficiency");
|
||||||
}
|
}
|
||||||
|
|
||||||
$base /= $efficiency;
|
$base /= $efficiency;
|
||||||
@ -278,6 +290,12 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
return $base;
|
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.
|
* Returns whether random block updates will be done on this block.
|
||||||
@ -289,14 +307,18 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fires a block update on the Block
|
* Called when this block is randomly updated due to chunk ticking.
|
||||||
*
|
* WARNING: This will not be called if ticksRandomly() does not return true!
|
||||||
* @param int $type
|
|
||||||
*
|
|
||||||
* @return bool|int
|
|
||||||
*/
|
*/
|
||||||
public function onUpdate(int $type){
|
public function onRandomTick() : void{
|
||||||
return false;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when this block is updated by the delayed blockupdate scheduler in the level.
|
||||||
|
*/
|
||||||
|
public function onScheduledUpdate() : void{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -319,14 +341,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
* @return float
|
|
||||||
*/
|
|
||||||
public function getResistance() : float{
|
|
||||||
return $this->getBlastResistance();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the block's resistance to explosions. Usually 5x hardness.
|
* Returns the block's resistance to explosions. Usually 5x hardness.
|
||||||
* @return float
|
* @return float
|
||||||
@ -470,6 +484,30 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns how much XP will be dropped by breaking this block with the given item.
|
||||||
|
*
|
||||||
|
* @param Item $item
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getXpDropForTool(Item $item) : int{
|
||||||
|
if($item->hasEnchantment(Enchantment::SILK_TOUCH) or !$this->isCompatibleWithTool($item)){
|
||||||
|
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
|
* Returns whether Silk Touch enchanted tools will cause this block to drop as itself. Since most blocks drop
|
||||||
* themselves anyway, this is implicitly true.
|
* themselves anyway, this is implicitly true.
|
||||||
@ -496,6 +534,50 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
return 0;
|
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()
|
* Returns the Block on the side $side, works like Vector3::getSide()
|
||||||
*
|
*
|
||||||
@ -504,7 +586,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
*
|
*
|
||||||
* @return Block
|
* @return Block
|
||||||
*/
|
*/
|
||||||
public function getSide($side, $step = 1){
|
public function getSide(int $side, int $step = 1){
|
||||||
if($this->isValid()){
|
if($this->isValid()){
|
||||||
return $this->getLevel()->getBlock(Vector3::getSide($side, $step));
|
return $this->getLevel()->getBlock(Vector3::getSide($side, $step));
|
||||||
}
|
}
|
||||||
@ -566,9 +648,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function collidesWithBB(AxisAlignedBB $bb) : bool{
|
public function collidesWithBB(AxisAlignedBB $bb) : bool{
|
||||||
$bbs = $this->getCollisionBoxes();
|
foreach($this->getCollisionBoxes() as $bb2){
|
||||||
|
|
||||||
foreach($bbs as $bb2){
|
|
||||||
if($bb->intersectsWith($bb2)){
|
if($bb->intersectsWith($bb2)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -673,30 +753,30 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function setMetadata(string $metadataKey, MetadataValue $newMetadataValue){
|
public function setMetadata(string $metadataKey, MetadataValue $newMetadataValue){
|
||||||
if($this->getLevel() instanceof Level){
|
if($this->isValid()){
|
||||||
$this->getLevel()->getBlockMetadata()->setMetadata($this, $metadataKey, $newMetadataValue);
|
$this->level->getBlockMetadata()->setMetadata($this, $metadataKey, $newMetadataValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMetadata(string $metadataKey){
|
public function getMetadata(string $metadataKey){
|
||||||
if($this->getLevel() instanceof Level){
|
if($this->isValid()){
|
||||||
return $this->getLevel()->getBlockMetadata()->getMetadata($this, $metadataKey);
|
return $this->level->getBlockMetadata()->getMetadata($this, $metadataKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasMetadata(string $metadataKey) : bool{
|
public function hasMetadata(string $metadataKey) : bool{
|
||||||
if($this->getLevel() instanceof Level){
|
if($this->isValid()){
|
||||||
return $this->getLevel()->getBlockMetadata()->hasMetadata($this, $metadataKey);
|
return $this->level->getBlockMetadata()->hasMetadata($this, $metadataKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function removeMetadata(string $metadataKey, Plugin $owningPlugin){
|
public function removeMetadata(string $metadataKey, Plugin $owningPlugin){
|
||||||
if($this->getLevel() instanceof Level){
|
if($this->isValid()){
|
||||||
$this->getLevel()->getBlockMetadata()->removeMetadata($this, $metadataKey, $owningPlugin);
|
$this->level->getBlockMetadata()->removeMetadata($this, $metadataKey, $owningPlugin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,13 +25,13 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Position;
|
use pocketmine\level\Position;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping;
|
||||||
|
use function min;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages block registration and instance creation
|
* Manages block registration and instance creation
|
||||||
*/
|
*/
|
||||||
class BlockFactory{
|
class BlockFactory{
|
||||||
/** @var \SplFixedArray<Block> */
|
|
||||||
private static $list = null;
|
|
||||||
/** @var \SplFixedArray<Block> */
|
/** @var \SplFixedArray<Block> */
|
||||||
private static $fullList = null;
|
private static $fullList = null;
|
||||||
|
|
||||||
@ -53,281 +53,280 @@ class BlockFactory{
|
|||||||
/**
|
/**
|
||||||
* Initializes the block factory. By default this is called only once on server start, however you may wish to use
|
* Initializes the block factory. By default this is called only once on server start, however you may wish to use
|
||||||
* this if you need to reset the block factory back to its original defaults for whatever reason.
|
* 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{
|
public static function init() : void{
|
||||||
if(self::$list === null or $force){
|
self::$fullList = new \SplFixedArray(4096);
|
||||||
self::$list = new \SplFixedArray(256);
|
|
||||||
self::$fullList = new \SplFixedArray(4096);
|
|
||||||
|
|
||||||
self::$light = new \SplFixedArray(256);
|
self::$light = new \SplFixedArray(256);
|
||||||
self::$lightFilter = new \SplFixedArray(256);
|
self::$lightFilter = new \SplFixedArray(256);
|
||||||
self::$solid = new \SplFixedArray(256);
|
self::$solid = new \SplFixedArray(256);
|
||||||
self::$hardness = new \SplFixedArray(256);
|
self::$hardness = new \SplFixedArray(256);
|
||||||
self::$transparent = new \SplFixedArray(256);
|
self::$transparent = new \SplFixedArray(256);
|
||||||
self::$diffusesSkyLight = new \SplFixedArray(256);
|
self::$diffusesSkyLight = new \SplFixedArray(256);
|
||||||
self::$blastResistance = new \SplFixedArray(256);
|
self::$blastResistance = new \SplFixedArray(256);
|
||||||
|
|
||||||
self::registerBlock(new Air());
|
self::registerBlock(new Air());
|
||||||
self::registerBlock(new Stone());
|
self::registerBlock(new Stone());
|
||||||
self::registerBlock(new Grass());
|
self::registerBlock(new Grass());
|
||||||
self::registerBlock(new Dirt());
|
self::registerBlock(new Dirt());
|
||||||
self::registerBlock(new Cobblestone());
|
self::registerBlock(new Cobblestone());
|
||||||
self::registerBlock(new Planks());
|
self::registerBlock(new Planks());
|
||||||
self::registerBlock(new Sapling());
|
self::registerBlock(new Sapling());
|
||||||
self::registerBlock(new Bedrock());
|
self::registerBlock(new Bedrock());
|
||||||
self::registerBlock(new Water());
|
self::registerBlock(new Water());
|
||||||
self::registerBlock(new StillWater());
|
self::registerBlock(new StillWater());
|
||||||
self::registerBlock(new Lava());
|
self::registerBlock(new Lava());
|
||||||
self::registerBlock(new StillLava());
|
self::registerBlock(new StillLava());
|
||||||
self::registerBlock(new Sand());
|
self::registerBlock(new Sand());
|
||||||
self::registerBlock(new Gravel());
|
self::registerBlock(new Gravel());
|
||||||
self::registerBlock(new GoldOre());
|
self::registerBlock(new GoldOre());
|
||||||
self::registerBlock(new IronOre());
|
self::registerBlock(new IronOre());
|
||||||
self::registerBlock(new CoalOre());
|
self::registerBlock(new CoalOre());
|
||||||
self::registerBlock(new Wood());
|
self::registerBlock(new Wood());
|
||||||
self::registerBlock(new Leaves());
|
self::registerBlock(new Leaves());
|
||||||
self::registerBlock(new Sponge());
|
self::registerBlock(new Sponge());
|
||||||
self::registerBlock(new Glass());
|
self::registerBlock(new Glass());
|
||||||
self::registerBlock(new LapisOre());
|
self::registerBlock(new LapisOre());
|
||||||
self::registerBlock(new Lapis());
|
self::registerBlock(new Lapis());
|
||||||
//TODO: DISPENSER
|
//TODO: DISPENSER
|
||||||
self::registerBlock(new Sandstone());
|
self::registerBlock(new Sandstone());
|
||||||
self::registerBlock(new NoteBlock());
|
self::registerBlock(new NoteBlock());
|
||||||
self::registerBlock(new Bed());
|
self::registerBlock(new Bed());
|
||||||
self::registerBlock(new PoweredRail());
|
self::registerBlock(new PoweredRail());
|
||||||
self::registerBlock(new DetectorRail());
|
self::registerBlock(new DetectorRail());
|
||||||
//TODO: STICKY_PISTON
|
//TODO: STICKY_PISTON
|
||||||
self::registerBlock(new Cobweb());
|
self::registerBlock(new Cobweb());
|
||||||
self::registerBlock(new TallGrass());
|
self::registerBlock(new TallGrass());
|
||||||
self::registerBlock(new DeadBush());
|
self::registerBlock(new DeadBush());
|
||||||
//TODO: PISTON
|
//TODO: PISTON
|
||||||
//TODO: PISTONARMCOLLISION
|
//TODO: PISTONARMCOLLISION
|
||||||
self::registerBlock(new Wool());
|
self::registerBlock(new Wool());
|
||||||
|
|
||||||
self::registerBlock(new Dandelion());
|
self::registerBlock(new Dandelion());
|
||||||
self::registerBlock(new Flower());
|
self::registerBlock(new Flower());
|
||||||
self::registerBlock(new BrownMushroom());
|
self::registerBlock(new BrownMushroom());
|
||||||
self::registerBlock(new RedMushroom());
|
self::registerBlock(new RedMushroom());
|
||||||
self::registerBlock(new Gold());
|
self::registerBlock(new Gold());
|
||||||
self::registerBlock(new Iron());
|
self::registerBlock(new Iron());
|
||||||
self::registerBlock(new DoubleStoneSlab());
|
self::registerBlock(new DoubleStoneSlab());
|
||||||
self::registerBlock(new StoneSlab());
|
self::registerBlock(new StoneSlab());
|
||||||
self::registerBlock(new Bricks());
|
self::registerBlock(new Bricks());
|
||||||
self::registerBlock(new TNT());
|
self::registerBlock(new TNT());
|
||||||
self::registerBlock(new Bookshelf());
|
self::registerBlock(new Bookshelf());
|
||||||
self::registerBlock(new MossyCobblestone());
|
self::registerBlock(new MossyCobblestone());
|
||||||
self::registerBlock(new Obsidian());
|
self::registerBlock(new Obsidian());
|
||||||
self::registerBlock(new Torch());
|
self::registerBlock(new Torch());
|
||||||
self::registerBlock(new Fire());
|
self::registerBlock(new Fire());
|
||||||
self::registerBlock(new MonsterSpawner());
|
self::registerBlock(new MonsterSpawner());
|
||||||
self::registerBlock(new WoodenStairs(Block::OAK_STAIRS, 0, "Oak Stairs"));
|
self::registerBlock(new WoodenStairs(Block::OAK_STAIRS, 0, "Oak Stairs"));
|
||||||
self::registerBlock(new Chest());
|
self::registerBlock(new Chest());
|
||||||
//TODO: REDSTONE_WIRE
|
//TODO: REDSTONE_WIRE
|
||||||
self::registerBlock(new DiamondOre());
|
self::registerBlock(new DiamondOre());
|
||||||
self::registerBlock(new Diamond());
|
self::registerBlock(new Diamond());
|
||||||
self::registerBlock(new CraftingTable());
|
self::registerBlock(new CraftingTable());
|
||||||
self::registerBlock(new Wheat());
|
self::registerBlock(new Wheat());
|
||||||
self::registerBlock(new Farmland());
|
self::registerBlock(new Farmland());
|
||||||
self::registerBlock(new Furnace());
|
self::registerBlock(new Furnace());
|
||||||
self::registerBlock(new BurningFurnace());
|
self::registerBlock(new BurningFurnace());
|
||||||
self::registerBlock(new SignPost());
|
self::registerBlock(new SignPost());
|
||||||
self::registerBlock(new WoodenDoor(Block::OAK_DOOR_BLOCK, 0, "Oak Door", Item::OAK_DOOR));
|
self::registerBlock(new WoodenDoor(Block::OAK_DOOR_BLOCK, 0, "Oak Door", Item::OAK_DOOR));
|
||||||
self::registerBlock(new Ladder());
|
self::registerBlock(new Ladder());
|
||||||
self::registerBlock(new Rail());
|
self::registerBlock(new Rail());
|
||||||
self::registerBlock(new CobblestoneStairs());
|
self::registerBlock(new CobblestoneStairs());
|
||||||
self::registerBlock(new WallSign());
|
self::registerBlock(new WallSign());
|
||||||
self::registerBlock(new Lever());
|
self::registerBlock(new Lever());
|
||||||
self::registerBlock(new StonePressurePlate());
|
self::registerBlock(new StonePressurePlate());
|
||||||
self::registerBlock(new IronDoor());
|
self::registerBlock(new IronDoor());
|
||||||
self::registerBlock(new WoodenPressurePlate());
|
self::registerBlock(new WoodenPressurePlate());
|
||||||
self::registerBlock(new RedstoneOre());
|
self::registerBlock(new RedstoneOre());
|
||||||
self::registerBlock(new GlowingRedstoneOre());
|
self::registerBlock(new GlowingRedstoneOre());
|
||||||
self::registerBlock(new RedstoneTorchUnlit());
|
self::registerBlock(new RedstoneTorchUnlit());
|
||||||
self::registerBlock(new RedstoneTorch());
|
self::registerBlock(new RedstoneTorch());
|
||||||
self::registerBlock(new StoneButton());
|
self::registerBlock(new StoneButton());
|
||||||
self::registerBlock(new SnowLayer());
|
self::registerBlock(new SnowLayer());
|
||||||
self::registerBlock(new Ice());
|
self::registerBlock(new Ice());
|
||||||
self::registerBlock(new Snow());
|
self::registerBlock(new Snow());
|
||||||
self::registerBlock(new Cactus());
|
self::registerBlock(new Cactus());
|
||||||
self::registerBlock(new Clay());
|
self::registerBlock(new Clay());
|
||||||
self::registerBlock(new Sugarcane());
|
self::registerBlock(new Sugarcane());
|
||||||
//TODO: JUKEBOX
|
//TODO: JUKEBOX
|
||||||
self::registerBlock(new WoodenFence());
|
self::registerBlock(new WoodenFence());
|
||||||
self::registerBlock(new Pumpkin());
|
self::registerBlock(new Pumpkin());
|
||||||
self::registerBlock(new Netherrack());
|
self::registerBlock(new Netherrack());
|
||||||
self::registerBlock(new SoulSand());
|
self::registerBlock(new SoulSand());
|
||||||
self::registerBlock(new Glowstone());
|
self::registerBlock(new Glowstone());
|
||||||
//TODO: PORTAL
|
//TODO: PORTAL
|
||||||
self::registerBlock(new LitPumpkin());
|
self::registerBlock(new LitPumpkin());
|
||||||
self::registerBlock(new Cake());
|
self::registerBlock(new Cake());
|
||||||
//TODO: REPEATER_BLOCK
|
//TODO: REPEATER_BLOCK
|
||||||
//TODO: POWERED_REPEATER
|
//TODO: POWERED_REPEATER
|
||||||
//TODO: INVISIBLEBEDROCK
|
self::registerBlock(new InvisibleBedrock());
|
||||||
self::registerBlock(new Trapdoor());
|
self::registerBlock(new Trapdoor());
|
||||||
//TODO: MONSTER_EGG
|
//TODO: MONSTER_EGG
|
||||||
self::registerBlock(new StoneBricks());
|
self::registerBlock(new StoneBricks());
|
||||||
self::registerBlock(new BrownMushroomBlock());
|
self::registerBlock(new BrownMushroomBlock());
|
||||||
self::registerBlock(new RedMushroomBlock());
|
self::registerBlock(new RedMushroomBlock());
|
||||||
self::registerBlock(new IronBars());
|
self::registerBlock(new IronBars());
|
||||||
self::registerBlock(new GlassPane());
|
self::registerBlock(new GlassPane());
|
||||||
self::registerBlock(new Melon());
|
self::registerBlock(new Melon());
|
||||||
self::registerBlock(new PumpkinStem());
|
self::registerBlock(new PumpkinStem());
|
||||||
self::registerBlock(new MelonStem());
|
self::registerBlock(new MelonStem());
|
||||||
self::registerBlock(new Vine());
|
self::registerBlock(new Vine());
|
||||||
self::registerBlock(new FenceGate(Block::OAK_FENCE_GATE, 0, "Oak Fence Gate"));
|
self::registerBlock(new FenceGate(Block::OAK_FENCE_GATE, 0, "Oak Fence Gate"));
|
||||||
self::registerBlock(new BrickStairs());
|
self::registerBlock(new BrickStairs());
|
||||||
self::registerBlock(new StoneBrickStairs());
|
self::registerBlock(new StoneBrickStairs());
|
||||||
self::registerBlock(new Mycelium());
|
self::registerBlock(new Mycelium());
|
||||||
self::registerBlock(new WaterLily());
|
self::registerBlock(new WaterLily());
|
||||||
self::registerBlock(new NetherBrick(Block::NETHER_BRICK_BLOCK, 0, "Nether Bricks"));
|
self::registerBlock(new NetherBrick(Block::NETHER_BRICK_BLOCK, 0, "Nether Bricks"));
|
||||||
self::registerBlock(new NetherBrickFence());
|
self::registerBlock(new NetherBrickFence());
|
||||||
self::registerBlock(new NetherBrickStairs());
|
self::registerBlock(new NetherBrickStairs());
|
||||||
self::registerBlock(new NetherWartPlant());
|
self::registerBlock(new NetherWartPlant());
|
||||||
self::registerBlock(new EnchantingTable());
|
self::registerBlock(new EnchantingTable());
|
||||||
self::registerBlock(new BrewingStand());
|
self::registerBlock(new BrewingStand());
|
||||||
//TODO: CAULDRON_BLOCK
|
//TODO: CAULDRON_BLOCK
|
||||||
//TODO: END_PORTAL
|
//TODO: END_PORTAL
|
||||||
self::registerBlock(new EndPortalFrame());
|
self::registerBlock(new EndPortalFrame());
|
||||||
self::registerBlock(new EndStone());
|
self::registerBlock(new EndStone());
|
||||||
//TODO: DRAGON_EGG
|
//TODO: DRAGON_EGG
|
||||||
self::registerBlock(new RedstoneLamp());
|
self::registerBlock(new RedstoneLamp());
|
||||||
self::registerBlock(new LitRedstoneLamp());
|
self::registerBlock(new LitRedstoneLamp());
|
||||||
//TODO: DROPPER
|
//TODO: DROPPER
|
||||||
self::registerBlock(new ActivatorRail());
|
self::registerBlock(new ActivatorRail());
|
||||||
self::registerBlock(new CocoaBlock());
|
self::registerBlock(new CocoaBlock());
|
||||||
self::registerBlock(new SandstoneStairs());
|
self::registerBlock(new SandstoneStairs());
|
||||||
self::registerBlock(new EmeraldOre());
|
self::registerBlock(new EmeraldOre());
|
||||||
self::registerBlock(new EnderChest());
|
self::registerBlock(new EnderChest());
|
||||||
self::registerBlock(new TripwireHook());
|
self::registerBlock(new TripwireHook());
|
||||||
self::registerBlock(new Tripwire());
|
self::registerBlock(new Tripwire());
|
||||||
self::registerBlock(new Emerald());
|
self::registerBlock(new Emerald());
|
||||||
self::registerBlock(new WoodenStairs(Block::SPRUCE_STAIRS, 0, "Spruce Stairs"));
|
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::BIRCH_STAIRS, 0, "Birch Stairs"));
|
||||||
self::registerBlock(new WoodenStairs(Block::JUNGLE_STAIRS, 0, "Jungle Stairs"));
|
self::registerBlock(new WoodenStairs(Block::JUNGLE_STAIRS, 0, "Jungle Stairs"));
|
||||||
//TODO: COMMAND_BLOCK
|
//TODO: COMMAND_BLOCK
|
||||||
//TODO: BEACON
|
//TODO: BEACON
|
||||||
self::registerBlock(new CobblestoneWall());
|
self::registerBlock(new CobblestoneWall());
|
||||||
self::registerBlock(new FlowerPot());
|
self::registerBlock(new FlowerPot());
|
||||||
self::registerBlock(new Carrot());
|
self::registerBlock(new Carrot());
|
||||||
self::registerBlock(new Potato());
|
self::registerBlock(new Potato());
|
||||||
self::registerBlock(new WoodenButton());
|
self::registerBlock(new WoodenButton());
|
||||||
self::registerBlock(new Skull());
|
self::registerBlock(new Skull());
|
||||||
self::registerBlock(new Anvil());
|
self::registerBlock(new Anvil());
|
||||||
self::registerBlock(new TrappedChest());
|
self::registerBlock(new TrappedChest());
|
||||||
self::registerBlock(new WeightedPressurePlateLight());
|
self::registerBlock(new WeightedPressurePlateLight());
|
||||||
self::registerBlock(new WeightedPressurePlateHeavy());
|
self::registerBlock(new WeightedPressurePlateHeavy());
|
||||||
//TODO: COMPARATOR_BLOCK
|
//TODO: COMPARATOR_BLOCK
|
||||||
//TODO: POWERED_COMPARATOR
|
//TODO: POWERED_COMPARATOR
|
||||||
self::registerBlock(new DaylightSensor());
|
self::registerBlock(new DaylightSensor());
|
||||||
self::registerBlock(new Redstone());
|
self::registerBlock(new Redstone());
|
||||||
self::registerBlock(new NetherQuartzOre());
|
self::registerBlock(new NetherQuartzOre());
|
||||||
//TODO: HOPPER_BLOCK
|
//TODO: HOPPER_BLOCK
|
||||||
self::registerBlock(new Quartz());
|
self::registerBlock(new Quartz());
|
||||||
self::registerBlock(new QuartzStairs());
|
self::registerBlock(new QuartzStairs());
|
||||||
self::registerBlock(new DoubleWoodenSlab());
|
self::registerBlock(new DoubleWoodenSlab());
|
||||||
self::registerBlock(new WoodenSlab());
|
self::registerBlock(new WoodenSlab());
|
||||||
self::registerBlock(new StainedClay());
|
self::registerBlock(new StainedClay());
|
||||||
self::registerBlock(new StainedGlassPane());
|
self::registerBlock(new StainedGlassPane());
|
||||||
self::registerBlock(new Leaves2());
|
self::registerBlock(new Leaves2());
|
||||||
self::registerBlock(new Wood2());
|
self::registerBlock(new Wood2());
|
||||||
self::registerBlock(new WoodenStairs(Block::ACACIA_STAIRS, 0, "Acacia Stairs"));
|
self::registerBlock(new WoodenStairs(Block::ACACIA_STAIRS, 0, "Acacia Stairs"));
|
||||||
self::registerBlock(new WoodenStairs(Block::DARK_OAK_STAIRS, 0, "Dark Oak Stairs"));
|
self::registerBlock(new WoodenStairs(Block::DARK_OAK_STAIRS, 0, "Dark Oak Stairs"));
|
||||||
//TODO: SLIME
|
//TODO: SLIME
|
||||||
|
|
||||||
self::registerBlock(new IronTrapdoor());
|
self::registerBlock(new IronTrapdoor());
|
||||||
self::registerBlock(new Prismarine());
|
self::registerBlock(new Prismarine());
|
||||||
self::registerBlock(new SeaLantern());
|
self::registerBlock(new SeaLantern());
|
||||||
self::registerBlock(new HayBale());
|
self::registerBlock(new HayBale());
|
||||||
self::registerBlock(new Carpet());
|
self::registerBlock(new Carpet());
|
||||||
self::registerBlock(new HardenedClay());
|
self::registerBlock(new HardenedClay());
|
||||||
self::registerBlock(new Coal());
|
self::registerBlock(new Coal());
|
||||||
self::registerBlock(new PackedIce());
|
self::registerBlock(new PackedIce());
|
||||||
self::registerBlock(new DoublePlant());
|
self::registerBlock(new DoublePlant());
|
||||||
self::registerBlock(new StandingBanner());
|
self::registerBlock(new StandingBanner());
|
||||||
self::registerBlock(new WallBanner());
|
self::registerBlock(new WallBanner());
|
||||||
//TODO: DAYLIGHT_DETECTOR_INVERTED
|
//TODO: DAYLIGHT_DETECTOR_INVERTED
|
||||||
self::registerBlock(new RedSandstone());
|
self::registerBlock(new RedSandstone());
|
||||||
self::registerBlock(new RedSandstoneStairs());
|
self::registerBlock(new RedSandstoneStairs());
|
||||||
self::registerBlock(new DoubleStoneSlab2());
|
self::registerBlock(new DoubleStoneSlab2());
|
||||||
self::registerBlock(new StoneSlab2());
|
self::registerBlock(new StoneSlab2());
|
||||||
self::registerBlock(new FenceGate(Block::SPRUCE_FENCE_GATE, 0, "Spruce Fence Gate"));
|
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::BIRCH_FENCE_GATE, 0, "Birch Fence Gate"));
|
||||||
self::registerBlock(new FenceGate(Block::JUNGLE_FENCE_GATE, 0, "Jungle 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::DARK_OAK_FENCE_GATE, 0, "Dark Oak Fence Gate"));
|
||||||
self::registerBlock(new FenceGate(Block::ACACIA_FENCE_GATE, 0, "Acacia Fence Gate"));
|
self::registerBlock(new FenceGate(Block::ACACIA_FENCE_GATE, 0, "Acacia Fence Gate"));
|
||||||
//TODO: REPEATING_COMMAND_BLOCK
|
//TODO: REPEATING_COMMAND_BLOCK
|
||||||
//TODO: CHAIN_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::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::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::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::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 WoodenDoor(Block::DARK_OAK_DOOR_BLOCK, 0, "Dark Oak Door", Item::DARK_OAK_DOOR));
|
||||||
self::registerBlock(new GrassPath());
|
self::registerBlock(new GrassPath());
|
||||||
self::registerBlock(new ItemFrame());
|
self::registerBlock(new ItemFrame());
|
||||||
//TODO: CHORUS_FLOWER
|
//TODO: CHORUS_FLOWER
|
||||||
self::registerBlock(new Purpur());
|
self::registerBlock(new Purpur());
|
||||||
|
|
||||||
self::registerBlock(new PurpurStairs());
|
self::registerBlock(new PurpurStairs());
|
||||||
|
|
||||||
//TODO: UNDYED_SHULKER_BOX
|
//TODO: UNDYED_SHULKER_BOX
|
||||||
self::registerBlock(new EndStoneBricks());
|
self::registerBlock(new EndStoneBricks());
|
||||||
//TODO: FROSTED_ICE
|
//TODO: FROSTED_ICE
|
||||||
self::registerBlock(new EndRod());
|
self::registerBlock(new EndRod());
|
||||||
//TODO: END_GATEWAY
|
//TODO: END_GATEWAY
|
||||||
|
|
||||||
self::registerBlock(new Magma());
|
self::registerBlock(new Magma());
|
||||||
self::registerBlock(new NetherWartBlock());
|
self::registerBlock(new NetherWartBlock());
|
||||||
self::registerBlock(new NetherBrick(Block::RED_NETHER_BRICK, 0, "Red Nether Bricks"));
|
self::registerBlock(new NetherBrick(Block::RED_NETHER_BRICK, 0, "Red Nether Bricks"));
|
||||||
self::registerBlock(new BoneBlock());
|
self::registerBlock(new BoneBlock());
|
||||||
|
|
||||||
//TODO: SHULKER_BOX
|
//TODO: SHULKER_BOX
|
||||||
self::registerBlock(new GlazedTerracotta(Block::PURPLE_GLAZED_TERRACOTTA, 0, "Purple Glazed Terracotta"));
|
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::WHITE_GLAZED_TERRACOTTA, 0, "White Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::ORANGE_GLAZED_TERRACOTTA, 0, "Orange 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::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::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::YELLOW_GLAZED_TERRACOTTA, 0, "Yellow Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::LIME_GLAZED_TERRACOTTA, 0, "Lime 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::PINK_GLAZED_TERRACOTTA, 0, "Pink Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::GRAY_GLAZED_TERRACOTTA, 0, "Grey 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::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::CYAN_GLAZED_TERRACOTTA, 0, "Cyan Glazed Terracotta"));
|
||||||
|
|
||||||
self::registerBlock(new GlazedTerracotta(Block::BLUE_GLAZED_TERRACOTTA, 0, "Blue 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::BROWN_GLAZED_TERRACOTTA, 0, "Brown Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::GREEN_GLAZED_TERRACOTTA, 0, "Green 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::RED_GLAZED_TERRACOTTA, 0, "Red Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::BLACK_GLAZED_TERRACOTTA, 0, "Black Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::BLACK_GLAZED_TERRACOTTA, 0, "Black Glazed Terracotta"));
|
||||||
self::registerBlock(new Concrete());
|
self::registerBlock(new Concrete());
|
||||||
self::registerBlock(new ConcretePowder());
|
self::registerBlock(new ConcretePowder());
|
||||||
|
|
||||||
//TODO: CHORUS_PLANT
|
//TODO: CHORUS_PLANT
|
||||||
self::registerBlock(new StainedGlass());
|
self::registerBlock(new StainedGlass());
|
||||||
|
|
||||||
self::registerBlock(new Podzol());
|
self::registerBlock(new Podzol());
|
||||||
self::registerBlock(new Beetroot());
|
self::registerBlock(new Beetroot());
|
||||||
self::registerBlock(new Stonecutter());
|
self::registerBlock(new Stonecutter());
|
||||||
self::registerBlock(new GlowingObsidian());
|
self::registerBlock(new GlowingObsidian());
|
||||||
self::registerBlock(new NetherReactor());
|
self::registerBlock(new NetherReactor());
|
||||||
//TODO: INFO_UPDATE
|
self::registerBlock(new InfoUpdate(Block::INFO_UPDATE, 0, "update!"));
|
||||||
//TODO: INFO_UPDATE2
|
self::registerBlock(new InfoUpdate(Block::INFO_UPDATE2, 0, "ate!upd"));
|
||||||
//TODO: MOVINGBLOCK
|
//TODO: MOVINGBLOCK
|
||||||
//TODO: OBSERVER
|
//TODO: OBSERVER
|
||||||
//TODO: STRUCTURE_BLOCK
|
//TODO: STRUCTURE_BLOCK
|
||||||
|
|
||||||
//TODO: RESERVED6
|
self::registerBlock(new Reserved6(Block::RESERVED6, 0, "reserved6"));
|
||||||
|
|
||||||
foreach(self::$list as $id => $block){
|
for($id = 0, $size = self::$fullList->getSize() >> 4; $id < $size; ++$id){
|
||||||
if($block === null){
|
if(self::$fullList[$id << 4] === null){
|
||||||
self::registerBlock(new UnknownBlock($id));
|
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
|
* Registers a block type into the index. Plugins may use this method to register new block types or override
|
||||||
* existing ones.
|
* existing ones.
|
||||||
@ -348,8 +347,6 @@ class BlockFactory{
|
|||||||
throw new \RuntimeException("Trying to overwrite an already registered block");
|
throw new \RuntimeException("Trying to overwrite an already registered block");
|
||||||
}
|
}
|
||||||
|
|
||||||
self::$list[$id] = clone $block;
|
|
||||||
|
|
||||||
for($meta = 0; $meta < 16; ++$meta){
|
for($meta = 0; $meta < 16; ++$meta){
|
||||||
$variant = clone $block;
|
$variant = clone $block;
|
||||||
$variant->setDamage($meta);
|
$variant->setDamage($meta);
|
||||||
@ -360,7 +357,7 @@ class BlockFactory{
|
|||||||
self::$transparent[$id] = $block->isTransparent();
|
self::$transparent[$id] = $block->isTransparent();
|
||||||
self::$hardness[$id] = $block->getHardness();
|
self::$hardness[$id] = $block->getHardness();
|
||||||
self::$light[$id] = $block->getLightLevel();
|
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::$diffusesSkyLight[$id] = $block->diffusesSkyLight();
|
||||||
self::$blastResistance[$id] = $block->getBlastResistance();
|
self::$blastResistance[$id] = $block->getBlastResistance();
|
||||||
}
|
}
|
||||||
@ -390,9 +387,9 @@ class BlockFactory{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($pos !== null){
|
if($pos !== null){
|
||||||
$block->x = $pos->x;
|
$block->x = $pos->getFloorX();
|
||||||
$block->y = $pos->y;
|
$block->y = $pos->getFloorY();
|
||||||
$block->z = $pos->z;
|
$block->z = $pos->getFloorZ();
|
||||||
$block->level = $pos->level;
|
$block->level = $pos->level;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,10 +408,36 @@ class BlockFactory{
|
|||||||
* Returns whether a specified block ID is already registered in the block factory.
|
* Returns whether a specified block ID is already registered in the block factory.
|
||||||
*
|
*
|
||||||
* @param int $id
|
* @param int $id
|
||||||
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public static function isRegistered(int $id) : bool{
|
public static function isRegistered(int $id) : bool{
|
||||||
$b = self::$list[$id];
|
$b = self::$fullList[$id << 4];
|
||||||
return $b !== null and !($b instanceof UnknownBlock);
|
return $b !== null and !($b instanceof UnknownBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @deprecated
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @param int $meta
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public static function toStaticRuntimeId(int $id, int $meta = 0) : int{
|
||||||
|
return RuntimeBlockMapping::toStaticRuntimeId($id, $meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @param int $runtimeId
|
||||||
|
*
|
||||||
|
* @return int[] [id, meta]
|
||||||
|
*/
|
||||||
|
public static function fromStaticRuntimeId(int $runtimeId) : array{
|
||||||
|
return RuntimeBlockMapping::fromStaticRuntimeId($runtimeId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,4 +56,11 @@ class Bookshelf extends Solid{
|
|||||||
return 300;
|
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;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\TieredTool;
|
use pocketmine\item\TieredTool;
|
||||||
|
|
||||||
class BrewingStand extends Transparent{
|
class BrewingStand extends Transparent{
|
||||||
|
|
||||||
protected $id = self::BREWING_STAND_BLOCK;
|
protected $id = self::BREWING_STAND_BLOCK;
|
||||||
|
|
||||||
|
protected $itemId = Item::BREWING_STAND;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(int $meta = 0){
|
||||||
$this->meta = $meta;
|
$this->meta = $meta;
|
||||||
}
|
}
|
||||||
|
@ -52,5 +52,4 @@ class BrickStairs extends Stair{
|
|||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return "Brick Stairs";
|
return "Brick Stairs";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class BrownMushroomBlock extends RedMushroomBlock{
|
class BrownMushroomBlock extends RedMushroomBlock{
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\TieredTool;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\nbt\tag\StringTag;
|
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\tile\Furnace as TileFurnace;
|
use pocketmine\tile\Furnace as TileFurnace;
|
||||||
use pocketmine\tile\Tile;
|
use pocketmine\tile\Tile;
|
||||||
@ -83,7 +82,7 @@ class BurningFurnace extends Solid{
|
|||||||
$furnace = Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this));
|
$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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,11 +28,9 @@ use pocketmine\event\block\BlockGrowEvent;
|
|||||||
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||||
use pocketmine\event\entity\EntityDamageEvent;
|
use pocketmine\event\entity\EntityDamageEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\Server;
|
|
||||||
|
|
||||||
class Cactus extends Transparent{
|
class Cactus extends Transparent{
|
||||||
|
|
||||||
@ -66,50 +64,53 @@ class Cactus extends Transparent{
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ticksRandomly() : bool{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onEntityCollide(Entity $entity) : void{
|
public function onEntityCollide(Entity $entity) : void{
|
||||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_CONTACT, 1);
|
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_CONTACT, 1);
|
||||||
$entity->attack($ev);
|
$entity->attack($ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
if($down->getId() !== self::SAND and $down->getId() !== self::CACTUS){
|
||||||
if($down->getId() !== self::SAND and $down->getId() !== self::CACTUS){
|
$this->getLevel()->useBreakOn($this);
|
||||||
$this->getLevel()->useBreakOn($this);
|
}else{
|
||||||
}else{
|
for($side = 2; $side <= 5; ++$side){
|
||||||
for($side = 2; $side <= 5; ++$side){
|
$b = $this->getSide($side);
|
||||||
$b = $this->getSide($side);
|
if($b->isSolid()){
|
||||||
if(!$b->canBeFlowedInto()){
|
$this->getLevel()->useBreakOn($this);
|
||||||
$this->getLevel()->useBreakOn($this);
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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{
|
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);
|
$block1 = $this->getSide(Vector3::SIDE_SOUTH);
|
||||||
$block2 = $this->getSide(Vector3::SIDE_WEST);
|
$block2 = $this->getSide(Vector3::SIDE_WEST);
|
||||||
$block3 = $this->getSide(Vector3::SIDE_EAST);
|
$block3 = $this->getSide(Vector3::SIDE_EAST);
|
||||||
if($block0->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);
|
$this->getLevel()->setBlock($this, $this, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -23,11 +23,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\entity\Effect;
|
use pocketmine\entity\EffectInstance;
|
||||||
use pocketmine\entity\Living;
|
use pocketmine\entity\Living;
|
||||||
use pocketmine\item\FoodSource;
|
use pocketmine\item\FoodSource;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
@ -36,6 +35,8 @@ class Cake extends Transparent implements FoodSource{
|
|||||||
|
|
||||||
protected $id = self::CAKE_BLOCK;
|
protected $id = self::CAKE_BLOCK;
|
||||||
|
|
||||||
|
protected $itemId = Item::CAKE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(int $meta = 0){
|
||||||
$this->meta = $meta;
|
$this->meta = $meta;
|
||||||
}
|
}
|
||||||
@ -73,16 +74,10 @@ class Cake extends Transparent implements FoodSource{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
@ -127,7 +122,7 @@ class Cake extends Transparent implements FoodSource{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Effect[]
|
* @return EffectInstance[]
|
||||||
*/
|
*/
|
||||||
public function getAdditionalEffects() : array{
|
public function getAdditionalEffects() : array{
|
||||||
return [];
|
return [];
|
||||||
|
@ -25,7 +25,6 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
use pocketmine\block\utils\ColorBlockMetaHelper;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
@ -73,16 +72,17 @@ class Carpet extends Flowable{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
|
$this->getLevel()->useBreakOn($this);
|
||||||
$this->getLevel()->useBreakOn($this);
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class Carrot extends Crops{
|
class Carrot extends Crops{
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\nbt\tag\StringTag;
|
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\tile\Chest as TileChest;
|
use pocketmine\tile\Chest as TileChest;
|
||||||
use pocketmine\tile\Tile;
|
use pocketmine\tile\Tile;
|
||||||
@ -115,7 +114,7 @@ class Chest extends Transparent{
|
|||||||
if(
|
if(
|
||||||
!$this->getSide(Vector3::SIDE_UP)->isTransparent() or
|
!$this->getSide(Vector3::SIDE_UP)->isTransparent() or
|
||||||
($chest->isPaired() and !$chest->getPair()->getBlock()->getSide(Vector3::SIDE_UP)->isTransparent()) or
|
($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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -52,4 +52,12 @@ class Coal extends Solid{
|
|||||||
public function getFuelTime() : int{
|
public function getFuelTime() : int{
|
||||||
return 16000;
|
return 16000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFlameEncouragement() : int{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\TieredTool;
|
use pocketmine\item\TieredTool;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class CoalOre extends Solid{
|
class CoalOre extends Solid{
|
||||||
|
|
||||||
@ -57,4 +58,7 @@ class CoalOre extends Solid{
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getXpDropAmount() : int{
|
||||||
|
return mt_rand(0, 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,5 +48,4 @@ class CobblestoneStairs extends Stair{
|
|||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return "Cobblestone Stairs";
|
return "Cobblestone Stairs";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,18 @@ use pocketmine\math\Vector3;
|
|||||||
class CobblestoneWall extends Transparent{
|
class CobblestoneWall extends Transparent{
|
||||||
public const NONE_MOSSY_WALL = 0;
|
public const NONE_MOSSY_WALL = 0;
|
||||||
public const MOSSY_WALL = 1;
|
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;
|
protected $id = self::COBBLESTONE_WALL;
|
||||||
|
|
||||||
@ -50,11 +62,23 @@ class CobblestoneWall extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
if($this->meta === 0x01){
|
static $names = [
|
||||||
return "Mossy Cobblestone Wall";
|
self::NONE_MOSSY_WALL => "Cobblestone",
|
||||||
}
|
self::MOSSY_WALL => "Mossy Cobblestone",
|
||||||
|
self::GRANITE_WALL => "Granite",
|
||||||
return "Cobblestone Wall";
|
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{
|
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
@ -90,5 +114,4 @@ class CobblestoneWall extends Transparent{
|
|||||||
public function canConnect(Block $block){
|
public function canConnect(Block $block){
|
||||||
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
|
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
use pocketmine\block\utils\ColorBlockMetaHelper;
|
||||||
use pocketmine\level\Level;
|
|
||||||
|
|
||||||
class ConcretePowder extends Fallable{
|
class ConcretePowder extends Fallable{
|
||||||
|
|
||||||
@ -46,13 +45,12 @@ class ConcretePowder extends Fallable{
|
|||||||
return BlockToolType::TYPE_SHOVEL;
|
return BlockToolType::TYPE_SHOVEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL and ($block = $this->checkAdjacentWater()) !== null){
|
if(($block = $this->checkAdjacentWater()) !== null){
|
||||||
$this->level->setBlock($this, $block);
|
$this->level->setBlock($this, $block);
|
||||||
return $type;
|
}else{
|
||||||
|
parent::onNearbyBlockChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::onUpdate($type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,7 +66,7 @@ class ConcretePowder extends Fallable{
|
|||||||
private function checkAdjacentWater() : ?Block{
|
private function checkAdjacentWater() : ?Block{
|
||||||
for($i = 1; $i < 6; ++$i){ //Do not check underneath
|
for($i = 1; $i < 6; ++$i){ //Do not check underneath
|
||||||
if($this->getSide($i) instanceof Water){
|
if($this->getSide($i) instanceof Water){
|
||||||
return Block::get(Block::CONCRETE, $this->meta);
|
return BlockFactory::get(Block::CONCRETE, $this->meta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\inventory\BigCraftingGrid;
|
use pocketmine\inventory\CraftingGrid;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ class CraftingTable extends Solid{
|
|||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
if($player instanceof Player){
|
if($player instanceof Player){
|
||||||
$player->setCraftingGrid(new BigCraftingGrid($player));
|
$player->setCraftingGrid(new CraftingGrid($player, CraftingGrid::SIZE_BIG));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -25,10 +25,9 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\event\block\BlockGrowEvent;
|
use pocketmine\event\block\BlockGrowEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\Server;
|
use function mt_rand;
|
||||||
|
|
||||||
abstract class Crops extends Flowable{
|
abstract class Crops extends Flowable{
|
||||||
|
|
||||||
@ -44,15 +43,15 @@ abstract class Crops extends Flowable{
|
|||||||
|
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
if($this->meta < 7 and $item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
||||||
$block = clone $this;
|
$block = clone $this;
|
||||||
$block->meta += mt_rand(2, 5);
|
$block->meta += mt_rand(2, 5);
|
||||||
if($block->meta > 7){
|
if($block->meta > 7){
|
||||||
$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()){
|
if(!$ev->isCancelled()){
|
||||||
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
|
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
|
||||||
}
|
}
|
||||||
@ -65,35 +64,28 @@ abstract class Crops extends Flowable{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function onNearbyBlockChange() : void{
|
||||||
|
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
|
||||||
|
$this->getLevel()->useBreakOn($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function ticksRandomly() : bool{
|
public function ticksRandomly() : bool{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onRandomTick() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if(mt_rand(0, 2) === 1){
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
|
if($this->meta < 0x07){
|
||||||
$this->getLevel()->useBreakOn($this);
|
$block = clone $this;
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
++$block->meta;
|
||||||
}
|
$ev = new BlockGrowEvent($this, $block);
|
||||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
$ev->call();
|
||||||
if(mt_rand(0, 2) === 1){
|
if(!$ev->isCancelled()){
|
||||||
if($this->meta < 0x07){
|
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
|
||||||
$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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}else{
|
|
||||||
return Level::BLOCK_UPDATE_RANDOM;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isAffectedBySilkTouch() : bool{
|
public function isAffectedBySilkTouch() : bool{
|
||||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
@ -52,15 +51,17 @@ class Dandelion extends Flowable{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
|
$this->getLevel()->useBreakOn($this);
|
||||||
$this->getLevel()->useBreakOn($this);
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
public function getFlameEncouragement() : int{
|
||||||
|
return 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,9 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
|
use pocketmine\Player;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class DeadBush extends Flowable{
|
class DeadBush extends Flowable{
|
||||||
|
|
||||||
@ -40,18 +41,20 @@ class DeadBush extends Flowable{
|
|||||||
return "Dead Bush";
|
return "Dead Bush";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if(!$this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
|
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
$this->getLevel()->useBreakOn($this);
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function onNearbyBlockChange() : void{
|
||||||
|
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||||
|
$this->getLevel()->useBreakOn($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return BlockToolType::TYPE_SHEARS;
|
return BlockToolType::TYPE_SHEARS;
|
||||||
}
|
}
|
||||||
@ -69,4 +72,12 @@ class DeadBush extends Flowable{
|
|||||||
|
|
||||||
return parent::getDrops($item);
|
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;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
class DetectorRail extends Rail{
|
class DetectorRail extends RedstoneRail{
|
||||||
|
|
||||||
protected $id = self::DETECTOR_RAIL;
|
protected $id = self::DETECTOR_RAIL;
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\TieredTool;
|
use pocketmine\item\TieredTool;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class DiamondOre extends Solid{
|
class DiamondOre extends Solid{
|
||||||
|
|
||||||
@ -56,4 +57,8 @@ class DiamondOre extends Solid{
|
|||||||
ItemFactory::get(Item::DIAMOND)
|
ItemFactory::get(Item::DIAMOND)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getXpDropAmount() : int{
|
||||||
|
return mt_rand(3, 7);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
|
use pocketmine\item\Hoe;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
@ -50,8 +51,8 @@ class Dirt extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
if($item->isHoe()){
|
if($item instanceof Hoe){
|
||||||
$item->useOn($this);
|
$item->applyDamage(1);
|
||||||
if($this->meta === 1){
|
if($this->meta === 1){
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
$this->getLevel()->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
||||||
}else{
|
}else{
|
||||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\level\sound\DoorSound;
|
use pocketmine\level\sound\DoorSound;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
@ -201,26 +200,20 @@ abstract class Door extends Transparent{
|
|||||||
return $bb;
|
return $bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false);
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false);
|
if($this->getSide(Vector3::SIDE_UP) instanceof Door){
|
||||||
if($this->getSide(Vector3::SIDE_UP) instanceof Door){
|
$this->getLevel()->setBlock($this->getSide(Vector3::SIDE_UP), BlockFactory::get(Block::AIR), false);
|
||||||
$this->getLevel()->setBlock($this->getSide(Vector3::SIDE_UP), BlockFactory::get(Block::AIR), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
if($face === Vector3::SIDE_UP){
|
if($face === Vector3::SIDE_UP){
|
||||||
$blockUp = $this->getSide(Vector3::SIDE_UP);
|
$blockUp = $this->getSide(Vector3::SIDE_UP);
|
||||||
$blockDown = $this->getSide(Vector3::SIDE_DOWN);
|
$blockDown = $this->getSide(Vector3::SIDE_DOWN);
|
||||||
if($blockUp->canBeReplaced() === false or $blockDown->isTransparent() === true){
|
if(!$blockUp->canBeReplaced() or $blockDown->isTransparent()){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$direction = $player instanceof Player ? $player->getDirection() : 0;
|
$direction = $player instanceof Player ? $player->getDirection() : 0;
|
||||||
@ -233,13 +226,13 @@ abstract class Door extends Transparent{
|
|||||||
$next = $this->getSide($faces[($direction + 2) % 4]);
|
$next = $this->getSide($faces[($direction + 2) % 4]);
|
||||||
$next2 = $this->getSide($faces[$direction]);
|
$next2 = $this->getSide($faces[$direction]);
|
||||||
$metaUp = 0x08;
|
$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;
|
$metaUp |= 0x01;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->setDamage($player->getDirection() & 0x03);
|
$this->setDamage($player->getDirection() & 0x03);
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, true, true); //Bottom
|
$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 true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,9 +25,9 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class DoublePlant extends Flowable{
|
class DoublePlant extends Flowable{
|
||||||
public const BITFLAG_TOP = 0x08;
|
public const BITFLAG_TOP = 0x08;
|
||||||
@ -84,17 +84,10 @@ class DoublePlant extends Flowable{
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if(!$this->isValidHalfPlant() or (($this->meta & self::BITFLAG_TOP) === 0 and $this->getSide(Vector3::SIDE_DOWN)->isTransparent())){
|
||||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
$this->getLevel()->useBreakOn($this);
|
||||||
if(!$this->isValidHalfPlant() or (($this->meta & self::BITFLAG_TOP) === 0 and $down->isTransparent())){
|
|
||||||
$this->getLevel()->useBreakOn($this);
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
public function getVariantBitmask() : int{
|
||||||
|
@ -35,7 +35,7 @@ abstract class DoubleSlab extends Solid{
|
|||||||
abstract public function getSlabId() : int;
|
abstract public function getSlabId() : int;
|
||||||
|
|
||||||
public function getName() : string{
|
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 getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
@ -47,4 +47,8 @@ abstract class DoubleSlab extends Solid{
|
|||||||
public function isAffectedBySilkTouch() : bool{
|
public function isAffectedBySilkTouch() : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getPickedItem() : Item{
|
||||||
|
return ItemFactory::get($this->getSlabId(), $this->getVariant());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,5 +30,4 @@ class DoubleStoneSlab2 extends DoubleStoneSlab{
|
|||||||
public function getSlabId() : int{
|
public function getSlabId() : int{
|
||||||
return self::STONE_SLAB2;
|
return self::STONE_SLAB2;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -38,4 +38,12 @@ class DoubleWoodenSlab extends DoubleSlab{
|
|||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return BlockToolType::TYPE_AXE;
|
return BlockToolType::TYPE_AXE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFlameEncouragement() : int{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\TieredTool;
|
use pocketmine\item\TieredTool;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class EmeraldOre extends Solid{
|
class EmeraldOre extends Solid{
|
||||||
|
|
||||||
@ -53,7 +54,11 @@ class EmeraldOre extends Solid{
|
|||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [
|
return [
|
||||||
ItemFactory::get(Item::EMERALD)
|
ItemFactory::get(Item::EMERALD)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getXpDropAmount() : int{
|
||||||
|
return mt_rand(3, 7);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,5 +106,4 @@ class EnderChest extends Chest{
|
|||||||
public function getFuelTime() : int{
|
public function getFuelTime() : int{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,26 +24,23 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
|
|
||||||
abstract class Fallable extends Solid{
|
abstract class Fallable extends Solid{
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
if($down->getId() === self::AIR or $down instanceof Liquid or $down instanceof Fire){
|
||||||
if($down->getId() === self::AIR or $down instanceof Liquid or $down instanceof Fire){
|
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||||
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true);
|
|
||||||
|
|
||||||
$nbt = Entity::createBaseNBT($this->add(0.5, 0, 0.5));
|
$nbt = Entity::createBaseNBT($this->add(0.5, 0, 0.5));
|
||||||
$nbt->setInt("TileID", $this->getId());
|
$nbt->setInt("TileID", $this->getId());
|
||||||
$nbt->setByte("Data", $this->getDamage());
|
$nbt->setByte("Data", $this->getDamage());
|
||||||
|
|
||||||
$fall = Entity::createEntity("FallingSand", $this->getLevel(), $nbt);
|
$fall = Entity::createEntity("FallingSand", $this->getLevel(), $nbt);
|
||||||
|
|
||||||
if($fall !== null){
|
if($fall !== null){
|
||||||
$fall->spawnToAll();
|
$fall->spawnToAll();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
|
|
||||||
@ -49,9 +48,6 @@ class Farmland extends Transparent{
|
|||||||
return BlockToolType::TYPE_SHOVEL;
|
return BlockToolType::TYPE_SHOVEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ticksRandomly() : bool{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
return new AxisAlignedBB(
|
return new AxisAlignedBB(
|
||||||
@ -64,29 +60,28 @@ class Farmland extends Transparent{
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL and $this->getSide(Vector3::SIDE_UP)->isSolid()){
|
if($this->getSide(Vector3::SIDE_UP)->isSolid()){
|
||||||
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
$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{
|
protected function canHydrate() : bool{
|
||||||
@ -116,4 +111,8 @@ class Farmland extends Transparent{
|
|||||||
public function isAffectedBySilkTouch() : bool{
|
public function isAffectedBySilkTouch() : bool{
|
||||||
return false;
|
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){
|
public function canConnect(Block $block){
|
||||||
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
|
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -94,4 +94,12 @@ class FenceGate extends Transparent{
|
|||||||
public function getFuelTime() : int{
|
public function getFuelTime() : int{
|
||||||
return 300;
|
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\Entity;
|
||||||
use pocketmine\entity\projectile\Arrow;
|
use pocketmine\entity\projectile\Arrow;
|
||||||
|
use pocketmine\event\block\BlockBurnEvent;
|
||||||
use pocketmine\event\entity\EntityCombustByBlockEvent;
|
use pocketmine\event\entity\EntityCombustByBlockEvent;
|
||||||
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||||
use pocketmine\event\entity\EntityDamageEvent;
|
use pocketmine\event\entity\EntityDamageEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Server;
|
use function min;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class Fire extends Flowable{
|
class Fire extends Flowable{
|
||||||
|
|
||||||
@ -61,10 +62,6 @@ class Fire extends Flowable{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ticksRandomly() : bool{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onEntityCollide(Entity $entity) : void{
|
public function onEntityCollide(Entity $entity) : void{
|
||||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, 1);
|
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, 1);
|
||||||
$entity->attack($ev);
|
$entity->attack($ev);
|
||||||
@ -73,7 +70,7 @@ class Fire extends Flowable{
|
|||||||
if($entity instanceof Arrow){
|
if($entity instanceof Arrow){
|
||||||
$ev->setCancelled();
|
$ev->setCancelled();
|
||||||
}
|
}
|
||||||
Server::getInstance()->getPluginManager()->callEvent($ev);
|
$ev->call();
|
||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
$entity->setOnFire($ev->getDuration());
|
$entity->setOnFire($ev->getDuration());
|
||||||
}
|
}
|
||||||
@ -83,35 +80,91 @@ class Fire extends Flowable{
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if(!$this->getSide(Vector3::SIDE_DOWN)->isSolid() and !$this->hasAdjacentFlammableBlocks()){
|
||||||
for($s = 0; $s <= 5; ++$s){
|
|
||||||
$side = $this->getSide($s);
|
|
||||||
if($side->getId() !== self::AIR and !($side instanceof Liquid)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||||
|
}else{
|
||||||
|
$this->level->scheduleDelayedBlockUpdate($this, mt_rand(30, 40));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
public function ticksRandomly() : bool{
|
||||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
return true;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
//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;
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
@ -71,15 +70,17 @@ class Flower extends Flowable{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
$this->getLevel()->useBreakOn($this);
|
||||||
$this->getLevel()->useBreakOn($this);
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
@ -68,16 +67,10 @@ class FlowerPot extends Flowable{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
|
$this->getLevel()->useBreakOn($this);
|
||||||
$this->getLevel()->useBreakOn($this);
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
|
@ -23,7 +23,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\level\Level;
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\Player;
|
||||||
|
|
||||||
class GlowingRedstoneOre extends RedstoneOre{
|
class GlowingRedstoneOre extends RedstoneOre{
|
||||||
|
|
||||||
@ -39,13 +40,19 @@ class GlowingRedstoneOre extends RedstoneOre{
|
|||||||
return 9;
|
return 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
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,6 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class Glowstone extends Transparent{
|
class Glowstone extends Transparent{
|
||||||
|
|
||||||
|
@ -24,13 +24,15 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\event\block\BlockSpreadEvent;
|
use pocketmine\event\block\BlockSpreadEvent;
|
||||||
|
use pocketmine\item\Hoe;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
|
use pocketmine\item\Shovel;
|
||||||
use pocketmine\level\generator\object\TallGrass as TallGrassObject;
|
use pocketmine\level\generator\object\TallGrass as TallGrassObject;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\utils\Random;
|
use pocketmine\utils\Random;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class Grass extends Solid{
|
class Grass extends Solid{
|
||||||
|
|
||||||
@ -62,43 +64,37 @@ class Grass extends Solid{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onRandomTick() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_RANDOM){
|
$lightAbove = $this->level->getFullLightAt($this->x, $this->y + 1, $this->z);
|
||||||
$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
|
||||||
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
|
||||||
//grass dies
|
$ev = new BlockSpreadEvent($this, $this, BlockFactory::get(Block::DIRT));
|
||||||
$this->level->getServer()->getPluginManager()->callEvent($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()){
|
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{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
@ -107,13 +103,13 @@ class Grass extends Solid{
|
|||||||
TallGrassObject::growGrass($this->getLevel(), $this, new Random(mt_rand()), 8, 2);
|
TallGrassObject::growGrass($this->getLevel(), $this, new Random(mt_rand()), 8, 2);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}elseif($item->isHoe()){
|
}elseif($item instanceof Hoe){
|
||||||
$item->useOn($this);
|
$item->applyDamage(1);
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND));
|
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}elseif($item->isShovel() and $this->getSide(Vector3::SIDE_UP)->getId() === Block::AIR){
|
}elseif($item instanceof Shovel and $this->getSide(Vector3::SIDE_UP)->getId() === Block::AIR){
|
||||||
$item->useOn($this);
|
$item->applyDamage(1);
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::GRASS_PATH));
|
$this->getLevel()->setBlock($this, BlockFactory::get(Block::GRASS_PATH));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -25,7 +25,6 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
|
|
||||||
@ -60,13 +59,10 @@ class GrassPath extends Transparent{
|
|||||||
return 0.6;
|
return 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL and $this->getSide(Vector3::SIDE_UP)->isSolid()){
|
if($this->getSide(Vector3::SIDE_UP)->isSolid()){
|
||||||
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
||||||
return $type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class Gravel extends Fallable{
|
class Gravel extends Fallable{
|
||||||
|
|
||||||
@ -55,5 +56,4 @@ class Gravel extends Fallable{
|
|||||||
|
|
||||||
return parent::getDropsForCompatibleTool($item);
|
return parent::getDropsForCompatibleTool($item);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -54,4 +54,12 @@ class HayBale extends Solid{
|
|||||||
public function getVariantBitmask() : int{
|
public function getVariantBitmask() : int{
|
||||||
return 0x03;
|
return 0x03;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFlameEncouragement() : int{
|
||||||
|
return 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\enchantment\Enchantment;
|
use pocketmine\item\enchantment\Enchantment;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
class Ice extends Transparent{
|
class Ice extends Transparent{
|
||||||
@ -57,7 +56,7 @@ class Ice extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onBreak(Item $item, Player $player = null) : bool{
|
public function onBreak(Item $item, Player $player = null) : bool{
|
||||||
if(!$item->hasEnchantment(Enchantment::SILK_TOUCH)){
|
if(($player === null or $player->isSurvival()) and !$item->hasEnchantment(Enchantment::SILK_TOUCH)){
|
||||||
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::WATER), true);
|
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::WATER), true);
|
||||||
}
|
}
|
||||||
return parent::onBreak($item, $player);
|
return parent::onBreak($item, $player);
|
||||||
@ -67,15 +66,10 @@ class Ice extends Transparent{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onRandomTick() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_RANDOM){
|
if($this->level->getHighestAdjacentBlockLight($this->x, $this->y, $this->z) >= 12){
|
||||||
if($this->level->getHighestAdjacentBlockLight($this->x, $this->y, $this->z) >= 12){
|
$this->level->useBreakOn($this);
|
||||||
$this->level->useBreakOn($this);
|
|
||||||
|
|
||||||
return $type;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
|
@ -21,11 +21,11 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\inventory;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
class BigCraftingGrid extends CraftingGrid{
|
class InfoUpdate extends Solid{
|
||||||
|
|
||||||
public function getGridWidth() : int{
|
public function getHardness() : float{
|
||||||
return 3;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -21,30 +21,31 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\scheduler;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\plugin\Plugin;
|
use pocketmine\item\Item;
|
||||||
|
|
||||||
/**
|
class InvisibleBedrock extends Transparent{
|
||||||
* Base class for plugin tasks. Allows the Server to delete them easily when needed
|
|
||||||
*/
|
|
||||||
abstract class PluginTask extends Task{
|
|
||||||
|
|
||||||
/** @var Plugin */
|
protected $id = self::INVISIBLE_BEDROCK;
|
||||||
protected $owner;
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Plugin $owner
|
|
||||||
*/
|
|
||||||
public function __construct(Plugin $owner){
|
|
||||||
$this->owner = $owner;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getName() : string{
|
||||||
* @return Plugin
|
return "Invisible Bedrock";
|
||||||
*/
|
|
||||||
final public function getOwner() : Plugin{
|
|
||||||
return $this->owner;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getHardness() : float{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBlastResistance() : float{
|
||||||
|
return 18000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isBreakable(Item $item) : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
@ -53,4 +53,3 @@ class IronBars extends Thin{
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,11 +24,11 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\tile\ItemFrame as TileItemFrame;
|
use pocketmine\tile\ItemFrame as TileItemFrame;
|
||||||
use pocketmine\tile\Tile;
|
use pocketmine\tile\Tile;
|
||||||
|
use function lcg_value;
|
||||||
|
|
||||||
class ItemFrame extends Flowable{
|
class ItemFrame extends Flowable{
|
||||||
protected $id = Block::ITEM_FRAME_BLOCK;
|
protected $id = Block::ITEM_FRAME_BLOCK;
|
||||||
@ -58,20 +58,16 @@ class ItemFrame extends Flowable{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
$sides = [
|
||||||
$sides = [
|
0 => Vector3::SIDE_WEST,
|
||||||
0 => Vector3::SIDE_WEST,
|
1 => Vector3::SIDE_EAST,
|
||||||
1 => Vector3::SIDE_EAST,
|
2 => Vector3::SIDE_NORTH,
|
||||||
2 => Vector3::SIDE_NORTH,
|
3 => Vector3::SIDE_SOUTH
|
||||||
3 => Vector3::SIDE_SOUTH
|
];
|
||||||
];
|
if(isset($sides[$this->meta]) and !$this->getSide($sides[$this->meta])->isSolid()){
|
||||||
if(!$this->getSide($sides[$this->meta])->isSolid()){
|
$this->level->useBreakOn($this);
|
||||||
$this->level->useBreakOn($this);
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
@ -116,4 +112,8 @@ class ItemFrame extends Flowable{
|
|||||||
public function isAffectedBySilkTouch() : bool{
|
public function isAffectedBySilkTouch() : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getHardness() : float{
|
||||||
|
return 0.25;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
@ -59,8 +58,10 @@ class Ladder extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onEntityCollide(Entity $entity) : void{
|
public function onEntityCollide(Entity $entity) : void{
|
||||||
$entity->resetFallDistance();
|
if($entity->asVector3()->floor()->distanceSquared($this) < 1){ //entity coordinates must be inside block
|
||||||
$entity->onGround = true;
|
$entity->resetFallDistance();
|
||||||
|
$entity->onGround = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
@ -91,7 +92,7 @@ class Ladder extends Transparent{
|
|||||||
|
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
if($blockClicked->isTransparent() === false){
|
if(!$blockClicked->isTransparent()){
|
||||||
$faces = [
|
$faces = [
|
||||||
2 => 2,
|
2 => 2,
|
||||||
3 => 3,
|
3 => 3,
|
||||||
@ -109,15 +110,10 @@ class Ladder extends Transparent{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if(!$this->getSide($this->meta ^ 0x01)->isSolid()){ //Replace with common break method
|
||||||
if(!$this->getSide($this->meta ^ 0x01)->isSolid()){ //Replace with common break method
|
$this->level->useBreakOn($this);
|
||||||
$this->level->useBreakOn($this);
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
|
@ -26,6 +26,7 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\TieredTool;
|
use pocketmine\item\TieredTool;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class LapisOre extends Solid{
|
class LapisOre extends Solid{
|
||||||
|
|
||||||
@ -57,4 +58,7 @@ class LapisOre extends Solid{
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getXpDropAmount() : int{
|
||||||
|
return mt_rand(2, 5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,6 @@ use pocketmine\item\Item;
|
|||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
|
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\Server;
|
|
||||||
|
|
||||||
class Lava extends Liquid{
|
class Lava extends Liquid{
|
||||||
|
|
||||||
@ -107,7 +106,7 @@ class Lava extends Liquid{
|
|||||||
$entity->attack($ev);
|
$entity->attack($ev);
|
||||||
|
|
||||||
$ev = new EntityCombustByBlockEvent($this, $entity, 15);
|
$ev = new EntityCombustByBlockEvent($this, $entity, 15);
|
||||||
Server::getInstance()->getPluginManager()->callEvent($ev);
|
$ev->call();
|
||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
$entity->setOnFire($ev->getDuration());
|
$entity->setOnFire($ev->getDuration());
|
||||||
}
|
}
|
||||||
@ -121,5 +120,4 @@ class Lava extends Liquid{
|
|||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,9 +26,9 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\event\block\LeavesDecayEvent;
|
use pocketmine\event\block\LeavesDecayEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class Leaves extends Transparent{
|
class Leaves extends Transparent{
|
||||||
public const OAK = 0;
|
public const OAK = 0;
|
||||||
@ -67,12 +67,8 @@ class Leaves extends Transparent{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ticksRandomly() : bool{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function findLog(Block $pos, array $visited, $distance, &$check, $fromSide = null){
|
protected function findLog(Block $pos, array $visited, int $distance, ?int $fromSide = null) : bool{
|
||||||
++$check;
|
|
||||||
$index = $pos->x . "." . $pos->y . "." . $pos->z;
|
$index = $pos->x . "." . $pos->y . "." . $pos->z;
|
||||||
if(isset($visited[$index])){
|
if(isset($visited[$index])){
|
||||||
return false;
|
return false;
|
||||||
@ -87,45 +83,45 @@ class Leaves extends Transparent{
|
|||||||
}
|
}
|
||||||
if($fromSide === null){
|
if($fromSide === null){
|
||||||
for($side = 2; $side <= 5; ++$side){
|
for($side = 2; $side <= 5; ++$side){
|
||||||
if($this->findLog($pos->getSide($side), $visited, $distance + 1, $check, $side) === true){
|
if($this->findLog($pos->getSide($side), $visited, $distance + 1, $side)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{ //No more loops
|
}else{ //No more loops
|
||||||
switch($fromSide){
|
switch($fromSide){
|
||||||
case 2:
|
case 2:
|
||||||
if($this->findLog($pos->getSide(Vector3::SIDE_NORTH), $visited, $distance + 1, $check, $fromSide) === true){
|
if($this->findLog($pos->getSide(Vector3::SIDE_NORTH), $visited, $distance + 1, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}elseif($this->findLog($pos->getSide(Vector3::SIDE_WEST), $visited, $distance + 1, $check, $fromSide) === true){
|
}elseif($this->findLog($pos->getSide(Vector3::SIDE_WEST), $visited, $distance + 1, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}elseif($this->findLog($pos->getSide(Vector3::SIDE_EAST), $visited, $distance + 1, $check, $fromSide) === true){
|
}elseif($this->findLog($pos->getSide(Vector3::SIDE_EAST), $visited, $distance + 1, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if($this->findLog($pos->getSide(Vector3::SIDE_SOUTH), $visited, $distance + 1, $check, $fromSide) === true){
|
if($this->findLog($pos->getSide(Vector3::SIDE_SOUTH), $visited, $distance + 1, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}elseif($this->findLog($pos->getSide(Vector3::SIDE_WEST), $visited, $distance + 1, $check, $fromSide) === true){
|
}elseif($this->findLog($pos->getSide(Vector3::SIDE_WEST), $visited, $distance + 1, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}elseif($this->findLog($pos->getSide(Vector3::SIDE_EAST), $visited, $distance + 1, $check, $fromSide) === true){
|
}elseif($this->findLog($pos->getSide(Vector3::SIDE_EAST), $visited, $distance + 1, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if($this->findLog($pos->getSide(Vector3::SIDE_NORTH), $visited, $distance + 1, $check, $fromSide) === true){
|
if($this->findLog($pos->getSide(Vector3::SIDE_NORTH), $visited, $distance + 1, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}elseif($this->findLog($pos->getSide(Vector3::SIDE_SOUTH), $visited, $distance + 1, $check, $fromSide) === true){
|
}elseif($this->findLog($pos->getSide(Vector3::SIDE_SOUTH), $visited, $distance + 1, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}elseif($this->findLog($pos->getSide(Vector3::SIDE_WEST), $visited, $distance + 1, $check, $fromSide) === true){
|
}elseif($this->findLog($pos->getSide(Vector3::SIDE_WEST), $visited, $distance + 1, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
if($this->findLog($pos->getSide(Vector3::SIDE_NORTH), $visited, $distance + 1, $check, $fromSide) === true){
|
if($this->findLog($pos->getSide(Vector3::SIDE_NORTH), $visited, $distance + 1, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}elseif($this->findLog($pos->getSide(Vector3::SIDE_SOUTH), $visited, $distance + 1, $check, $fromSide) === true){
|
}elseif($this->findLog($pos->getSide(Vector3::SIDE_SOUTH), $visited, $distance + 1, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}elseif($this->findLog($pos->getSide(Vector3::SIDE_EAST), $visited, $distance + 1, $check, $fromSide) === true){
|
}elseif($this->findLog($pos->getSide(Vector3::SIDE_EAST), $visited, $distance + 1, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -136,31 +132,30 @@ class Leaves extends Transparent{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if(($this->meta & 0b00001100) === 0){
|
||||||
if(($this->meta & 0b00001100) === 0){
|
$this->meta |= 0x08;
|
||||||
$this->meta |= 0x08;
|
$this->getLevel()->setBlock($this, $this, true, false);
|
||||||
$this->getLevel()->setBlock($this, $this, true, false);
|
}
|
||||||
}
|
}
|
||||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
|
||||||
if(($this->meta & 0b00001100) === 0x08){
|
|
||||||
$this->meta &= 0x03;
|
|
||||||
$visited = [];
|
|
||||||
$check = 0;
|
|
||||||
|
|
||||||
$this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new LeavesDecayEvent($this));
|
public function ticksRandomly() : bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if($ev->isCancelled() or $this->findLog($this, $visited, 0, $check) === true){
|
public function onRandomTick() : void{
|
||||||
$this->getLevel()->setBlock($this, $this, false, false);
|
if(($this->meta & 0b00001100) === 0x08){
|
||||||
}else{
|
$this->meta &= 0x03;
|
||||||
$this->getLevel()->useBreakOn($this);
|
$visited = [];
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
$ev = new LeavesDecayEvent($this);
|
||||||
}
|
$ev->call();
|
||||||
|
if($ev->isCancelled() or $this->findLog($this, $visited, 0)){
|
||||||
|
$this->getLevel()->setBlock($this, $this, false, false);
|
||||||
|
}else{
|
||||||
|
$this->getLevel()->useBreakOn($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
@ -195,4 +190,12 @@ class Leaves extends Transparent{
|
|||||||
public function canDropApples() : bool{
|
public function canDropApples() : bool{
|
||||||
return $this->meta === self::OAK;
|
return $this->meta === self::OAK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFlameEncouragement() : int{
|
||||||
|
return 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return 60;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
@ -74,26 +73,20 @@ class Lever extends Flowable{
|
|||||||
return $this->level->setBlock($blockReplace, $this, true, true);
|
return $this->level->setBlock($blockReplace, $this, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
$faces = [
|
||||||
$faces = [
|
0 => Vector3::SIDE_UP,
|
||||||
0 => Vector3::SIDE_UP,
|
1 => Vector3::SIDE_WEST,
|
||||||
1 => Vector3::SIDE_WEST,
|
2 => Vector3::SIDE_EAST,
|
||||||
2 => Vector3::SIDE_EAST,
|
3 => Vector3::SIDE_NORTH,
|
||||||
3 => Vector3::SIDE_NORTH,
|
4 => Vector3::SIDE_SOUTH,
|
||||||
4 => Vector3::SIDE_SOUTH,
|
5 => Vector3::SIDE_DOWN,
|
||||||
5 => Vector3::SIDE_DOWN,
|
6 => Vector3::SIDE_DOWN,
|
||||||
6 => Vector3::SIDE_DOWN,
|
7 => Vector3::SIDE_UP
|
||||||
7 => Vector3::SIDE_UP
|
];
|
||||||
];
|
if(!$this->getSide($faces[$this->meta & 0x07])->isSolid()){
|
||||||
if(!$this->getSide($faces[$this->meta & 0x07])->isSolid()){
|
$this->level->useBreakOn($this);
|
||||||
$this->level->useBreakOn($this);
|
|
||||||
|
|
||||||
return $type;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
|
@ -24,11 +24,16 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
|
use pocketmine\event\block\BlockFormEvent;
|
||||||
|
use pocketmine\event\block\BlockSpreadEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
use pocketmine\level\Level;
|
||||||
|
use pocketmine\level\sound\FizzSound;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
|
use function array_fill;
|
||||||
|
use function lcg_value;
|
||||||
|
use function min;
|
||||||
|
|
||||||
abstract class Liquid extends Transparent{
|
abstract class Liquid extends Transparent{
|
||||||
|
|
||||||
@ -189,10 +194,12 @@ abstract class Liquid extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function addVelocityToEntity(Entity $entity, Vector3 $vector) : void{
|
public function addVelocityToEntity(Entity $entity, Vector3 $vector) : void{
|
||||||
$flow = $this->getFlowVector();
|
if($entity->canBeMovedByCurrents()){
|
||||||
$vector->x += $flow->x;
|
$flow = $this->getFlowVector();
|
||||||
$vector->y += $flow->y;
|
$vector->x += $flow->x;
|
||||||
$vector->z += $flow->z;
|
$vector->y += $flow->y;
|
||||||
|
$vector->z += $flow->z;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract public function tickRate() : int;
|
abstract public function tickRate() : int;
|
||||||
@ -206,111 +213,102 @@ abstract class Liquid extends Transparent{
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function onNearbyBlockChange() : void{
|
||||||
* {@inheritdoc}
|
$this->checkForHarden();
|
||||||
*
|
$this->level->scheduleDelayedBlockUpdate($this, $this->tickRate());
|
||||||
* @param int $type
|
}
|
||||||
*
|
|
||||||
* @return bool|int
|
|
||||||
*/
|
|
||||||
public function onUpdate(int $type){
|
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
|
||||||
$this->checkForHarden();
|
|
||||||
$this->level->scheduleDelayedBlockUpdate($this, $this->tickRate());
|
|
||||||
|
|
||||||
return $type;
|
public function onScheduledUpdate() : void{
|
||||||
}elseif($type === Level::BLOCK_UPDATE_SCHEDULED){
|
$decay = $this->getFlowDecay($this);
|
||||||
$decay = $this->getFlowDecay($this);
|
$multiplier = $this->getFlowDecayPerBlock();
|
||||||
$multiplier = $this->getFlowDecayPerBlock();
|
|
||||||
|
|
||||||
if($decay > 0){
|
if($decay > 0){
|
||||||
$smallestFlowDecay = -100;
|
$smallestFlowDecay = -100;
|
||||||
$this->adjacentSources = 0;
|
$this->adjacentSources = 0;
|
||||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $smallestFlowDecay);
|
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $smallestFlowDecay);
|
||||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x, $this->y, $this->z + 1), $smallestFlowDecay);
|
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x, $this->y, $this->z + 1), $smallestFlowDecay);
|
||||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x - 1, $this->y, $this->z), $smallestFlowDecay);
|
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x - 1, $this->y, $this->z), $smallestFlowDecay);
|
||||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $smallestFlowDecay);
|
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $smallestFlowDecay);
|
||||||
|
|
||||||
$newDecay = $smallestFlowDecay + $multiplier;
|
$newDecay = $smallestFlowDecay + $multiplier;
|
||||||
|
|
||||||
if($newDecay >= 8 or $smallestFlowDecay < 0){
|
if($newDecay >= 8 or $smallestFlowDecay < 0){
|
||||||
$newDecay = -1;
|
$newDecay = -1;
|
||||||
}
|
|
||||||
|
|
||||||
if(($topFlowDecay = $this->getFlowDecay($this->level->getBlockAt($this->x, $this->y + 1, $this->z))) >= 0){
|
|
||||||
$newDecay = $topFlowDecay | 0x08;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($this->adjacentSources >= 2 and $this instanceof Water){
|
|
||||||
$bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z);
|
|
||||||
if($bottomBlock->isSolid()){
|
|
||||||
$newDecay = 0;
|
|
||||||
}elseif($bottomBlock instanceof Water and $bottomBlock->getDamage() === 0){
|
|
||||||
$newDecay = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if($newDecay !== $decay){
|
|
||||||
$decay = $newDecay;
|
|
||||||
if($decay < 0){
|
|
||||||
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true, true);
|
|
||||||
}else{
|
|
||||||
$this->level->setBlock($this, BlockFactory::get($this->id, $decay), true, true);
|
|
||||||
$this->level->scheduleDelayedBlockUpdate($this, $this->tickRate());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($decay >= 0){
|
if(($topFlowDecay = $this->getFlowDecay($this->level->getBlockAt($this->x, $this->y + 1, $this->z))) >= 0){
|
||||||
|
$newDecay = $topFlowDecay | 0x08;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->adjacentSources >= 2 and $this instanceof Water){
|
||||||
$bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z);
|
$bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z);
|
||||||
|
if($bottomBlock->isSolid()){
|
||||||
$this->flowIntoBlock($bottomBlock, $decay | 0x08);
|
$newDecay = 0;
|
||||||
|
}elseif($bottomBlock instanceof Water and $bottomBlock->getDamage() === 0){
|
||||||
if($decay === 0 or !$bottomBlock->canBeFlowedInto()){
|
$newDecay = 0;
|
||||||
if($decay >= 8){
|
|
||||||
$adjacentDecay = 1;
|
|
||||||
}else{
|
|
||||||
$adjacentDecay = $decay + $multiplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($adjacentDecay < 8){
|
|
||||||
$flags = $this->getOptimalFlowDirections();
|
|
||||||
|
|
||||||
if($flags[0]){
|
|
||||||
$this->flowIntoBlock($this->level->getBlockAt($this->x - 1, $this->y, $this->z), $adjacentDecay);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($flags[1]){
|
|
||||||
$this->flowIntoBlock($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $adjacentDecay);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($flags[2]){
|
|
||||||
$this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $adjacentDecay);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($flags[3]){
|
|
||||||
$this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z + 1), $adjacentDecay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->checkForHarden();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $type;
|
if($newDecay !== $decay){
|
||||||
|
$decay = $newDecay;
|
||||||
|
if($decay < 0){
|
||||||
|
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true, true);
|
||||||
|
}else{
|
||||||
|
$this->level->setBlock($this, BlockFactory::get($this->id, $decay), true, true);
|
||||||
|
$this->level->scheduleDelayedBlockUpdate($this, $this->tickRate());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
if($decay >= 0){
|
||||||
|
$bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z);
|
||||||
|
|
||||||
|
$this->flowIntoBlock($bottomBlock, $decay | 0x08);
|
||||||
|
|
||||||
|
if($decay === 0 or !$bottomBlock->canBeFlowedInto()){
|
||||||
|
if($decay >= 8){
|
||||||
|
$adjacentDecay = 1;
|
||||||
|
}else{
|
||||||
|
$adjacentDecay = $decay + $multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($adjacentDecay < 8){
|
||||||
|
$flags = $this->getOptimalFlowDirections();
|
||||||
|
|
||||||
|
if($flags[0]){
|
||||||
|
$this->flowIntoBlock($this->level->getBlockAt($this->x - 1, $this->y, $this->z), $adjacentDecay);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($flags[1]){
|
||||||
|
$this->flowIntoBlock($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $adjacentDecay);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($flags[2]){
|
||||||
|
$this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $adjacentDecay);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($flags[3]){
|
||||||
|
$this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z + 1), $adjacentDecay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->checkForHarden();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function flowIntoBlock(Block $block, int $newFlowDecay) : void{
|
protected function flowIntoBlock(Block $block, int $newFlowDecay) : void{
|
||||||
if($this->canFlowInto($block) and !($block instanceof Liquid)){
|
if($this->canFlowInto($block) and !($block instanceof Liquid)){
|
||||||
if($block->getId() > 0){
|
$ev = new BlockSpreadEvent($block, $this, BlockFactory::get($this->getId(), $newFlowDecay));
|
||||||
$this->level->useBreakOn($block);
|
$ev->call();
|
||||||
}
|
if(!$ev->isCancelled()){
|
||||||
|
if($block->getId() > 0){
|
||||||
|
$this->level->useBreakOn($block);
|
||||||
|
}
|
||||||
|
|
||||||
$this->level->setBlock($block, BlockFactory::get($this->getId(), $newFlowDecay), true, true);
|
$this->level->setBlock($block, $ev->getNewState(), true, true);
|
||||||
$this->level->scheduleDelayedBlockUpdate($block, $this->tickRate());
|
$this->level->scheduleDelayedBlockUpdate($block, $this->tickRate());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,10 +434,12 @@ abstract class Liquid extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function liquidCollide(Block $cause, Block $result) : bool{
|
protected function liquidCollide(Block $cause, Block $result) : bool{
|
||||||
//TODO: add events
|
$ev = new BlockFormEvent($this, $result);
|
||||||
|
$ev->call();
|
||||||
$this->level->setBlock($this, $result, true, true);
|
if(!$ev->isCancelled()){
|
||||||
$this->level->broadcastLevelSoundEvent($this->add(0.5, 0.5, 0.5), LevelSoundEventPacket::SOUND_FIZZ, (int) ((2.6 + (lcg_value() - lcg_value()) * 0.8) * 1000));
|
$this->level->setBlock($this, $ev->getNewState(), true, true);
|
||||||
|
$this->level->addSound(new FizzSound($this->add(0.5, 0.5, 0.5), 2.6 + (lcg_value() - lcg_value()) * 0.8));
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,4 +66,8 @@ class Magma extends Solid{
|
|||||||
$entity->attack($ev);
|
$entity->attack($ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function burnsForever() : bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class Melon extends Transparent{
|
class Melon extends Transparent{
|
||||||
|
|
||||||
|
@ -26,9 +26,8 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\event\block\BlockGrowEvent;
|
use pocketmine\event\block\BlockGrowEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Server;
|
use function mt_rand;
|
||||||
|
|
||||||
class MelonStem extends Crops{
|
class MelonStem extends Crops{
|
||||||
|
|
||||||
@ -42,45 +41,34 @@ class MelonStem extends Crops{
|
|||||||
$this->meta = $meta;
|
$this->meta = $meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onRandomTick() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if(mt_rand(0, 2) === 1){
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
|
if($this->meta < 0x07){
|
||||||
$this->getLevel()->useBreakOn($this);
|
$block = clone $this;
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
++$block->meta;
|
||||||
}
|
$ev = new BlockGrowEvent($this, $block);
|
||||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
$ev->call();
|
||||||
if(mt_rand(0, 2) === 1){
|
if(!$ev->isCancelled()){
|
||||||
if($this->meta < 0x07){
|
$this->getLevel()->setBlock($this, $ev->getNewState(), true);
|
||||||
$block = clone $this;
|
}
|
||||||
++$block->meta;
|
}else{
|
||||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
for($side = 2; $side <= 5; ++$side){
|
||||||
|
$b = $this->getSide($side);
|
||||||
|
if($b->getId() === self::MELON_BLOCK){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$side = $this->getSide(mt_rand(2, 5));
|
||||||
|
$d = $side->getSide(Vector3::SIDE_DOWN);
|
||||||
|
if($side->getId() === self::AIR and ($d->getId() === self::FARMLAND or $d->getId() === self::GRASS or $d->getId() === self::DIRT)){
|
||||||
|
$ev = new BlockGrowEvent($side, BlockFactory::get(Block::MELON_BLOCK));
|
||||||
|
$ev->call();
|
||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
$this->getLevel()->setBlock($this, $ev->getNewState(), true);
|
$this->getLevel()->setBlock($side, $ev->getNewState(), true);
|
||||||
}
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_RANDOM;
|
|
||||||
}else{
|
|
||||||
for($side = 2; $side <= 5; ++$side){
|
|
||||||
$b = $this->getSide($side);
|
|
||||||
if($b->getId() === self::MELON_BLOCK){
|
|
||||||
return Level::BLOCK_UPDATE_RANDOM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$side = $this->getSide(mt_rand(2, 5));
|
|
||||||
$d = $side->getSide(Vector3::SIDE_DOWN);
|
|
||||||
if($side->getId() === self::AIR and ($d->getId() === self::FARMLAND or $d->getId() === self::GRASS or $d->getId() === self::DIRT)){
|
|
||||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($side, BlockFactory::get(Block::MELON_BLOCK)));
|
|
||||||
if(!$ev->isCancelled()){
|
|
||||||
$this->getLevel()->setBlock($side, $ev->getNewState(), true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_RANDOM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\TieredTool;
|
use pocketmine\item\TieredTool;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class MonsterSpawner extends Transparent{
|
class MonsterSpawner extends Transparent{
|
||||||
|
|
||||||
@ -57,4 +58,8 @@ class MonsterSpawner extends Transparent{
|
|||||||
public function isAffectedBySilkTouch() : bool{
|
public function isAffectedBySilkTouch() : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getXpDropAmount() : int{
|
||||||
|
return mt_rand(15, 43);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,9 +26,8 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\event\block\BlockSpreadEvent;
|
use pocketmine\event\block\BlockSpreadEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Server;
|
use function mt_rand;
|
||||||
|
|
||||||
class Mycelium extends Solid{
|
class Mycelium extends Solid{
|
||||||
|
|
||||||
@ -60,19 +59,18 @@ class Mycelium extends Solid{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onRandomTick() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_RANDOM){
|
//TODO: light levels
|
||||||
//TODO: light levels
|
$x = mt_rand($this->x - 1, $this->x + 1);
|
||||||
$x = mt_rand($this->x - 1, $this->x + 1);
|
$y = mt_rand($this->y - 2, $this->y + 2);
|
||||||
$y = mt_rand($this->y - 2, $this->y + 2);
|
$z = mt_rand($this->z - 1, $this->z + 1);
|
||||||
$z = mt_rand($this->z - 1, $this->z + 1);
|
$block = $this->getLevel()->getBlockAt($x, $y, $z);
|
||||||
$block = $this->getLevel()->getBlockAt($x, $y, $z);
|
if($block->getId() === Block::DIRT){
|
||||||
if($block->getId() === Block::DIRT){
|
if($block->getSide(Vector3::SIDE_UP) instanceof Transparent){
|
||||||
if($block->getSide(Vector3::SIDE_UP) instanceof Transparent){
|
$ev = new BlockSpreadEvent($block, $this, BlockFactory::get(Block::MYCELIUM));
|
||||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($block, $this, BlockFactory::get(Block::MYCELIUM)));
|
$ev->call();
|
||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
$this->getLevel()->setBlock($block, $ev->getNewState());
|
$this->getLevel()->setBlock($block, $ev->getNewState());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,5 +48,4 @@ class NetherBrickStairs extends Stair{
|
|||||||
public function getToolHarvestLevel() : int{
|
public function getToolHarvestLevel() : int{
|
||||||
return TieredTool::TIER_WOODEN;
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\TieredTool;
|
use pocketmine\item\TieredTool;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class NetherQuartzOre extends Solid{
|
class NetherQuartzOre extends Solid{
|
||||||
|
|
||||||
@ -57,4 +58,7 @@ class NetherQuartzOre extends Solid{
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getXpDropAmount() : int{
|
||||||
|
return mt_rand(2, 5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,5 +61,4 @@ class NetherReactor extends Solid{
|
|||||||
ItemFactory::get(Item::DIAMOND, 0, 3)
|
ItemFactory::get(Item::DIAMOND, 0, 3)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,9 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\event\block\BlockGrowEvent;
|
use pocketmine\event\block\BlockGrowEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
use function mt_rand;
|
||||||
|
|
||||||
class NetherWartPlant extends Flowable{
|
class NetherWartPlant extends Flowable{
|
||||||
protected $id = Block::NETHER_WART_PLANT;
|
protected $id = Block::NETHER_WART_PLANT;
|
||||||
@ -44,10 +44,6 @@ class NetherWartPlant extends Flowable{
|
|||||||
return "Nether Wart";
|
return "Nether Wart";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ticksRandomly() : bool{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||||
if($down->getId() === Block::SOUL_SAND){
|
if($down->getId() === Block::SOUL_SAND){
|
||||||
@ -59,30 +55,26 @@ class NetherWartPlant extends Flowable{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
switch($type){
|
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::SOUL_SAND){
|
||||||
case Level::BLOCK_UPDATE_RANDOM:
|
$this->getLevel()->useBreakOn($this);
|
||||||
if($this->meta < 3 and mt_rand(0, 10) === 0){ //Still growing
|
|
||||||
$block = clone $this;
|
|
||||||
$block->meta++;
|
|
||||||
$this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
|
||||||
|
|
||||||
if(!$ev->isCancelled()){
|
|
||||||
$this->getLevel()->setBlock($this, $ev->getNewState(), false, true);
|
|
||||||
|
|
||||||
return $type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Level::BLOCK_UPDATE_NORMAL:
|
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::SOUL_SAND){
|
|
||||||
$this->getLevel()->useBreakOn($this);
|
|
||||||
return $type;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
public function ticksRandomly() : bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onRandomTick() : void{
|
||||||
|
if($this->meta < 3 and mt_rand(0, 10) === 0){ //Still growing
|
||||||
|
$block = clone $this;
|
||||||
|
$block->meta++;
|
||||||
|
$ev = new BlockGrowEvent($this, $block);
|
||||||
|
$ev->call();
|
||||||
|
if(!$ev->isCancelled()){
|
||||||
|
$this->getLevel()->setBlock($this, $ev->getNewState(), false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
|
@ -48,4 +48,8 @@ class Netherrack extends Solid{
|
|||||||
public function getToolHarvestLevel() : int{
|
public function getToolHarvestLevel() : int{
|
||||||
return TieredTool::TIER_WOODEN;
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function burnsForever() : bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user