mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-08 19:02:59 +00:00
Compare commits
1079 Commits
api/3.0.0-
...
1.7dev-318
Author | SHA1 | Date | |
---|---|---|---|
716c1f29b4 | |||
0df3b00de4 | |||
13e5718463 | |||
270e0c076c | |||
3765511317 | |||
8daa8deae9 | |||
e055ce9526 | |||
3ed8855894 | |||
f25255e46c | |||
7db8345424 | |||
bc7ba3b3c1 | |||
1dd2203ee5 | |||
554096953b | |||
55a1731da3 | |||
ba3fe20227 | |||
7b04049bb7 | |||
30211bee82 | |||
e318dc12a5 | |||
967ce99b03 | |||
9bdda54aec | |||
18e4e5364f | |||
98cfd0b398 | |||
a245615531 | |||
0a19a2611a | |||
50be26958a | |||
67c6fca0ed | |||
d99e9513b0 | |||
5a353012de | |||
087badcb48 | |||
d9769360fe | |||
9fb93985d6 | |||
2b22d5d8cc | |||
2db13bd114 | |||
11cc20972f | |||
4821e7386d | |||
584810780a | |||
55de75b914 | |||
2a1a17aa7a | |||
90165cf99d | |||
a4ca3f1d1c | |||
f783789e5a | |||
43be64baed | |||
5c92c8a9d3 | |||
d2dc49cd9c | |||
f148c366f9 | |||
91d84aaff4 | |||
6b78ba8c25 | |||
b9de2e8b4b | |||
15764543b4 | |||
2c34648c3d | |||
3e3157cbe1 | |||
07abd61f73 | |||
a456b7cfca | |||
ece37d1e19 | |||
cccaade00c | |||
7f0a961526 | |||
68ac4f538f | |||
f14b7cbf78 | |||
f4ff5d81ea | |||
28a840d161 | |||
292e462ea0 | |||
c8379efbce | |||
1b5746fd97 | |||
4a0ac01697 | |||
9bcb41fb21 | |||
20b86bdea8 | |||
0b1a9ba062 | |||
45b003ac2e | |||
769a50faa5 | |||
af85659c63 | |||
95fa1824c8 | |||
251d5d7946 | |||
3b5eb45ff5 | |||
fd847f02ad | |||
18d3a97466 | |||
04668d534d | |||
092cc2750f | |||
68809d992b | |||
1641183674 | |||
72531209bf | |||
8c6ab3e634 | |||
97e2d64592 | |||
a547e2cca8 | |||
cdebb62c35 | |||
2e73fd7f8c | |||
51906daad0 | |||
ce67bc620a | |||
bcefc3a54b | |||
f5378ab604 | |||
dab7cfde1c | |||
6e1318b522 | |||
cd8006e242 | |||
f5abed95ec | |||
489b9fc29b | |||
b524b841c5 | |||
41f292d995 | |||
fd8a562e02 | |||
cc553a157d | |||
a6d1cc27ec | |||
d8c90be5b8 | |||
060426ff12 | |||
eeea4fa06a | |||
401e33dd85 | |||
2893aac3ac | |||
c5c74c1898 | |||
423bea4b57 | |||
e3567faa94 | |||
4b5040dcc7 | |||
21c79b0645 | |||
7b5df10b6a | |||
c4fe9ad32d | |||
60b62a4890 | |||
061a9444cc | |||
3eb73ab468 | |||
15d6fd86e2 | |||
0c092a7ceb | |||
b9501ef415 | |||
5afe4fdb5b | |||
cc7ed7a28f | |||
7e9b89e48a | |||
63fccd4682 | |||
35e7aca88f | |||
9413f155ce | |||
6569fdbe04 | |||
d8b1757ebc | |||
8f0ee84277 | |||
b7a9e10d49 | |||
be2d134994 | |||
7b1bfc0520 | |||
59d9d6a7df | |||
8d095dff6c | |||
4981931c4a | |||
5dafabbec2 | |||
2a5d954c67 | |||
287f08cbd1 | |||
76469e1d5f | |||
c4c83e23ca | |||
eccc7bf7b3 | |||
78ca2f2e58 | |||
cef9c4621c | |||
151681bd80 | |||
327907988b | |||
97dbf61236 | |||
2be8b576ef | |||
6dbdefafdd | |||
9598b8cee4 | |||
246c6daef6 | |||
2601e35990 | |||
bdfd9c95dd | |||
cd44551d64 | |||
cebb4b35f6 | |||
7267f1a520 | |||
66a3354b31 | |||
ac7384a2b4 | |||
748beaaaa7 | |||
58788b4bc7 | |||
ae76ac82c8 | |||
e4000f8f03 | |||
ebcce43131 | |||
119913da30 | |||
1a88f59b23 | |||
fdfe70b9f2 | |||
3bda1473e7 | |||
29cd071108 | |||
1810088acf | |||
51e4a62e7b | |||
aa91183504 | |||
ae5aa31e7b | |||
7239dbbb1a | |||
3738ab1f8a | |||
8fafef2f7f | |||
5b9515b20f | |||
69e29236aa | |||
e8453b7872 | |||
00bf190e54 | |||
81dee2f9fc | |||
f6875705a1 | |||
d294d5a91b | |||
a7e9aa4bc1 | |||
628ff9449e | |||
7f5fe137d1 | |||
18448cbcb8 | |||
b0104099fe | |||
68195c64ce | |||
27aa51bac4 | |||
eac1d76e8b | |||
a8c6e14d02 | |||
bf68a6a9fc | |||
4dfd171af0 | |||
fc9c264e77 | |||
04ba41c58c | |||
736cc927ff | |||
4be7885ee4 | |||
7dc5dc3a9f | |||
f7ee78233b | |||
88807e8b22 | |||
5a6812357b | |||
ca401ec3f5 | |||
9bbebaa071 | |||
76117e7fa0 | |||
088a44ea3a | |||
b54f256fea | |||
c09d782503 | |||
b3b3ee7c56 | |||
ab5bbaa7bd | |||
afa37bd2aa | |||
49ac2555ce | |||
edd0189d59 | |||
b76b9d53fe | |||
42dd9d6abd | |||
9cd7f39c03 | |||
f6e30d4225 | |||
27798c69ee | |||
a33be643c4 | |||
a06ff3d96b | |||
e6cecabf3f | |||
c273a46537 | |||
c448f4a3b5 | |||
86b76bfcab | |||
7ba193dc2e | |||
f565791e41 | |||
bc0434913e | |||
9bc8d8db79 | |||
d0bf0ff083 | |||
7dc1fc54b1 | |||
bae42dc0d9 | |||
ab809f8a2b | |||
2162675b64 | |||
8f63117dac | |||
1c9b4f3e21 | |||
48d2d7e422 | |||
52bd042bde | |||
4b63a22f8c | |||
c47f1f572c | |||
7a77bb0402 | |||
90cb018de2 | |||
992c4ce6a0 | |||
78af87a572 | |||
c79a5509f6 | |||
827ee5d4f9 | |||
f5b0cbb337 | |||
18777a9041 | |||
13d50aff62 | |||
5b191327bc | |||
8811188e71 | |||
38fad4b963 | |||
e64076ec81 | |||
ccbdb77618 | |||
91c6086ae1 | |||
85ec7d9732 | |||
10f597cd64 | |||
6e5759b1d1 | |||
03d3e595d6 | |||
8ca59d12e9 | |||
89e4defa29 | |||
f5534a9ab0 | |||
28bce8d48c | |||
3c02a6a8ed | |||
6b0ac8adb8 | |||
38ec5da260 | |||
240cc3043a | |||
043ae487de | |||
f12701e582 | |||
6e961ae897 | |||
e1d10f595a | |||
178dd1b981 | |||
826ec90856 | |||
0523f26613 | |||
5190d9c1e2 | |||
c8fd0eaf8b | |||
53ef9b653a | |||
030cc4afb0 | |||
9bd7f771d3 | |||
10f6a0eef0 | |||
d0a96f35da | |||
65e908a403 | |||
d7091f4460 | |||
c6670b2e74 | |||
194278d986 | |||
0e2e9aab2e | |||
1b5fed983b | |||
5aba87b250 | |||
f01ce8e994 | |||
d89b8cf12e | |||
6aa9b081e9 | |||
dbed80386a | |||
cefad0444c | |||
ee052f91d4 | |||
ef6250967f | |||
61cfdac6a1 | |||
fd7fb10223 | |||
6897cb4774 | |||
8e7ad532f1 | |||
9e8366725a | |||
b14ecc18c4 | |||
55720d9f0a | |||
0262465a26 | |||
7996a7b08c | |||
4a1fc1bdf7 | |||
85b2b2ae2e | |||
38e11aae5e | |||
f0755d1659 | |||
fd33a65e3b | |||
7baadf9dad | |||
ca23864e4c | |||
8728547a11 | |||
90fb3c5e12 | |||
1fb6d12a6b | |||
1323d89139 | |||
136ab1dba1 | |||
8cae20e818 | |||
ff2b3bfa2a | |||
361b262d3a | |||
1fd7f441b4 | |||
3f56d6ddc8 | |||
1e4cbb0dd9 | |||
a99eee9def | |||
bdee746e46 | |||
642c7733cd | |||
c8199e14ad | |||
0f37bc35ba | |||
8dc3d019f6 | |||
bd64172750 | |||
0e51820dfb | |||
30d2318bb7 | |||
63634d7e7d | |||
d941bf8e74 | |||
8c9d9626ab | |||
6b34c47c96 | |||
77241e14ce | |||
15b08c1417 | |||
4d1daecd91 | |||
53e5db5142 | |||
ad72fe6232 | |||
8b33f711d0 | |||
319735db3a | |||
c283d87494 | |||
be27e03126 | |||
c1c290cd39 | |||
5267c571e9 | |||
0fac3b9a9d | |||
23a38400e2 | |||
297172d111 | |||
825d4f9702 | |||
1d31958ce6 | |||
130a60f2b2 | |||
07268e4b37 | |||
441efc4ae2 | |||
88bd7713c5 | |||
aaa3b6e59a | |||
25adac8859 | |||
8d0b881762 | |||
16cb75ef38 | |||
3b9689674d | |||
7f5d8cc900 | |||
8761256246 | |||
8c363cb571 | |||
10b765e17a | |||
0eb866bf25 | |||
c46caa38e1 | |||
17d949f476 | |||
c569f55933 | |||
01d8d216ca | |||
f1ccee505b | |||
a61adb5991 | |||
cae1a3bb4b | |||
6681bd250a | |||
38293913ee | |||
8493ce8a35 | |||
9b7868238c | |||
953c1ef4ec | |||
021a9a4820 | |||
5b7565664c | |||
ebdfbe6bb9 | |||
85ff236461 | |||
d7422d9283 | |||
fcb3c4820e | |||
c72ef605b9 | |||
e274f1b7f8 | |||
69514c5763 | |||
2c6205e3f3 | |||
12c154badf | |||
2215543e39 | |||
b310959fd1 | |||
c9ee206fe6 | |||
d065e76a41 | |||
6877ac35eb | |||
f0c1ea7dd7 | |||
6aaef1660a | |||
78d49f8e66 | |||
de6ebc5791 | |||
815c697767 | |||
231617b9d0 | |||
90cb3c010f | |||
2398e2450a | |||
bb9299070d | |||
58bf5d6679 | |||
cb7911ee9c | |||
aa9fd1b4f9 | |||
7483f22e8b | |||
89f5567476 | |||
4df261b75a | |||
41780fd195 | |||
0b83c61494 | |||
1d338bfdf9 | |||
2cff5a500c | |||
f077ba4748 | |||
2f614c5dc2 | |||
dcf34b7188 | |||
ca84532640 | |||
4d8d57ca5e | |||
75e32b11b7 | |||
9f44b2ed75 | |||
62aba15f9e | |||
1c02c747ca | |||
22d8626e23 | |||
b071ce9c5a | |||
a6c0f1512c | |||
604d8ecf9a | |||
5d75d3d5b6 | |||
8b13b520e0 | |||
2603f5cc63 | |||
00e4fff259 | |||
a06c934f4d | |||
14ea76ecd7 | |||
c81b76cbf6 | |||
517609dc2e | |||
506118e28f | |||
6e8631347d | |||
5335ed9394 | |||
138d85307b | |||
226175f961 | |||
297cfcf168 | |||
9ea39ea3d7 | |||
16aeb0ac85 | |||
8caabd3267 | |||
ddfe828445 | |||
67ad2d25b9 | |||
b9c4a65307 | |||
23752548fe | |||
190f4dd6ab | |||
120cf56a47 | |||
21f09d5fdb | |||
bde6d7db8d | |||
adc6b03d4c | |||
fd52022065 | |||
ea5bd0348a | |||
c3cf82ab26 | |||
6abef6b22d | |||
9902d29734 | |||
7475aa3a18 | |||
6d6283b7f3 | |||
a3d21de559 | |||
6a717d8050 | |||
ece0692229 | |||
b5d2402c9b | |||
37b050f864 | |||
d07b5ba1e1 | |||
697ea55fb7 | |||
8b3fad8a7b | |||
f2402f2122 | |||
b548c4fdbe | |||
a982344b96 | |||
0b2b9126a2 | |||
f4f2323518 | |||
badd669b3d | |||
c7fd3eb725 | |||
a5f5502380 | |||
6d5620606e | |||
20f34fba53 | |||
61968cca28 | |||
13187e1749 | |||
7c212d3d53 | |||
9e142655ea | |||
1fec16f167 | |||
4ab286a142 | |||
44dd7c2222 | |||
97911aa9cf | |||
7ff143c793 | |||
cd7724d94a | |||
76e213ae73 | |||
8ce833bf74 | |||
ba27fff853 | |||
80f2519d7d | |||
ebda6ec19b | |||
6553c82320 | |||
1b0ed0f1b8 | |||
5433a3f964 | |||
3ee8f2b182 | |||
238b3ca4c1 | |||
2c3d7c49f9 | |||
76acb1da7b | |||
17518195d1 | |||
2443a57234 | |||
90edb8ebe7 | |||
55e32424a0 | |||
d6266d19b6 | |||
95752ef542 | |||
84c8ac03fb | |||
da4c9cf404 | |||
0f2ca99c67 | |||
a7674c52e6 | |||
a52fa93998 | |||
770616d4ab | |||
d1852834de | |||
eb4594348b | |||
5a3ce42f74 | |||
0712979908 | |||
ae715cf2f2 | |||
3a5fc78c53 | |||
445a67954d | |||
50580f4408 | |||
4250e99e3a | |||
8229410e27 | |||
938af60733 | |||
8a35b9da29 | |||
c32b75fa18 | |||
b8ade18888 | |||
592ce3c9e9 | |||
876659cc73 | |||
604d11a8fd | |||
d2ace6bdd2 | |||
672b7610a9 | |||
456ddd3fb3 | |||
b62597fe63 | |||
9e54980ded | |||
121777375e | |||
93e149e91c | |||
1f70a7830e | |||
2f3c77c68a | |||
02f42eba48 | |||
9451dd361e | |||
da83b879c0 | |||
d1fd6aef44 | |||
cd02f1e4be | |||
eeedcf7332 | |||
216fc6fe31 | |||
17053389b0 | |||
8475c63426 | |||
f2ff0198cc | |||
c394aea803 | |||
e1d894057c | |||
5b3bed8b06 | |||
159b2e3d5e | |||
bed68a012d | |||
e0307411da | |||
e88053faf4 | |||
e51106e64c | |||
0e24596aed | |||
276fccf4bb | |||
64f2e7587d | |||
bedfca8698 | |||
4a3f01703e | |||
41c6cb6f97 | |||
384a4b3a09 | |||
e5e76d4c93 | |||
a7ad26426f | |||
2688228a6f | |||
e15eefc58f | |||
f73d3d086e | |||
41f5cba971 | |||
8853452feb | |||
d8f0dd6db8 | |||
09c53552c1 | |||
c8ed2406d7 | |||
a4ec2b7f2c | |||
1f6d325328 | |||
f35ca147bb | |||
9efd350e78 | |||
be4f48a119 | |||
b6fb2bca13 | |||
4f1302adf2 | |||
83f29e5639 | |||
e825ebd8fa | |||
83af4dcd59 | |||
f6c31680f6 | |||
6320a63ca5 | |||
9e02f3c4e3 | |||
2cd05bf5b5 | |||
5b4035253b | |||
77376d3e33 | |||
56e45a031b | |||
21a1e0eb6b | |||
670a9fe44f | |||
6efa4343b1 | |||
dc3f13cd30 | |||
b4c4005009 | |||
eebc52e00b | |||
20aa519f3a | |||
741394dab1 | |||
ea414ea72d | |||
696c67f541 | |||
021dbd65d7 | |||
8510be062c | |||
7b142d4742 | |||
643e10037c | |||
0257432afc | |||
4950157f1d | |||
c4d8c28338 | |||
eda2473e78 | |||
4b65fef957 | |||
fbe2567e58 | |||
9a0b3a6e22 | |||
5fc50aeda5 | |||
ebb71fc6c5 | |||
ae3a8a5493 | |||
9be1b929a5 | |||
6480f7a989 | |||
1576a79644 | |||
02cbf800d0 | |||
5a4fbc6f5a | |||
83fcec3e94 | |||
5d436a06ec | |||
8958b3c51c | |||
c1ff7bbef4 | |||
74ee94b385 | |||
5208ad885c | |||
0c798222a4 | |||
e8bd0c3e09 | |||
51be88c698 | |||
0dc8362536 | |||
9bae4d8ef6 | |||
bb4808c23e | |||
3025f76cd0 | |||
1e539c4e3b | |||
590003d7c1 | |||
72d40860f3 | |||
d3d1e32309 | |||
36d47a33f3 | |||
260179197b | |||
82fd3b540e | |||
75644b5df2 | |||
3ad1b1ba7f | |||
b4c2305c7f | |||
1d0f0a2999 | |||
8ca37b3813 | |||
2ba601b6e9 | |||
06083d6dc4 | |||
2d8395f70e | |||
6b5c0af161 | |||
c84218c55b | |||
6b7a382625 | |||
54b6a5710e | |||
7958fffa07 | |||
98e0a2ecba | |||
44f1dedbf8 | |||
899e318a88 | |||
23eb8600ab | |||
989505c42c | |||
d9da9accbc | |||
711d62b5eb | |||
49506659e0 | |||
7886918140 | |||
8a151dc373 | |||
58a12fdfa3 | |||
50dffeb6a1 | |||
63d2b341b9 | |||
77cd8e7799 | |||
10ff2948ac | |||
0d0df3390a | |||
e4a5cb6021 | |||
71e354cf1d | |||
7d3fca83f0 | |||
3fdbcee10f | |||
4e9af1ac45 | |||
475066c9f5 | |||
d5f6966ce3 | |||
0ad4a59d5a | |||
5f6dc25c9f | |||
3b7fc21839 | |||
ecba80fd63 | |||
fb59b57bdf | |||
2b4e303f52 | |||
2103c981a9 | |||
3188f1c053 | |||
fdf71841e1 | |||
11fae493a5 | |||
3135fe3c69 | |||
561d8e7a39 | |||
3048a3b39b | |||
63c12440dc | |||
b912b9173c | |||
ca3cf3e067 | |||
8a02dbb15a | |||
f0b4a33e2e | |||
306bf7be5f | |||
0b47324fe3 | |||
17be06a56d | |||
caff686827 | |||
210bdc2436 | |||
acaa0d2740 | |||
ffefcd4473 | |||
8957dbf08e | |||
2d626d1d90 | |||
253db40a11 | |||
8a3b31077e | |||
1f4e6535bb | |||
6ae24c5c19 | |||
036663e0b5 | |||
344500785c | |||
a95d173989 | |||
e72d8cf8f5 | |||
c0e0730923 | |||
b6fe231bc1 | |||
3bd94c9da7 | |||
2e5e016b87 | |||
822c048af0 | |||
6e4b8ba677 | |||
a5a8732800 | |||
21887b283f | |||
3e141afe48 | |||
aa6eef26e9 | |||
87c16dab23 | |||
c1542d853f | |||
8274f5b3cc | |||
e8be8550a0 | |||
b3dada4cb9 | |||
ed5f69f170 | |||
7d777510c5 | |||
6ff92f2adf | |||
f32e880542 | |||
6cacb368ce | |||
6fa59230db | |||
1a7f567a70 | |||
42fb1d1fef | |||
cca9cf2c86 | |||
7c00982fff | |||
3150c50cac | |||
57e7c3d91f | |||
3e8825f826 | |||
ab3b50f062 | |||
dbb92096e4 | |||
24bdf330d5 | |||
b28128f835 | |||
fb5587350d | |||
e6a2b0f270 | |||
bb230c5812 | |||
6de8415c79 | |||
2018ad6376 | |||
b5790d19bf | |||
9390866a13 | |||
c3b8be3f60 | |||
b9355387da | |||
7f99d9019a | |||
8bb0c53797 | |||
46a2e6cbf8 | |||
8fc1501e89 | |||
6a191b5069 | |||
08b8debd78 | |||
2a7b736f18 | |||
c2a7c2c6cd | |||
4d874e7e78 | |||
23866359c9 | |||
3a214b7ce6 | |||
6341d3a0dc | |||
72d1948f30 | |||
a7f5ee2f3e | |||
6b773dc04d | |||
6af87b7b30 | |||
5283975f20 | |||
a5c6c8b973 | |||
caa229a25f | |||
4731bf0a16 | |||
30df0c2418 | |||
e485999218 | |||
650afe2d94 | |||
fa58736360 | |||
c33972aa67 | |||
6bcc8cea8e | |||
f2467d3dbc | |||
be7e97e0bb | |||
767f0dcbf6 | |||
c9fdb66c78 | |||
8a28dfa64d | |||
c6a6571c07 | |||
6d7b76f356 | |||
8cca8e1256 | |||
30c5487f94 | |||
728851594b | |||
2726f2a011 | |||
1a5e3b2ad0 | |||
1493cde07f | |||
6cd4d2c5a2 | |||
6504fdabab | |||
394f420059 | |||
b8a30309bb | |||
1a6517ea4e | |||
9c9095060f | |||
97f6a32557 | |||
409fc282d2 | |||
d474f73665 | |||
c2dfef700f | |||
dca7efa03c | |||
b4a149cce8 | |||
2a67507997 | |||
70bd9afd37 | |||
56dfa7d000 | |||
390df00966 | |||
82fd0e8d47 | |||
6259f42d81 | |||
08d4d7fe0e | |||
ae612b913e | |||
adbc298909 | |||
d92a6240d8 | |||
4a7c40edd5 | |||
1dd8fc008b | |||
ec079b68a6 | |||
ecfcf49984 | |||
f7aad8e2fe | |||
a73c6f1861 | |||
a365c831a8 | |||
c0377fc63a | |||
22d148a59d | |||
a1ce535d02 | |||
993af0fa30 | |||
b83c135c3f | |||
8bf1cc9e48 | |||
c70690a600 | |||
4b4f2af9e3 | |||
9047c2c1ef | |||
89ca2ac2d5 | |||
6a2a74a457 | |||
7ba807fd42 | |||
19410754c6 | |||
8cd31c2dc4 | |||
c09a5ab301 | |||
a0ef15b15e | |||
03826d9cbc | |||
080b35bf53 | |||
e9c46da7f0 | |||
0f79b19fdc | |||
69ae37d191 | |||
86742fcf30 | |||
a4b8dd43e6 | |||
e11f1e94e9 | |||
938452bfe9 | |||
a724395148 | |||
bc10edfdd3 | |||
f7d07ca155 | |||
be7b057fa5 | |||
8637e0224f | |||
8919d4a372 | |||
0cf3914f5d | |||
e9a638d84a | |||
e3b3f60c66 | |||
1bae973502 | |||
e0f8a02bb8 | |||
846be84324 | |||
8ef24423d1 | |||
8fc38c36f9 | |||
eb05f2ecde | |||
478e954b3f | |||
313fdb9e87 | |||
1bf18ba8d2 | |||
5011198a4e | |||
e96fa8b682 | |||
bf3868c078 | |||
3167817e34 | |||
433b8369f5 | |||
0612244b5e | |||
487233a101 | |||
4341fb8347 | |||
789df942b6 | |||
9e99252817 | |||
75cc2d6914 | |||
61b857a81c | |||
2024e9ecdf | |||
4765242397 | |||
3687b149b9 | |||
1aae9e03b6 | |||
c43ab12a9a | |||
cd66f58526 | |||
7870a8672e | |||
eac756470a | |||
a302b4988f | |||
2193adf844 | |||
890f72dbf2 | |||
595e1ab52f | |||
4a7abb7033 | |||
d358e13868 | |||
1f630e57f2 | |||
cc1d1b0f45 | |||
78c09267e5 | |||
c445db421f | |||
e18a3ac933 | |||
75863e2a44 | |||
5aea9220c9 | |||
bd7205dd64 | |||
82a63ed18e | |||
cf07af8b55 | |||
b775e8c88a | |||
51091fe87b | |||
7c14ffbcfa | |||
db93827650 | |||
c2186041d6 | |||
481114281e | |||
51b0673b4b | |||
606b9b687d | |||
45618c7cfe | |||
3f03d9e683 | |||
f0d12a0b30 | |||
9cc27b2719 | |||
87e54d7a3a | |||
29e88d8592 | |||
c6e800cf42 | |||
b7b7bcee4f | |||
6ea0eb47ec | |||
b9a87ed147 | |||
742f593758 | |||
1e9ff44890 | |||
55c4e35407 | |||
e83ffd5afe | |||
54453d0b0a | |||
51d510aa4f | |||
4cd97a7c7a | |||
d586ad03ec | |||
61d354a4ea | |||
6f126ad239 | |||
efea39e0a4 | |||
d4bb078566 | |||
6686bd4442 | |||
2b02fcfe2c | |||
138fb88431 | |||
26577d9d5b | |||
2f4943ac90 | |||
eda7965f86 | |||
4666560731 | |||
b01ad01eff | |||
4ba3a3af3d | |||
5baf59ca56 | |||
902957cb53 | |||
3463bea932 | |||
105917a534 | |||
b83082f224 | |||
840a3883b1 | |||
ad4659365a | |||
8d858e3e6d | |||
22ba017965 | |||
8bb0e8d398 | |||
087a994393 | |||
e4e4ef5f2a | |||
3ac51e1095 | |||
2db6ea6b18 | |||
b6ae92e1a7 | |||
31e2c1d26c | |||
846e3b6f1e | |||
0e525ac1c3 | |||
8382970d56 | |||
db3cd1829c | |||
caced595d2 | |||
86f3b257a7 | |||
1ed5de1d3b | |||
63358a8065 | |||
f6ff03fc31 | |||
0ad16c1919 | |||
38b8f14758 | |||
8779259734 | |||
2f306c3a38 | |||
57379b93ce | |||
954271b90f | |||
645d744e05 | |||
4c764072b2 | |||
3446f68c74 | |||
ca6826898b | |||
76ab3d4288 | |||
b6c1139b27 | |||
af06d78725 | |||
8cc1003956 | |||
92281da514 | |||
5c8297f4a1 | |||
23ed3334c2 | |||
674394c4f5 | |||
4e381ab033 | |||
c5527db424 | |||
aecff7c782 | |||
0207b22110 | |||
a77c1ce13c | |||
afd90adb1c | |||
2e480b5ea1 | |||
d4cc7d13cd | |||
f6c0ba9846 | |||
f3c38700f5 | |||
77b1b565a4 | |||
36c95660e6 | |||
905d3f1610 | |||
0f174f7605 | |||
60f5c7ccef | |||
85c1535c75 | |||
568e2760f1 | |||
fe8cb8cd86 | |||
15b47fcb2f | |||
00e6d6a6b1 | |||
8887a92d4b | |||
a9afad10bc | |||
b41fef0276 | |||
fe3b5bac51 | |||
0a4d62b405 | |||
0935855def | |||
c7c7a40899 | |||
162a08b8cb | |||
b9ad0b99a5 | |||
576702ffa9 | |||
dbb8e8ad0a | |||
4a9acf564c | |||
69f64dd802 | |||
11169b0777 | |||
71af694cc1 | |||
c51c8ae700 | |||
713f3facf9 | |||
df577bddc2 | |||
046f17c9e2 | |||
50f7d04044 | |||
4ccd955647 | |||
c383c7b0dd | |||
adbb53929e | |||
8a7259aa73 | |||
76ceddf266 | |||
11f35d28c2 | |||
c4f461f65d | |||
702c129a97 | |||
56306f6636 | |||
18f1376c65 | |||
49eb0eb050 | |||
13fd8b681e | |||
40f2d7fcdc | |||
c537cea87e | |||
eaef2bd169 | |||
966e4bf8a1 | |||
f889bf9cf5 | |||
6d90f91be0 | |||
0a52e210db | |||
971703a618 | |||
de359a2bce | |||
1266f8f1aa | |||
a22306d418 | |||
b542277eca | |||
edf1fbb6e6 | |||
653b6b55a9 | |||
7f09a2a26e | |||
7aeb3129ac | |||
dc71eb5246 | |||
bf9b8722c9 | |||
4d897b824b | |||
caf4937222 | |||
2f87dfdcb0 | |||
ffcada88f3 | |||
946d7e2bb1 | |||
7a2ed232cc | |||
1be4bd67e4 | |||
fcff6961a8 | |||
db4027cdb2 | |||
e22bb213af | |||
179210aa27 | |||
be631ad6f7 | |||
3f1790bcb8 | |||
a0ba8f0098 | |||
feb538900b | |||
5ce860c2f5 | |||
6c5ca9b256 | |||
17e4f45e97 | |||
6828ce66b6 | |||
b7b7a93e4e | |||
a34573643f | |||
dab73d8950 | |||
5e6a0e7ba0 | |||
c5eccc8e1c | |||
b55929b382 | |||
d7378fe6f4 | |||
66924729ff | |||
f12a6eed29 | |||
a327a74ece | |||
f3ab45e7d5 | |||
cdf6d200ef | |||
894beed59b | |||
022f33b256 | |||
90f1efc667 | |||
f7e959d602 | |||
9c25ec3afd | |||
e47c7ea55f |
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -6,6 +6,7 @@
|
||||
*.properties text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.cmd text eol=crlf
|
||||
*.ps1 text eol=crlf
|
||||
|
||||
# Custom for Visual Studio
|
||||
*.cs diff=csharp
|
||||
|
40
.github/ISSUE_TEMPLATE.md
vendored
40
.github/ISSUE_TEMPLATE.md
vendored
@ -1,14 +1,19 @@
|
||||
### Issue description
|
||||
<!--- use our forum https://forums.pmmp.io for questions -->
|
||||
<!--- Any issues requesting updates to new versions of MCPE will be treated as spam. We do not need issues to tell us that there is a new version available. -->
|
||||
<!---
|
||||
Write a short description about the issue
|
||||
<!---
|
||||
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
|
||||
|
||||
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?
|
||||
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. ...
|
||||
@ -16,15 +21,28 @@ Actual result: What actually happened?
|
||||
|
||||
### OS and versions
|
||||
<!--- use the 'version' command in PocketMine-MP
|
||||
NOTE: LATEST is not a valid version.
|
||||
PocketMine version should include Jenkins build number and/or git commit hash.
|
||||
ALSO NOTE: NO support whatsoever will be provided for forks or spoons of PocketMine. Issues relating to non-official distributions will be closed as spam. Please send such issues to whoever is responsible for the fork or spoon you are using.
|
||||
|
||||
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
|
||||
<!--- please use gist or anything else and add links here -->
|
||||
- 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
|
||||
|
||||
* ...
|
||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -28,3 +28,9 @@ Desktop.ini
|
||||
# Sphinx-doc
|
||||
/docs/build/
|
||||
!/docs/requirements.txt
|
||||
|
||||
# Composer
|
||||
vendor/*
|
||||
|
||||
# Travis files
|
||||
test_data/*
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -14,3 +14,6 @@
|
||||
[submodule "tests/plugins/PocketMine-DevTools"]
|
||||
path = tests/plugins/PocketMine-DevTools
|
||||
url = https://github.com/pmmp/PocketMine-DevTools.git
|
||||
[submodule "tests/plugins/PocketMine-TesterPlugin"]
|
||||
path = tests/plugins/PocketMine-TesterPlugin
|
||||
url = https://github.com/pmmp/PocketMine-TesterPlugin.git
|
||||
|
17
.travis.yml
17
.travis.yml
@ -1,12 +1,21 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 7.0
|
||||
- 7.2
|
||||
|
||||
before_script:
|
||||
- pecl install channel://pecl.php.net/pthreads-3.1.6
|
||||
- pecl install channel://pecl.php.net/weakref-0.3.3
|
||||
- echo | pecl install channel://pecl.php.net/yaml-2.0.0
|
||||
# - pecl install channel://pecl.php.net/pthreads-3.1.6
|
||||
- echo | pecl install channel://pecl.php.net/yaml-2.0.2
|
||||
- git clone https://github.com/krakjoe/pthreads.git
|
||||
- cd pthreads
|
||||
- git checkout 6c6b15138c923b69cfa46ee05fc2dd45da587287
|
||||
- phpize
|
||||
- ./configure
|
||||
- make
|
||||
- make install
|
||||
- cd ..
|
||||
- echo "extension=pthreads.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
|
||||
- composer install
|
||||
|
||||
script:
|
||||
- ./tests/travis.sh
|
||||
|
@ -18,8 +18,10 @@
|
||||
|
||||
- Information must be provided in the issue body, not in the title. No tags like `[BUG]` are allowed in the title, including `[SOLVED]` for solved issues.
|
||||
|
||||
- Similarly, no generic issue reports. For bugs, it is the issue author's responsibility to provide us an issue that is **trackable, debuggable, reproducible, reported professionally and is an actual bug**. If you do not provide us with a summary or instructions on how to reproduce the issue, it will be treated as spam and will therefore be closed.
|
||||
<br>In simple words, if your issue does not appear to be a bug or a feature request, or if the issue cannot be properly confirmed to be valid, the issue will be closed until further information is provided.
|
||||
- Similarly, no generic issue reports. For bugs, it is the issue author's responsibility to provide us an issue that is **trackable, debuggable, reproducible, reported professionally and is an actual bug**.
|
||||
<br><br>Valid issue reports must include instructions how to reproduce the issue or a crashdump/backtrace (unless the cause of the issue is obvious).
|
||||
<br><br>**If you do not provide us with a summary or instructions on how to reproduce the issue, it will be treated as spam and will therefore be closed.**
|
||||
<br><br>In simple words, if the issue cannot be properly confirmed to be valid or lacks required information, the issue will be closed until further information is provided.
|
||||
|
||||
- To express appreciation, objection, confusion or other supported reactions on pull requests, issues or comments on them, use GitHub [reactions](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments) rather than posting an individual comment with an emoji only. This helps keeping the issue/pull request conversation clean and readable.
|
||||
|
||||
|
@ -13,7 +13,7 @@ If you don't find what you're looking for there, [talk to a human](#discussion).
|
||||
- [#pmmp + #pocketmine channel IRC](http://webchat.freenode.net/?channels=pmmp,pocketmine)
|
||||
|
||||
### Plugins
|
||||
There are a very wide range of already-written plugins available which you can use to customise your server. Check out [the old plugin repository](http://plugins.pocketmine.net/) and [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
|
||||
* [Latest API documentation](https://jenkins.pmmp.io/job/PocketMine-MP-doc/doxygen/) - Doxygen documentation generated from development
|
||||
|
33
composer.json
Normal file
33
composer.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "pmmp/pocketmine-mp",
|
||||
"description": "A server software for Minecraft: Pocket Edition written in PHP",
|
||||
"type": "project",
|
||||
"homepage": "https://pmmp.io",
|
||||
"license": "LGPL-3.0",
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"ext-bcmath": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-hash": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-pcre": "*",
|
||||
"ext-phar": "*",
|
||||
"ext-pthreads": ">=3.1.7dev",
|
||||
"ext-reflection": "*",
|
||||
"ext-sockets": "*",
|
||||
"ext-spl": "*",
|
||||
"ext-yaml": ">=2.0.0",
|
||||
"ext-zip": "*",
|
||||
"ext-zlib": ">=1.2.11"
|
||||
},
|
||||
"autoload": {
|
||||
"exclude-from-classmap": [
|
||||
"src/spl/stubs"
|
||||
],
|
||||
"psr-0": {
|
||||
"": ["src", "src/spl"]
|
||||
}
|
||||
}
|
||||
}
|
36
composer.lock
generated
Normal file
36
composer.lock
generated
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "d4fecad9dce5314493052c870c8cf059",
|
||||
"packages": [],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"ext-pthreads": 20
|
||||
},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": ">=7.2",
|
||||
"ext-bcmath": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-hash": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-pcre": "*",
|
||||
"ext-phar": "*",
|
||||
"ext-pthreads": ">=3.1.7dev",
|
||||
"ext-reflection": "*",
|
||||
"ext-sockets": "*",
|
||||
"ext-spl": "*",
|
||||
"ext-yaml": ">=2.0.0",
|
||||
"ext-zip": "*",
|
||||
"ext-zlib": ">=1.2.11"
|
||||
},
|
||||
"platform-dev": []
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\event\TranslationContainer;
|
||||
@ -39,76 +41,82 @@ abstract class Achievement{
|
||||
"mineWood" => [
|
||||
"name" => "Getting Wood",
|
||||
"requires" => [ //"openInventory",
|
||||
],
|
||||
]
|
||||
],
|
||||
"buildWorkBench" => [
|
||||
"name" => "Benchmarking",
|
||||
"requires" => [
|
||||
"mineWood",
|
||||
],
|
||||
"mineWood"
|
||||
]
|
||||
],
|
||||
"buildPickaxe" => [
|
||||
"name" => "Time to Mine!",
|
||||
"requires" => [
|
||||
"buildWorkBench",
|
||||
],
|
||||
"buildWorkBench"
|
||||
]
|
||||
],
|
||||
"buildFurnace" => [
|
||||
"name" => "Hot Topic",
|
||||
"requires" => [
|
||||
"buildPickaxe",
|
||||
],
|
||||
"buildPickaxe"
|
||||
]
|
||||
],
|
||||
"acquireIron" => [
|
||||
"name" => "Acquire hardware",
|
||||
"requires" => [
|
||||
"buildFurnace",
|
||||
],
|
||||
"buildFurnace"
|
||||
]
|
||||
],
|
||||
"buildHoe" => [
|
||||
"name" => "Time to Farm!",
|
||||
"requires" => [
|
||||
"buildWorkBench",
|
||||
],
|
||||
"buildWorkBench"
|
||||
]
|
||||
],
|
||||
"makeBread" => [
|
||||
"name" => "Bake Bread",
|
||||
"requires" => [
|
||||
"buildHoe",
|
||||
],
|
||||
"buildHoe"
|
||||
]
|
||||
],
|
||||
"bakeCake" => [
|
||||
"name" => "The Lie",
|
||||
"requires" => [
|
||||
"buildHoe",
|
||||
],
|
||||
"buildHoe"
|
||||
]
|
||||
],
|
||||
"buildBetterPickaxe" => [
|
||||
"name" => "Getting an Upgrade",
|
||||
"requires" => [
|
||||
"buildPickaxe",
|
||||
],
|
||||
"buildPickaxe"
|
||||
]
|
||||
],
|
||||
"buildSword" => [
|
||||
"name" => "Time to Strike!",
|
||||
"requires" => [
|
||||
"buildWorkBench",
|
||||
],
|
||||
"buildWorkBench"
|
||||
]
|
||||
],
|
||||
"diamonds" => [
|
||||
"name" => "DIAMONDS!",
|
||||
"requires" => [
|
||||
"acquireIron",
|
||||
],
|
||||
],
|
||||
"acquireIron"
|
||||
]
|
||||
]
|
||||
|
||||
];
|
||||
|
||||
|
||||
public static function broadcast(Player $player, $achievementId){
|
||||
/**
|
||||
* @param Player $player
|
||||
* @param string $achievementId
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function broadcast(Player $player, string $achievementId) : bool{
|
||||
if(isset(Achievement::$list[$achievementId])){
|
||||
$translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"]]);
|
||||
if(Server::getInstance()->getConfigString("announce-player-achievements", true) === true){
|
||||
$translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"] . TextFormat::RESET]);
|
||||
if(Server::getInstance()->getConfigBoolean("announce-player-achievements", true) === true){
|
||||
Server::getInstance()->broadcastMessage($translation);
|
||||
}else{
|
||||
$player->sendMessage($translation);
|
||||
@ -120,11 +128,18 @@ abstract class Achievement{
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function add($achievementId, $achievementName, array $requires = []){
|
||||
/**
|
||||
* @param string $achievementId
|
||||
* @param string $achievementName
|
||||
* @param array $requires
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function add(string $achievementId, string $achievementName, array $requires = []) : bool{
|
||||
if(!isset(Achievement::$list[$achievementId])){
|
||||
Achievement::$list[$achievementId] = [
|
||||
"name" => $achievementName,
|
||||
"requires" => $requires,
|
||||
"requires" => $requires
|
||||
];
|
||||
|
||||
return true;
|
||||
|
@ -19,9 +19,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
abstract class Collectable extends \Threaded implements \Collectable{
|
||||
abstract class Collectable extends \Threaded{
|
||||
|
||||
private $isGarbage = false;
|
||||
|
||||
|
@ -19,11 +19,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
||||
use pocketmine\plugin\PluginBase;
|
||||
use pocketmine\plugin\PluginLoadOrder;
|
||||
use pocketmine\plugin\PluginManager;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\VersionString;
|
||||
use raklib\RakLib;
|
||||
@ -35,7 +38,9 @@ class CrashDump{
|
||||
private $fp;
|
||||
private $time;
|
||||
private $data = [];
|
||||
private $encodedData = null;
|
||||
/** @var string */
|
||||
private $encodedData = "";
|
||||
/** @var string */
|
||||
private $path;
|
||||
|
||||
public function __construct(Server $server){
|
||||
@ -61,7 +66,7 @@ class CrashDump{
|
||||
$this->encodeData();
|
||||
}
|
||||
|
||||
public function getPath(){
|
||||
public function getPath() : string{
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
@ -69,7 +74,7 @@ class CrashDump{
|
||||
return $this->encodedData;
|
||||
}
|
||||
|
||||
public function getData(){
|
||||
public function getData() : array{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
@ -86,7 +91,7 @@ class CrashDump{
|
||||
}
|
||||
|
||||
private function pluginsData(){
|
||||
if(class_exists("pocketmine\\plugin\\PluginManager", false)){
|
||||
if($this->server->getPluginManager() instanceof PluginManager){
|
||||
$this->addLine();
|
||||
$this->addLine("Loaded plugins:");
|
||||
$this->data["plugins"] = [];
|
||||
@ -159,7 +164,7 @@ class CrashDump{
|
||||
E_STRICT => "E_STRICT",
|
||||
E_RECOVERABLE_ERROR => "E_RECOVERABLE_ERROR",
|
||||
E_DEPRECATED => "E_DEPRECATED",
|
||||
E_USER_DEPRECATED => "E_USER_DEPRECATED",
|
||||
E_USER_DEPRECATED => "E_USER_DEPRECATED"
|
||||
];
|
||||
$error["fullFile"] = $error["file"];
|
||||
$error["file"] = cleanPath($error["file"]);
|
||||
@ -224,6 +229,7 @@ class CrashDump{
|
||||
private function generalData(){
|
||||
$version = new VersionString();
|
||||
$this->data["general"] = [];
|
||||
$this->data["general"]["name"] = $this->server->getName();
|
||||
$this->data["general"]["version"] = $version->get(false);
|
||||
$this->data["general"]["build"] = $version->getBuild();
|
||||
$this->data["general"]["protocol"] = ProtocolInfo::CURRENT_PROTOCOL;
|
||||
@ -235,7 +241,7 @@ class CrashDump{
|
||||
$this->data["general"]["zend"] = zend_version();
|
||||
$this->data["general"]["php_os"] = PHP_OS;
|
||||
$this->data["general"]["os"] = Utils::getOS();
|
||||
$this->addLine("PocketMine-MP version: " . $version->get(false) . " #" . $version->getBuild() . " [Protocol " . ProtocolInfo::CURRENT_PROTOCOL . "; API " . API_VERSION . "]");
|
||||
$this->addLine($this->server->getName() . " version: " . $version->get(false) . " #" . $version->getBuild() . " [Protocol " . ProtocolInfo::CURRENT_PROTOCOL . "; API " . API_VERSION . "]");
|
||||
$this->addLine("Git commit: " . GIT_COMMIT);
|
||||
$this->addLine("uname -a: " . php_uname("a"));
|
||||
$this->addLine("PHP Version: " . phpversion());
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\permission\ServerOperator;
|
||||
@ -28,32 +30,32 @@ interface IPlayer extends ServerOperator{
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isOnline();
|
||||
public function isOnline() : bool;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName();
|
||||
public function getName() : string;
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isBanned();
|
||||
public function isBanned() : bool;
|
||||
|
||||
/**
|
||||
* @param bool $banned
|
||||
*/
|
||||
public function setBanned($banned);
|
||||
public function setBanned(bool $banned);
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isWhitelisted();
|
||||
public function isWhitelisted() : bool;
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
*/
|
||||
public function setWhitelisted($value);
|
||||
public function setWhitelisted(bool $value);
|
||||
|
||||
/**
|
||||
* @return Player|null
|
||||
@ -61,18 +63,18 @@ interface IPlayer extends ServerOperator{
|
||||
public function getPlayer();
|
||||
|
||||
/**
|
||||
* @return int|double
|
||||
* @return int|null
|
||||
*/
|
||||
public function getFirstPlayed();
|
||||
|
||||
/**
|
||||
* @return int|double
|
||||
* @return int|null
|
||||
*/
|
||||
public function getLastPlayed();
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return bool
|
||||
*/
|
||||
public function hasPlayedBefore();
|
||||
public function hasPlayedBefore() : bool;
|
||||
|
||||
}
|
||||
|
@ -19,11 +19,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\event\server\LowMemoryEvent;
|
||||
use pocketmine\event\Timings;
|
||||
use pocketmine\scheduler\DumpWorkerMemoryTask;
|
||||
use pocketmine\scheduler\GarbageCollectionTask;
|
||||
use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\Utils;
|
||||
|
||||
class MemoryManager{
|
||||
@ -31,28 +35,49 @@ class MemoryManager{
|
||||
/** @var Server */
|
||||
private $server;
|
||||
|
||||
/** @var int */
|
||||
private $memoryLimit;
|
||||
/** @var int */
|
||||
private $globalMemoryLimit;
|
||||
/** @var int */
|
||||
private $checkRate;
|
||||
/** @var int */
|
||||
private $checkTicker = 0;
|
||||
/** @var bool */
|
||||
private $lowMemory = false;
|
||||
|
||||
/** @var bool */
|
||||
private $continuousTrigger = true;
|
||||
/** @var int */
|
||||
private $continuousTriggerRate;
|
||||
/** @var int */
|
||||
private $continuousTriggerCount = 0;
|
||||
/** @var int */
|
||||
private $continuousTriggerTicker = 0;
|
||||
|
||||
/** @var int */
|
||||
private $garbageCollectionPeriod;
|
||||
/** @var int */
|
||||
private $garbageCollectionTicker = 0;
|
||||
/** @var bool */
|
||||
private $garbageCollectionTrigger;
|
||||
/** @var bool */
|
||||
private $garbageCollectionAsync;
|
||||
|
||||
private $chunkRadiusOverride;
|
||||
private $chunkCollect;
|
||||
private $chunkTrigger;
|
||||
/** @var int */
|
||||
private $lowMemChunkRadiusOverride;
|
||||
/** @var bool */
|
||||
private $lowMemChunkGC;
|
||||
/** @var bool */
|
||||
private $lowMemReduceChunkRadius;
|
||||
|
||||
private $chunkCache;
|
||||
private $cacheTrigger;
|
||||
/** @var bool */
|
||||
private $lowMemDisableChunkCache;
|
||||
/** @var bool */
|
||||
private $lowMemClearWorldCache;
|
||||
|
||||
/** @var bool */
|
||||
private $dumpWorkers = true;
|
||||
|
||||
public function __construct(Server $server){
|
||||
$this->server = $server;
|
||||
@ -90,7 +115,7 @@ class MemoryManager{
|
||||
$hardLimit = ((int) $this->server->getProperty("memory.main-hard-limit", $defaultMemory));
|
||||
|
||||
if($hardLimit <= 0){
|
||||
ini_set("memory_limit", -1);
|
||||
ini_set("memory_limit", '-1');
|
||||
}else{
|
||||
ini_set("memory_limit", $hardLimit . "M");
|
||||
}
|
||||
@ -104,22 +129,28 @@ class MemoryManager{
|
||||
$this->garbageCollectionTrigger = (bool) $this->server->getProperty("memory.garbage-collection.low-memory-trigger", true);
|
||||
$this->garbageCollectionAsync = (bool) $this->server->getProperty("memory.garbage-collection.collect-async-worker", true);
|
||||
|
||||
$this->chunkRadiusOverride = (int) $this->server->getProperty("memory.max-chunks.chunk-radius", 4);
|
||||
$this->chunkCollect = (bool) $this->server->getProperty("memory.max-chunks.trigger-chunk-collect", true);
|
||||
$this->chunkTrigger = (bool) $this->server->getProperty("memory.max-chunks.low-memory-trigger", true);
|
||||
$this->lowMemChunkRadiusOverride = (int) $this->server->getProperty("memory.max-chunks.chunk-radius", 4);
|
||||
$this->lowMemChunkGC = (bool) $this->server->getProperty("memory.max-chunks.trigger-chunk-collect", true);
|
||||
|
||||
$this->chunkCache = (bool) $this->server->getProperty("memory.world-caches.disable-chunk-cache", true);
|
||||
$this->cacheTrigger = (bool) $this->server->getProperty("memory.world-caches.low-memory-trigger", true);
|
||||
$this->lowMemDisableChunkCache = (bool) $this->server->getProperty("memory.world-caches.disable-chunk-cache", true);
|
||||
$this->lowMemClearWorldCache = (bool) $this->server->getProperty("memory.world-caches.low-memory-trigger", true);
|
||||
|
||||
$this->dumpWorkers = (bool) $this->server->getProperty("memory.memory-dump.dump-async-worker", true);
|
||||
gc_enable();
|
||||
}
|
||||
|
||||
public function isLowMemory(){
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isLowMemory() : bool{
|
||||
return $this->lowMemory;
|
||||
}
|
||||
|
||||
public function canUseChunkCache(){
|
||||
return !($this->lowMemory and $this->chunkTrigger);
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function canUseChunkCache() : bool{
|
||||
return !$this->lowMemory or !$this->lowMemDisableChunkCache;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,19 +161,27 @@ class MemoryManager{
|
||||
* @return int
|
||||
*/
|
||||
public function getViewDistance(int $distance) : int{
|
||||
return $this->lowMemory ? min($this->chunkRadiusOverride, $distance) : $distance;
|
||||
return ($this->lowMemory and $this->lowMemChunkRadiusOverride > 0) ? (int) min($this->lowMemChunkRadiusOverride, $distance) : $distance;
|
||||
}
|
||||
|
||||
public function trigger($memory, $limit, $global = false, $triggerCount = 0){
|
||||
/**
|
||||
* Triggers garbage collection and cache cleanup to try and free memory.
|
||||
*
|
||||
* @param int $memory
|
||||
* @param int $limit
|
||||
* @param bool $global
|
||||
* @param int $triggerCount
|
||||
*/
|
||||
public function trigger(int $memory, int $limit, bool $global = false, int $triggerCount = 0){
|
||||
$this->server->getLogger()->debug(sprintf("[Memory Manager] %sLow memory triggered, limit %gMB, using %gMB",
|
||||
$global ? "Global " : "", round(($limit / 1024) / 1024, 2), round(($memory / 1024) / 1024, 2)));
|
||||
if($this->cacheTrigger){
|
||||
if($this->lowMemClearWorldCache){
|
||||
foreach($this->server->getLevels() as $level){
|
||||
$level->clearCache(true);
|
||||
}
|
||||
}
|
||||
|
||||
if($this->chunkTrigger and $this->chunkCollect){
|
||||
if($this->lowMemChunkGC){
|
||||
foreach($this->server->getLevels() as $level){
|
||||
$level->doChunkGarbageCollection();
|
||||
}
|
||||
@ -159,6 +198,9 @@ class MemoryManager{
|
||||
$this->server->getLogger()->debug(sprintf("[Memory Manager] Freed %gMB, $cycles cycles", round(($ev->getMemoryFreed() / 1024) / 1024, 2)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every tick to update the memory manager state.
|
||||
*/
|
||||
public function check(){
|
||||
Timings::$memoryManagerTimer->startTiming();
|
||||
|
||||
@ -196,7 +238,10 @@ class MemoryManager{
|
||||
Timings::$memoryManagerTimer->stopTiming();
|
||||
}
|
||||
|
||||
public function triggerGarbageCollector(){
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function triggerGarbageCollector() : int{
|
||||
Timings::$garbageCollectorTimer->startTiming();
|
||||
|
||||
if($this->garbageCollectionAsync){
|
||||
@ -213,26 +258,110 @@ class MemoryManager{
|
||||
return $cycles;
|
||||
}
|
||||
|
||||
public function dumpServerMemory($outputFolder, $maxNesting, $maxStringSize){
|
||||
/**
|
||||
* Dumps the server memory into the specified output folder.
|
||||
*
|
||||
* @param string $outputFolder
|
||||
* @param int $maxNesting
|
||||
* @param int $maxStringSize
|
||||
*/
|
||||
public function dumpServerMemory(string $outputFolder, int $maxNesting, int $maxStringSize){
|
||||
MainLogger::getLogger()->notice("[Dump] After the memory dump is done, the server might crash");
|
||||
self::dumpMemory($this->server, $this->server->getLoader(), $outputFolder, $maxNesting, $maxStringSize);
|
||||
|
||||
if($this->dumpWorkers){
|
||||
$scheduler = $this->server->getScheduler();
|
||||
for($i = 0, $size = $scheduler->getAsyncTaskPoolSize(); $i < $size; ++$i){
|
||||
$scheduler->scheduleAsyncTaskToWorker(new DumpWorkerMemoryTask($outputFolder, $maxNesting, $maxStringSize), $i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Static memory dumper accessible from any thread.
|
||||
*
|
||||
* @param mixed $startingObject
|
||||
* @param \ClassLoader $loader
|
||||
* @param string $outputFolder
|
||||
* @param int $maxNesting
|
||||
* @param int $maxStringSize
|
||||
*/
|
||||
public static function dumpMemory($startingObject, \ClassLoader $loader, string $outputFolder, int $maxNesting, int $maxStringSize){
|
||||
$hardLimit = ini_get('memory_limit');
|
||||
ini_set('memory_limit', '-1');
|
||||
gc_disable();
|
||||
|
||||
if(!file_exists($outputFolder)){
|
||||
mkdir($outputFolder, 0777, true);
|
||||
}
|
||||
|
||||
$this->server->getLogger()->notice("[Dump] After the memory dump is done, the server might crash");
|
||||
|
||||
$obData = fopen($outputFolder . "/objects.js", "wb+");
|
||||
|
||||
$staticProperties = [];
|
||||
|
||||
$data = [];
|
||||
|
||||
$objects = [];
|
||||
|
||||
$refCounts = [];
|
||||
|
||||
$this->continueDump($this->server, $data, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
$instanceCounts = [];
|
||||
|
||||
$staticProperties = [];
|
||||
$staticCount = 0;
|
||||
|
||||
foreach($loader->getClasses() as $className){
|
||||
$reflection = new \ReflectionClass($className);
|
||||
$staticProperties[$className] = [];
|
||||
foreach($reflection->getProperties() as $property){
|
||||
if(!$property->isStatic() or $property->getDeclaringClass()->getName() !== $className){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!$property->isPublic()){
|
||||
$property->setAccessible(true);
|
||||
}
|
||||
|
||||
$staticCount++;
|
||||
self::continueDump($property->getValue(), $staticProperties[$className][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
|
||||
if(count($staticProperties[$className]) === 0){
|
||||
unset($staticProperties[$className]);
|
||||
}
|
||||
}
|
||||
|
||||
file_put_contents($outputFolder . "/staticProperties.js", json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
MainLogger::getLogger()->info("[Dump] Wrote $staticCount static properties");
|
||||
|
||||
if($GLOBALS !== null){ //This might be null if we're on a different thread
|
||||
$globalVariables = [];
|
||||
$globalCount = 0;
|
||||
|
||||
$ignoredGlobals = [
|
||||
'GLOBALS' => true,
|
||||
'_SERVER' => true,
|
||||
'_REQUEST' => true,
|
||||
'_POST' => true,
|
||||
'_GET' => true,
|
||||
'_FILES' => true,
|
||||
'_ENV' => true,
|
||||
'_COOKIE' => true,
|
||||
'_SESSION' => true
|
||||
];
|
||||
|
||||
foreach($GLOBALS as $varName => $value){
|
||||
if(isset($ignoredGlobals[$varName])){
|
||||
continue;
|
||||
}
|
||||
|
||||
$globalCount++;
|
||||
self::continueDump($value, $globalVariables[$varName], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
|
||||
file_put_contents($outputFolder . "/globalVariables.js", json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
MainLogger::getLogger()->info("[Dump] Wrote $globalCount global variables");
|
||||
}
|
||||
|
||||
self::continueDump($startingObject, $data, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
|
||||
do{
|
||||
$continue = false;
|
||||
@ -243,6 +372,11 @@ class MemoryManager{
|
||||
$continue = true;
|
||||
|
||||
$className = get_class($object);
|
||||
if(!isset($instanceCounts[$className])){
|
||||
$instanceCounts[$className] = 1;
|
||||
}else{
|
||||
$instanceCounts[$className]++;
|
||||
}
|
||||
|
||||
$objects[$hash] = true;
|
||||
|
||||
@ -269,41 +403,41 @@ class MemoryManager{
|
||||
if(!$property->isPublic()){
|
||||
$property->setAccessible(true);
|
||||
}
|
||||
$this->continueDump($property->getValue($object), $info["properties"][$property->getName()], $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");
|
||||
|
||||
if(!isset($objects["staticProperties"][$className])){
|
||||
$staticProperties[$className] = [];
|
||||
foreach($reflection->getProperties() as $property){
|
||||
if(!$property->isStatic() or $property->getDeclaringClass()->getName() !== $className){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!$property->isPublic()){
|
||||
$property->setAccessible(true);
|
||||
}
|
||||
$this->continueDump($property->getValue($object), $staticProperties[$className][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "[Dump] Wrote " . count($objects) . " objects\n";
|
||||
|
||||
}while($continue);
|
||||
|
||||
|
||||
MainLogger::getLogger()->info("[Dump] Wrote " . count($objects) . " objects");
|
||||
|
||||
fclose($obData);
|
||||
|
||||
file_put_contents($outputFolder . "/staticProperties.js", json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
file_put_contents($outputFolder . "/serverEntry.js", json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
file_put_contents($outputFolder . "/referenceCounts.js", json_encode($refCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
|
||||
echo "[Dump] Finished!\n";
|
||||
arsort($instanceCounts, SORT_NUMERIC);
|
||||
file_put_contents($outputFolder . "/instanceCounts.js", json_encode($instanceCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
|
||||
MainLogger::getLogger()->info("[Dump] Finished!");
|
||||
|
||||
ini_set('memory_limit', $hardLimit);
|
||||
gc_enable();
|
||||
}
|
||||
|
||||
private function continueDump($from, &$data, &$objects, &$refCounts, $recursion, $maxNesting, $maxStringSize){
|
||||
/**
|
||||
* @param mixed $from
|
||||
* @param mixed &$data
|
||||
* @param object[] &$objects
|
||||
* @param int[] &$refCounts
|
||||
* @param int $recursion
|
||||
* @param int $maxNesting
|
||||
* @param int $maxStringSize
|
||||
*/
|
||||
private static function continueDump($from, &$data, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize){
|
||||
if($maxNesting <= 0){
|
||||
$data = "(error) NESTING LIMIT REACHED";
|
||||
return;
|
||||
@ -327,7 +461,7 @@ class MemoryManager{
|
||||
}
|
||||
$data = [];
|
||||
foreach($from as $key => $value){
|
||||
$this->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)){
|
||||
$data = "(string) len(". strlen($from) .") " . substr(Utils::printable($from), 0, $maxStringSize);
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\metadata\Metadatable;
|
||||
@ -28,15 +30,18 @@ use pocketmine\plugin\Plugin;
|
||||
|
||||
class OfflinePlayer implements IPlayer, Metadatable{
|
||||
|
||||
/** @var string */
|
||||
private $name;
|
||||
/** @var Server */
|
||||
private $server;
|
||||
/** @var CompoundTag|null */
|
||||
private $namedtag;
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct(Server $server, $name){
|
||||
public function __construct(Server $server, string $name){
|
||||
$this->server = $server;
|
||||
$this->name = $name;
|
||||
if(file_exists($this->server->getDataPath() . "players/" . strtolower($this->getName()) . ".dat")){
|
||||
@ -46,11 +51,11 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
||||
}
|
||||
}
|
||||
|
||||
public function isOnline(){
|
||||
public function isOnline() : bool{
|
||||
return $this->getPlayer() !== null;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
@ -58,11 +63,11 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
||||
return $this->server;
|
||||
}
|
||||
|
||||
public function isOp(){
|
||||
public function isOp() : bool{
|
||||
return $this->server->isOp(strtolower($this->getName()));
|
||||
}
|
||||
|
||||
public function setOp($value){
|
||||
public function setOp(bool $value){
|
||||
if($value === $this->isOp()){
|
||||
return;
|
||||
}
|
||||
@ -74,11 +79,11 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
||||
}
|
||||
}
|
||||
|
||||
public function isBanned(){
|
||||
public function isBanned() : bool{
|
||||
return $this->server->getNameBans()->isBanned(strtolower($this->getName()));
|
||||
}
|
||||
|
||||
public function setBanned($value){
|
||||
public function setBanned(bool $value){
|
||||
if($value === true){
|
||||
$this->server->getNameBans()->addBan($this->getName(), null, null, null);
|
||||
}else{
|
||||
@ -86,11 +91,11 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
||||
}
|
||||
}
|
||||
|
||||
public function isWhitelisted(){
|
||||
public function isWhitelisted() : bool{
|
||||
return $this->server->isWhitelisted(strtolower($this->getName()));
|
||||
}
|
||||
|
||||
public function setWhitelisted($value){
|
||||
public function setWhitelisted(bool $value){
|
||||
if($value === true){
|
||||
$this->server->addWhitelist(strtolower($this->getName()));
|
||||
}else{
|
||||
@ -110,24 +115,24 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
||||
return $this->namedtag instanceof CompoundTag ? $this->namedtag["lastPlayed"] : null;
|
||||
}
|
||||
|
||||
public function hasPlayedBefore(){
|
||||
public function hasPlayedBefore() : bool{
|
||||
return $this->namedtag instanceof CompoundTag;
|
||||
}
|
||||
|
||||
public function setMetadata($metadataKey, MetadataValue $metadataValue){
|
||||
$this->server->getPlayerMetadata()->setMetadata($this, $metadataKey, $metadataValue);
|
||||
public function setMetadata(string $metadataKey, MetadataValue $newMetadataValue){
|
||||
$this->server->getPlayerMetadata()->setMetadata($this, $metadataKey, $newMetadataValue);
|
||||
}
|
||||
|
||||
public function getMetadata($metadataKey){
|
||||
public function getMetadata(string $metadataKey){
|
||||
return $this->server->getPlayerMetadata()->getMetadata($this, $metadataKey);
|
||||
}
|
||||
|
||||
public function hasMetadata($metadataKey){
|
||||
public function hasMetadata(string $metadataKey) : bool{
|
||||
return $this->server->getPlayerMetadata()->hasMetadata($this, $metadataKey);
|
||||
}
|
||||
|
||||
public function removeMetadata($metadataKey, Plugin $plugin){
|
||||
$this->server->getPlayerMetadata()->removeMetadata($this, $metadataKey, $plugin);
|
||||
public function removeMetadata(string $metadataKey, Plugin $owningPlugin){
|
||||
$this->server->getPlayerMetadata()->removeMetadata($this, $metadataKey, $owningPlugin);
|
||||
}
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,7 +19,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace {
|
||||
const INT32_MIN = -0x80000000;
|
||||
const INT32_MAX = 0x7fffffff;
|
||||
|
||||
function safe_var_dump(){
|
||||
static $cnt = 0;
|
||||
foreach(func_get_args() as $var){
|
||||
@ -65,6 +70,7 @@ namespace {
|
||||
}
|
||||
|
||||
namespace pocketmine {
|
||||
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\ServerKiller;
|
||||
@ -73,9 +79,12 @@ namespace pocketmine {
|
||||
use pocketmine\wizard\SetupWizard;
|
||||
use raklib\RakLib;
|
||||
|
||||
const VERSION = "1.6.2dev";
|
||||
const API_VERSION = "3.0.0-ALPHA5";
|
||||
const CODENAME = "Unleashed";
|
||||
const NAME = "PocketMine-MP";
|
||||
const VERSION = "1.7dev";
|
||||
const API_VERSION = "3.0.0-ALPHA9";
|
||||
const CODENAME = "[REDACTED]";
|
||||
|
||||
const MIN_PHP_VERSION = "7.2.0RC3";
|
||||
|
||||
/*
|
||||
* Startup code. Do not look at it, it may harm you.
|
||||
@ -84,15 +93,9 @@ namespace pocketmine {
|
||||
* Enjoy it as much as I did writing it. I don't want to do it again.
|
||||
*/
|
||||
|
||||
if(\Phar::running(true) !== ""){
|
||||
@define('pocketmine\PATH', \Phar::running(true) . "/");
|
||||
}else{
|
||||
@define('pocketmine\PATH', \getcwd() . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
if(version_compare("7.0", PHP_VERSION) > 0){
|
||||
echo "[CRITICAL] You must use PHP >= 7.0" . PHP_EOL;
|
||||
echo "[CRITICAL] Please use the installer provided on the homepage." . PHP_EOL;
|
||||
if(version_compare(MIN_PHP_VERSION, PHP_VERSION) > 0){
|
||||
echo "[CRITICAL] " . \pocketmine\NAME . " requires PHP >= " . MIN_PHP_VERSION . ", but you have PHP " . PHP_VERSION . "." . PHP_EOL;
|
||||
echo "[CRITICAL] Please use the installer provided on the homepage, or update to a newer PHP version." . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -102,39 +105,82 @@ namespace pocketmine {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(!class_exists("ClassLoader", false)){
|
||||
if(!is_file(\pocketmine\PATH . "src/spl/ClassLoader.php")){
|
||||
echo "[CRITICAL] Unable to find the PocketMine-SPL library." . PHP_EOL;
|
||||
echo "[CRITICAL] Please use provided builds or clone the repository recursively." . PHP_EOL;
|
||||
exit(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) !== ""){
|
||||
define('pocketmine\PATH', \Phar::running(true) . "/");
|
||||
}else{
|
||||
define('pocketmine\PATH', dirname(__FILE__, 3) . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
$requiredSplVer = "0.0.1";
|
||||
if(!is_file(\pocketmine\PATH . "src/spl/version.php")){
|
||||
echo "[CRITICAL] Cannot find PocketMine-SPL or incompatible version." . PHP_EOL;
|
||||
echo "[CRITICAL] Please update your submodules or use provided builds." . PHP_EOL;
|
||||
exit(1);
|
||||
}elseif(version_compare($requiredSplVer, require(\pocketmine\PATH . "src/spl/version.php")) > 0){
|
||||
echo "[CRITICAL] Incompatible PocketMine-SPL submodule version ($requiredSplVer is required)." . PHP_EOL;
|
||||
echo "[CRITICAL] Please update your submodules or use provided builds." . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(is_file(\pocketmine\PATH . "vendor/autoload.php")){
|
||||
require_once(\pocketmine\PATH . "vendor/autoload.php");
|
||||
}else{
|
||||
echo "[CRITICAL] Composer autoloader not found" . PHP_EOL;
|
||||
echo "[CRITICAL] Please initialize composer dependencies before running." . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(!class_exists("ClassLoader", false)){
|
||||
require_once(\pocketmine\PATH . "src/spl/ClassLoader.php");
|
||||
require_once(\pocketmine\PATH . "src/spl/BaseClassLoader.php");
|
||||
}
|
||||
|
||||
/*
|
||||
* We now use the Composer autoloader, but this autoloader is still used by RakLib and for loading plugins.
|
||||
*/
|
||||
$autoloader = new \BaseClassLoader();
|
||||
$autoloader->addPath(\pocketmine\PATH . "src");
|
||||
$autoloader->addPath(\pocketmine\PATH . "src" . DIRECTORY_SEPARATOR . "spl");
|
||||
$autoloader->register(true);
|
||||
$autoloader->register(false);
|
||||
|
||||
try{
|
||||
if(!class_exists(RakLib::class)){
|
||||
throw new \Exception;
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
if(!class_exists(RakLib::class)){
|
||||
echo "[CRITICAL] Unable to find the RakLib library." . PHP_EOL;
|
||||
echo "[CRITICAL] Please use provided builds or clone the repository recursively." . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(version_compare(RakLib::VERSION, "0.8.1") < 0){
|
||||
echo "[CRITICAL] RakLib version 0.8.1 is required, while you have version " . RakLib::VERSION . "." . PHP_EOL;
|
||||
echo "[CRITICAL] Please update your submodules or use provided builds." . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
set_time_limit(0); //Who set it to 30 seconds?!?!
|
||||
|
||||
error_reporting(-1);
|
||||
ini_set("allow_url_fopen", 1);
|
||||
ini_set("display_errors", 1);
|
||||
ini_set("display_startup_errors", 1);
|
||||
ini_set("allow_url_fopen", '1');
|
||||
ini_set("display_errors", '1');
|
||||
ini_set("display_startup_errors", '1');
|
||||
ini_set("default_charset", "utf-8");
|
||||
|
||||
ini_set("memory_limit", -1);
|
||||
ini_set("memory_limit", '-1');
|
||||
define('pocketmine\START_TIME', microtime(true));
|
||||
|
||||
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-profiler"]);
|
||||
@ -153,42 +199,54 @@ namespace pocketmine {
|
||||
//Logger has a dependency on timezone, so we'll set it to UTC until we can get the actual timezone.
|
||||
date_default_timezone_set("UTC");
|
||||
|
||||
$logger = new MainLogger(\pocketmine\DATA . "server.log", \pocketmine\ANSI);
|
||||
$logger = new MainLogger(\pocketmine\DATA . "server.log");
|
||||
$logger->registerStatic();
|
||||
|
||||
do{
|
||||
$timezone = ini_get("date.timezone");
|
||||
if($timezone !== ""){
|
||||
/*
|
||||
* This is here so that people don't come to us complaining and fill up the issue tracker when they put
|
||||
* an incorrect timezone abbreviation in php.ini apparently.
|
||||
*/
|
||||
if(strpos($timezone, "/") === false){
|
||||
$default_timezone = timezone_name_from_abbr($timezone);
|
||||
if($default_timezone !== false){
|
||||
ini_set("date.timezone", $default_timezone);
|
||||
date_default_timezone_set($default_timezone);
|
||||
break;
|
||||
}else{
|
||||
//Bad php.ini value, try another method to detect timezone
|
||||
$logger->warning("Timezone \"$timezone\" could not be parsed as a valid timezone from php.ini, falling back to auto-detection");
|
||||
}
|
||||
}else{
|
||||
date_default_timezone_set($timezone);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!ini_get("date.timezone")){
|
||||
if(($timezone = detect_system_timezone()) and date_default_timezone_set($timezone)){
|
||||
//Success! Timezone has already been set and validated in the if statement.
|
||||
//This here is just for redundancy just in case some program wants to read timezone data from the ini.
|
||||
ini_set("date.timezone", $timezone);
|
||||
}else{
|
||||
//If system timezone detection fails or timezone is an invalid value.
|
||||
if($response = Utils::getURL("http://ip-api.com/json")
|
||||
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']);
|
||||
}else{
|
||||
ini_set("date.timezone", "UTC");
|
||||
date_default_timezone_set("UTC");
|
||||
$logger->warning("Timezone could not be automatically determined. 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.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
$timezone = ini_get("date.timezone");
|
||||
if(strpos($timezone, "/") === false){
|
||||
$default_timezone = timezone_name_from_abbr($timezone);
|
||||
ini_set("date.timezone", $default_timezone);
|
||||
date_default_timezone_set($default_timezone);
|
||||
}else{
|
||||
date_default_timezone_set($timezone);
|
||||
|
||||
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()){
|
||||
@ -227,7 +285,6 @@ namespace pocketmine {
|
||||
}
|
||||
|
||||
return parse_offset($offset);
|
||||
break;
|
||||
case 'linux':
|
||||
// Ubuntu / Debian.
|
||||
if(file_exists('/etc/timezone')){
|
||||
@ -254,7 +311,6 @@ namespace pocketmine {
|
||||
}
|
||||
|
||||
return parse_offset($offset);
|
||||
break;
|
||||
case 'mac':
|
||||
if(is_link('/etc/localtime')){
|
||||
$filename = readlink('/etc/localtime');
|
||||
@ -265,17 +321,15 @@ namespace pocketmine {
|
||||
}
|
||||
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $offset In the format of +09:00, +02:00, -04:00 etc.
|
||||
*
|
||||
* @return string
|
||||
* @return string|bool
|
||||
*/
|
||||
function parse_offset($offset){
|
||||
//Make signed offsets unsigned for date_parse
|
||||
@ -376,150 +430,151 @@ namespace pocketmine {
|
||||
}else{
|
||||
$args = $trace[$i]["params"];
|
||||
}
|
||||
foreach($args as $name => $value){
|
||||
$params .= (is_object($value) ? get_class($value) . " " . (method_exists($value, "__toString") ? $value->__toString() : "object") : gettype($value) . " " . (is_array($value) ? "Array()" : Utils::printable(@strval($value)))) . ", ";
|
||||
}
|
||||
|
||||
$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(substr($params, 0, -2)) . ")";
|
||||
$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 rtrim(str_replace(["\\", ".php", "phar://", rtrim(str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PATH), "/"), rtrim(str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PLUGIN_PATH), "/")], ["/", "", "", "", ""], $path), "/");
|
||||
return str_replace(["\\", ".php", "phar://", str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PATH), str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PLUGIN_PATH)], ["/", "", "", "", ""], $path);
|
||||
}
|
||||
|
||||
$errors = 0;
|
||||
$exitCode = 0;
|
||||
|
||||
if(php_sapi_name() !== "cli"){
|
||||
$logger->critical("You must run PocketMine-MP using the CLI.");
|
||||
++$errors;
|
||||
}
|
||||
do{
|
||||
$errors = 0;
|
||||
|
||||
$pthreads_version = phpversion("pthreads");
|
||||
if(substr_count($pthreads_version, ".") < 2){
|
||||
$pthreads_version = "0.$pthreads_version";
|
||||
}
|
||||
if(version_compare($pthreads_version, "3.1.5") < 0){
|
||||
$logger->critical("pthreads >= 3.1.5 is required, while you have $pthreads_version.");
|
||||
++$errors;
|
||||
}
|
||||
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(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.");
|
||||
if(php_sapi_name() !== "cli"){
|
||||
$logger->critical("You must run " . \pocketmine\NAME . " using the CLI.");
|
||||
++$errors;
|
||||
}
|
||||
}
|
||||
|
||||
if(extension_loaded("xdebug")){
|
||||
$logger->warning("
|
||||
|
||||
|
||||
You are running PocketMine with xdebug enabled. This has a major impact on performance.
|
||||
|
||||
");
|
||||
}
|
||||
|
||||
$extensions = [
|
||||
"curl" => "cURL",
|
||||
"json" => "JSON",
|
||||
"mbstring" => "Multibyte String",
|
||||
"yaml" => "YAML",
|
||||
"sockets" => "Sockets",
|
||||
"zip" => "Zip",
|
||||
"zlib" => "Zlib"
|
||||
];
|
||||
|
||||
foreach($extensions as $ext => $name){
|
||||
if(!extension_loaded($ext)){
|
||||
$logger->critical("Unable to find the $name ($ext) extension.");
|
||||
$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($errors > 0){
|
||||
$logger->critical("Please use the installer provided on the homepage, or recompile PHP again.");
|
||||
$logger->shutdown();
|
||||
$logger->join();
|
||||
exit(1); //Exit with error
|
||||
}
|
||||
|
||||
if(PHP_INT_SIZE < 8){
|
||||
$logger->warning("Running PocketMine-MP with 32-bit systems/PHP is deprecated. Support for 32-bit may be dropped in the future.");
|
||||
}
|
||||
|
||||
$gitHash = str_repeat("00", 20);
|
||||
if(file_exists(\pocketmine\PATH . ".git/HEAD")){ //Found Git information!
|
||||
$ref = trim(file_get_contents(\pocketmine\PATH . ".git/HEAD"));
|
||||
if(preg_match('/^[0-9a-f]{40}$/i', $ref)){
|
||||
$gitHash = strtolower($ref);
|
||||
}elseif(substr($ref, 0, 5) === "ref: "){
|
||||
$refFile = \pocketmine\PATH . ".git/" . substr($ref, 5);
|
||||
if(is_file($refFile)){
|
||||
$gitHash = strtolower(trim(file_get_contents($refFile)));
|
||||
if(extension_loaded("leveldb")){
|
||||
$leveldb_version = phpversion("leveldb");
|
||||
if(version_compare($leveldb_version, "0.2.0") < 0){
|
||||
$logger->critical("php-leveldb >= 0.2.0 is required, while you have $leveldb_version");
|
||||
++$errors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||
|
||||
|
||||
@define("ENDIANNESS", (pack("d", 1) === "\77\360\0\0\0\0\0\0" ? Binary::BIG_ENDIAN : Binary::LITTLE_ENDIAN));
|
||||
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
|
||||
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors
|
||||
|
||||
|
||||
if(!file_exists(\pocketmine\DATA . "server.properties") and !isset($opts["no-wizard"])){
|
||||
$installer = new SetupWizard();
|
||||
if(!$installer->run()){
|
||||
$logger->shutdown();
|
||||
$logger->join();
|
||||
exit(-1);
|
||||
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(\Phar::running(true) === ""){
|
||||
$logger->warning("Non-packaged PocketMine-MP installation detected, do not use on production.");
|
||||
}
|
||||
|
||||
ThreadManager::init();
|
||||
new Server($autoloader, $logger, \pocketmine\PATH, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
|
||||
|
||||
$logger->info("Stopping other threads");
|
||||
|
||||
$killer = new ServerKiller(8);
|
||||
$killer->start();
|
||||
|
||||
$erroredThreads = 0;
|
||||
foreach(ThreadManager::getInstance()->getAll() as $id => $thread){
|
||||
$logger->debug("Stopping " . $thread->getThreadName() . " thread");
|
||||
try{
|
||||
$thread->quit();
|
||||
$logger->debug($thread->getThreadName() . " thread stopped successfully.");
|
||||
}catch(\ThreadException $e){
|
||||
++$erroredThreads;
|
||||
$logger->debug("Could not stop " . $thread->getThreadName() . " thread: " . $e->getMessage());
|
||||
if(extension_loaded("xdebug")){
|
||||
$logger->warning(PHP_EOL . PHP_EOL . PHP_EOL . "\tYou are running " . \pocketmine\NAME . " with xdebug enabled. This has a major impact on performance." . PHP_EOL . PHP_EOL);
|
||||
}
|
||||
}
|
||||
|
||||
$extensions = [
|
||||
"bcmath" => "BC Math",
|
||||
"curl" => "cURL",
|
||||
"json" => "JSON",
|
||||
"mbstring" => "Multibyte String",
|
||||
"yaml" => "YAML",
|
||||
"sockets" => "Sockets",
|
||||
"zip" => "Zip",
|
||||
"zlib" => "Zlib"
|
||||
];
|
||||
|
||||
foreach($extensions as $ext => $name){
|
||||
if(!extension_loaded($ext)){
|
||||
$logger->critical("Unable to find the $name ($ext) extension.");
|
||||
++$errors;
|
||||
}
|
||||
}
|
||||
|
||||
if($errors > 0){
|
||||
$logger->critical("Please use the installer provided on the homepage, or recompile PHP again.");
|
||||
$exitCode = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
$gitHash = str_repeat("00", 20);
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
if(Utils::execute("git rev-parse HEAD", $out) === 0){
|
||||
$gitHash = trim($out);
|
||||
if(Utils::execute("git diff --quiet") === 1 or Utils::execute("git diff --cached --quiet") === 1){ //Locally-modified
|
||||
$gitHash .= "-dirty";
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$phar = new \Phar(\Phar::running(false));
|
||||
$meta = $phar->getMetadata();
|
||||
if(isset($meta["git"])){
|
||||
$gitHash = $meta["git"];
|
||||
}
|
||||
}
|
||||
|
||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||
|
||||
|
||||
@define("ENDIANNESS", (pack("d", 1) === "\77\360\0\0\0\0\0\0" ? Binary::BIG_ENDIAN : Binary::LITTLE_ENDIAN));
|
||||
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
|
||||
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors
|
||||
|
||||
|
||||
if(!file_exists(\pocketmine\DATA . "server.properties") and !isset($opts["no-wizard"])){
|
||||
$installer = new SetupWizard();
|
||||
if(!$installer->run()){
|
||||
$exitCode = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
$logger->warning("Non-packaged " . \pocketmine\NAME . " installation detected. Consider using a phar in production for better performance.");
|
||||
}
|
||||
|
||||
ThreadManager::init();
|
||||
new Server($autoloader, $logger, \pocketmine\PATH, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
|
||||
|
||||
$logger->info("Stopping other threads");
|
||||
|
||||
$killer = new ServerKiller(8);
|
||||
$killer->start();
|
||||
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
|
||||
|
||||
if(ThreadManager::getInstance()->stopAll() > 0){
|
||||
if(\pocketmine\DEBUG > 1){
|
||||
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
|
||||
}
|
||||
kill(getmypid());
|
||||
}
|
||||
}while(false);
|
||||
|
||||
$logger->shutdown();
|
||||
$logger->join();
|
||||
|
||||
echo Terminal::$FORMAT_RESET . PHP_EOL;
|
||||
|
||||
if($erroredThreads > 0){
|
||||
if(\pocketmine\DEBUG > 1){
|
||||
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
|
||||
}
|
||||
kill(getmypid());
|
||||
}else{
|
||||
exit(0);
|
||||
}
|
||||
|
||||
exit($exitCode);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
/**
|
||||
@ -41,17 +43,25 @@ abstract class Thread extends \Thread{
|
||||
$this->classLoader = $loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the class loader for this thread.
|
||||
*
|
||||
* WARNING: This method MUST be called from any descendent threads' run() method to make autoloading usable.
|
||||
* If you do not do this, you will not be able to use new classes that were not loaded when the thread was started
|
||||
* (unless you are using a custom autoloader).
|
||||
*/
|
||||
public function registerClassLoader(){
|
||||
require(\pocketmine\PATH . "vendor/autoload.php");
|
||||
if(!interface_exists("ClassLoader", false)){
|
||||
require(\pocketmine\PATH . "src/spl/ClassLoader.php");
|
||||
require(\pocketmine\PATH . "src/spl/BaseClassLoader.php");
|
||||
}
|
||||
if($this->classLoader !== null){
|
||||
$this->classLoader->register(true);
|
||||
$this->classLoader->register(false);
|
||||
}
|
||||
}
|
||||
|
||||
public function start(int $options = PTHREADS_INHERIT_ALL){
|
||||
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
||||
ThreadManager::getInstance()->add($this);
|
||||
|
||||
if(!$this->isRunning() and !$this->isJoined() and !$this->isTerminated()){
|
||||
@ -81,7 +91,7 @@ abstract class Thread extends \Thread{
|
||||
ThreadManager::getInstance()->remove($this);
|
||||
}
|
||||
|
||||
public function getThreadName(){
|
||||
public function getThreadName() : string{
|
||||
return (new \ReflectionClass($this))->getShortName();
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\utils\MainLogger;
|
||||
|
||||
class ThreadManager extends \Volatile{
|
||||
|
||||
/** @var ThreadManager */
|
||||
@ -58,7 +62,7 @@ class ThreadManager extends \Volatile{
|
||||
/**
|
||||
* @return Worker[]|Thread[]
|
||||
*/
|
||||
public function getAll(){
|
||||
public function getAll() : array{
|
||||
$array = [];
|
||||
foreach($this as $key => $thread){
|
||||
$array[$key] = $thread;
|
||||
@ -66,4 +70,23 @@ class ThreadManager extends \Volatile{
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
public function stopAll() : int{
|
||||
$logger = MainLogger::getLogger();
|
||||
|
||||
$erroredThreads = 0;
|
||||
|
||||
foreach($this->getAll() as $thread){
|
||||
$logger->debug("Stopping " . $thread->getThreadName() . " thread");
|
||||
try{
|
||||
$thread->quit();
|
||||
$logger->debug($thread->getThreadName() . " thread stopped successfully.");
|
||||
}catch(\ThreadException $e){
|
||||
++$erroredThreads;
|
||||
$logger->debug("Could not stop " . $thread->getThreadName() . " thread: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return $erroredThreads;
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
/**
|
||||
@ -42,17 +44,25 @@ abstract class Worker extends \Worker{
|
||||
$this->classLoader = $loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the class loader for this thread.
|
||||
*
|
||||
* WARNING: This method MUST be called from any descendent threads' run() method to make autoloading usable.
|
||||
* If you do not do this, you will not be able to use new classes that were not loaded when the thread was started
|
||||
* (unless you are using a custom autoloader).
|
||||
*/
|
||||
public function registerClassLoader(){
|
||||
require(\pocketmine\PATH . "vendor/autoload.php");
|
||||
if(!interface_exists("ClassLoader", false)){
|
||||
require(\pocketmine\PATH . "src/spl/ClassLoader.php");
|
||||
require(\pocketmine\PATH . "src/spl/BaseClassLoader.php");
|
||||
}
|
||||
if($this->classLoader !== null){
|
||||
$this->classLoader->register(true);
|
||||
$this->classLoader->register(false);
|
||||
}
|
||||
}
|
||||
|
||||
public function start(int $options = PTHREADS_INHERIT_ALL){
|
||||
public function start(?int $options = \PTHREADS_INHERIT_ALL){
|
||||
ThreadManager::getInstance()->add($this);
|
||||
|
||||
if(!$this->isRunning() and !$this->isJoined() and !$this->isTerminated()){
|
||||
@ -86,7 +96,7 @@ abstract class Worker extends \Worker{
|
||||
ThreadManager::getInstance()->remove($this);
|
||||
}
|
||||
|
||||
public function getThreadName(){
|
||||
public function getThreadName() : string{
|
||||
return (new \ReflectionClass($this))->getShortName();
|
||||
}
|
||||
}
|
||||
|
@ -19,17 +19,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class ActivatorRail extends Rail{
|
||||
|
||||
protected $id = self::ACTIVATOR_RAIL;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Activator Rail";
|
||||
}
|
||||
|
||||
//TODO
|
||||
}
|
||||
|
@ -19,9 +19,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
|
||||
|
||||
/**
|
||||
@ -32,47 +35,51 @@ class Air extends Transparent{
|
||||
protected $id = self::AIR;
|
||||
protected $meta = 0;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Air";
|
||||
}
|
||||
|
||||
public function canPassThrough(){
|
||||
public function canPassThrough() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isBreakable(Item $item){
|
||||
public function isBreakable(Item $item) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function canBeFlowedInto(){
|
||||
public function canBeFlowedInto() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function canBeReplaced(){
|
||||
public function canBeReplaced() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function canBePlaced(){
|
||||
public function canBePlaced() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isSolid(){
|
||||
public function isSolid() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
public function getBoundingBox() : ?AxisAlignedBB{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getCollisionBoxes() : array{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public function getResistance(){
|
||||
public function getBlastResistance() : float{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -19,11 +19,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\inventory\AnvilInventory;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Anvil extends Fallable{
|
||||
@ -34,27 +39,23 @@ class Anvil extends Fallable{
|
||||
|
||||
protected $id = self::ANVIL;
|
||||
|
||||
public function isSolid(){
|
||||
return false;
|
||||
}
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function canBeActivated(){
|
||||
public function isTransparent() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 5;
|
||||
}
|
||||
|
||||
public function getResistance(){
|
||||
public function getBlastResistance() : float{
|
||||
return 6000;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
static $names = [
|
||||
self::TYPE_NORMAL => "Anvil",
|
||||
self::TYPE_SLIGHTLY_DAMAGED => "Slightly Damaged Anvil",
|
||||
@ -63,11 +64,35 @@ class Anvil extends Fallable{
|
||||
return $names[$this->meta & 0x0c] ?? "Anvil";
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
public function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
$inset = 0.125;
|
||||
|
||||
if($this->meta & 0x01){ //east/west
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z + $inset,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1 - $inset
|
||||
);
|
||||
}else{
|
||||
return new AxisAlignedBB(
|
||||
$this->x + $inset,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1 - $inset,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($player instanceof Player){
|
||||
$player->addWindow(new AnvilInventory($this));
|
||||
}
|
||||
@ -75,19 +100,19 @@ class Anvil extends Fallable{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
$direction = ($player !== null ? $player->getDirection() : 0) & 0x03;
|
||||
$this->meta = ($this->meta & 0x0c) | $direction;
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
return $this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return [
|
||||
[$this->id, $this->meta & 0x0c, 1],
|
||||
ItemFactory::get($this->getItemId(), $this->getDamage() & 0x0c, 1)
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
@ -19,36 +19,42 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\event\TranslationContainer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\tile\Bed as TileBed;
|
||||
use pocketmine\tile\Tile;
|
||||
use pocketmine\utils\TextFormat;
|
||||
|
||||
class Bed extends Transparent{
|
||||
const BITFLAG_OCCUPIED = 0x04;
|
||||
const BITFLAG_HEAD = 0x08;
|
||||
|
||||
protected $id = self::BED_BLOCK;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
protected $itemId = Item::BED;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function canBeActivated(){
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 0.2;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Bed Block";
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox(){
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
@ -59,64 +65,123 @@ class Bed extends Transparent{
|
||||
);
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
public function isHeadPart() : bool{
|
||||
return ($this->meta & self::BITFLAG_HEAD) !== 0;
|
||||
}
|
||||
|
||||
$time = $this->getLevel()->getTime() % Level::TIME_FULL;
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isOccupied() : bool{
|
||||
return ($this->meta & self::BITFLAG_OCCUPIED) !== 0;
|
||||
}
|
||||
|
||||
$isNight = ($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE);
|
||||
|
||||
if($player instanceof Player and !$isNight){
|
||||
$player->sendMessage(new TranslationContainer(TextFormat::GRAY . "%tile.bed.noSleep"));
|
||||
return true;
|
||||
public function setOccupied(bool $occupied = true){
|
||||
if($occupied){
|
||||
$this->meta |= self::BITFLAG_OCCUPIED;
|
||||
}else{
|
||||
$this->meta &= ~self::BITFLAG_OCCUPIED;
|
||||
}
|
||||
|
||||
$blockNorth = $this->getSide(2); //Gets the blocks around them
|
||||
$blockSouth = $this->getSide(3);
|
||||
$blockEast = $this->getSide(5);
|
||||
$blockWest = $this->getSide(4);
|
||||
if(($this->meta & 0x08) === 0x08){ //This is the Top part of bed
|
||||
$b = $this;
|
||||
}else{ //Bottom Part of Bed
|
||||
if($blockNorth->getId() === $this->id and ($blockNorth->meta & 0x08) === 0x08){
|
||||
$b = $blockNorth;
|
||||
}elseif($blockSouth->getId() === $this->id and ($blockSouth->meta & 0x08) === 0x08){
|
||||
$b = $blockSouth;
|
||||
}elseif($blockEast->getId() === $this->id and ($blockEast->meta & 0x08) === 0x08){
|
||||
$b = $blockEast;
|
||||
}elseif($blockWest->getId() === $this->id and ($blockWest->meta & 0x08) === 0x08){
|
||||
$b = $blockWest;
|
||||
}else{
|
||||
if($player instanceof Player){
|
||||
$player->sendMessage(TextFormat::GRAY . "This bed is incomplete");
|
||||
}
|
||||
$this->getLevel()->setBlock($this, $this, false, false);
|
||||
|
||||
if(($other = $this->getOtherHalf()) !== null and !$other->isOccupied()){
|
||||
$other->setOccupied($occupied);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $meta
|
||||
* @param bool $isHead
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getOtherHalfSide(int $meta, bool $isHead = false) : int{
|
||||
$rotation = $meta & 0x03;
|
||||
$side = -1;
|
||||
|
||||
switch($rotation){
|
||||
case 0x00: //South
|
||||
$side = Vector3::SIDE_SOUTH;
|
||||
break;
|
||||
case 0x01: //West
|
||||
$side = Vector3::SIDE_WEST;
|
||||
break;
|
||||
case 0x02: //North
|
||||
$side = Vector3::SIDE_NORTH;
|
||||
break;
|
||||
case 0x03: //East
|
||||
$side = Vector3::SIDE_EAST;
|
||||
break;
|
||||
}
|
||||
|
||||
if($isHead){
|
||||
$side = Vector3::getOppositeSide($side);
|
||||
}
|
||||
|
||||
return $side;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Bed|null
|
||||
*/
|
||||
public function getOtherHalf() : ?Bed{
|
||||
$other = $this->getSide(self::getOtherHalfSide($this->meta, $this->isHeadPart()));
|
||||
if($other instanceof Bed and $other->getId() === $this->getId() and $other->isHeadPart() !== $this->isHeadPart() and (($other->getDamage() & 0x03) === ($this->getDamage() & 0x03))){
|
||||
return $other;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($player !== null){
|
||||
$other = $this->getOtherHalf();
|
||||
if($other === null){
|
||||
$player->sendMessage(TextFormat::GRAY . "This bed is incomplete");
|
||||
|
||||
return true;
|
||||
}elseif($player->distanceSquared($this) > 4 and $player->distanceSquared($other) > 4){
|
||||
//MCPE doesn't have messages for bed too far away
|
||||
return true;
|
||||
}
|
||||
|
||||
$time = $this->getLevel()->getTime() % Level::TIME_FULL;
|
||||
|
||||
$isNight = ($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE);
|
||||
|
||||
if(!$isNight){
|
||||
$player->sendMessage(new TranslationContainer(TextFormat::GRAY . "%tile.bed.noSleep"));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if($player instanceof Player and $player->sleepOn($b) === false){
|
||||
$player->sendMessage(new TranslationContainer(TextFormat::GRAY . "%tile.bed.occupied"));
|
||||
$b = ($this->isHeadPart() ? $this : $other);
|
||||
|
||||
if($b->isOccupied()){
|
||||
$player->sendMessage(new TranslationContainer(TextFormat::GRAY . "%tile.bed.occupied"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$player->sleepOn($b);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->isTransparent() === false){
|
||||
$faces = [
|
||||
0 => 3,
|
||||
1 => 4,
|
||||
2 => 2,
|
||||
3 => 5,
|
||||
];
|
||||
$d = $player instanceof Player ? $player->getDirection() : 0;
|
||||
$next = $this->getSide($faces[(($d + 3) % 4)]);
|
||||
$downNext = $this->getSide(0);
|
||||
if($next->canBeReplaced() === true and $downNext->isTransparent() === false){
|
||||
$meta = (($d + 3) % 4) & 0x03;
|
||||
$this->getLevel()->setBlock($block, Block::get($this->id, $meta), true, true);
|
||||
$this->getLevel()->setBlock($next, Block::get($this->id, $meta | 0x08), true, true);
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if(!$down->isTransparent()){
|
||||
$meta = (($player instanceof Player ? $player->getDirection() : 0) - 1) & 0x03;
|
||||
$next = $this->getSide(self::getOtherHalfSide($meta));
|
||||
if($next->canBeReplaced() === true and !$next->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||
$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);
|
||||
|
||||
Tile::createTile(Tile::BED, $this->getLevel(), TileBed::createNBT($this, $face, $item, $player));
|
||||
Tile::createTile(Tile::BED, $this->getLevel(), TileBed::createNBT($next, $face, $item, $player));
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -125,42 +190,30 @@ class Bed extends Transparent{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onBreak(Item $item){
|
||||
$blockNorth = $this->getSide(2); //Gets the blocks around them
|
||||
$blockSouth = $this->getSide(3);
|
||||
$blockEast = $this->getSide(5);
|
||||
$blockWest = $this->getSide(4);
|
||||
|
||||
if(($this->meta & 0x08) === 0x08){ //This is the Top part of bed
|
||||
if($blockNorth->getId() === $this->id and $blockNorth->meta !== 0x08){ //Checks if the block ID and meta are right
|
||||
$this->getLevel()->setBlock($blockNorth, new Air(), true, true);
|
||||
}elseif($blockSouth->getId() === $this->id and $blockSouth->meta !== 0x08){
|
||||
$this->getLevel()->setBlock($blockSouth, new Air(), true, true);
|
||||
}elseif($blockEast->getId() === $this->id and $blockEast->meta !== 0x08){
|
||||
$this->getLevel()->setBlock($blockEast, new Air(), true, true);
|
||||
}elseif($blockWest->getId() === $this->id and $blockWest->meta !== 0x08){
|
||||
$this->getLevel()->setBlock($blockWest, new Air(), true, true);
|
||||
}
|
||||
}else{ //Bottom Part of Bed
|
||||
if($blockNorth->getId() === $this->id and ($blockNorth->meta & 0x08) === 0x08){
|
||||
$this->getLevel()->setBlock($blockNorth, new Air(), true, true);
|
||||
}elseif($blockSouth->getId() === $this->id and ($blockSouth->meta & 0x08) === 0x08){
|
||||
$this->getLevel()->setBlock($blockSouth, new Air(), true, true);
|
||||
}elseif($blockEast->getId() === $this->id and ($blockEast->meta & 0x08) === 0x08){
|
||||
$this->getLevel()->setBlock($blockEast, new Air(), true, true);
|
||||
}elseif($blockWest->getId() === $this->id and ($blockWest->meta & 0x08) === 0x08){
|
||||
$this->getLevel()->setBlock($blockWest, new Air(), true, true);
|
||||
}
|
||||
public function onBreak(Item $item, Player $player = null) : bool{
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
|
||||
if(($other = $this->getOtherHalf()) !== null){
|
||||
$this->getLevel()->useBreakOn($other, $item, null, $player !== null); //make sure tiles get removed
|
||||
}
|
||||
$this->getLevel()->setBlock($this, new Air(), true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return [
|
||||
[Item::BED, 0, 1],
|
||||
];
|
||||
public function getDrops(Item $item) : array{
|
||||
if($this->isHeadPart()){
|
||||
$tile = $this->getLevel()->getTile($this);
|
||||
if($tile instanceof TileBed){
|
||||
return [
|
||||
ItemFactory::get($this->getItemId(), $tile->getColor(), 1)
|
||||
];
|
||||
}else{
|
||||
return [
|
||||
ItemFactory::get($this->getItemId(), 14, 1) //Red
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -27,23 +29,23 @@ class Bedrock extends Solid{
|
||||
|
||||
protected $id = self::BEDROCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Bedrock";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public function getResistance(){
|
||||
public function getBlastResistance() : float{
|
||||
return 18000000;
|
||||
}
|
||||
|
||||
public function isBreakable(Item $item){
|
||||
public function isBreakable(Item $item) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -19,31 +19,35 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
|
||||
class Beetroot extends Crops{
|
||||
|
||||
protected $id = self::BEETROOT_BLOCK;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Beetroot Block";
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
$drops = [];
|
||||
public function getDrops(Item $item) : array{
|
||||
if($this->meta >= 0x07){
|
||||
$drops[] = [Item::BEETROOT, 0, 1];
|
||||
$drops[] = [Item::BEETROOT_SEEDS, 0, mt_rand(0, 3)];
|
||||
}else{
|
||||
$drops[] = [Item::BEETROOT_SEEDS, 0, 1];
|
||||
return [
|
||||
ItemFactory::get(Item::BEETROOT, 0, 1),
|
||||
ItemFactory::get(Item::BEETROOT_SEEDS, 0, mt_rand(0, 3))
|
||||
];
|
||||
}
|
||||
|
||||
return $drops;
|
||||
return [
|
||||
ItemFactory::get(Item::BEETROOT_SEEDS, 0, 1)
|
||||
];
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
420
src/pocketmine/block/BlockFactory.php
Normal file
420
src/pocketmine/block/BlockFactory.php
Normal file
@ -0,0 +1,420 @@
|
||||
<?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\level\Position;
|
||||
|
||||
/**
|
||||
* Manages block registration and instance creation
|
||||
*/
|
||||
class BlockFactory{
|
||||
/** @var \SplFixedArray<Block> */
|
||||
private static $list = null;
|
||||
/** @var \SplFixedArray<Block> */
|
||||
private static $fullList = null;
|
||||
|
||||
/** @var \SplFixedArray<bool> */
|
||||
public static $solid = null;
|
||||
/** @var \SplFixedArray<bool> */
|
||||
public static $transparent = null;
|
||||
/** @var \SplFixedArray<float> */
|
||||
public static $hardness = null;
|
||||
/** @var \SplFixedArray<int> */
|
||||
public static $light = null;
|
||||
/** @var \SplFixedArray<int> */
|
||||
public static $lightFilter = null;
|
||||
/** @var \SplFixedArray<bool> */
|
||||
public static $diffusesSkyLight = null;
|
||||
/** @var \SplFixedArray<float> */
|
||||
public static $blastResistance = null;
|
||||
|
||||
/**
|
||||
* Initializes the block factory. By default this is called only once on server start, however you may wish to use
|
||||
* this if you need to reset the block factory back to its original defaults for whatever reason.
|
||||
*
|
||||
* @param bool $force
|
||||
*/
|
||||
public static function init(bool $force = false) : void{
|
||||
if(self::$list === null or $force){
|
||||
self::$list = new \SplFixedArray(256);
|
||||
self::$fullList = new \SplFixedArray(4096);
|
||||
|
||||
self::$light = new \SplFixedArray(256);
|
||||
self::$lightFilter = new \SplFixedArray(256);
|
||||
self::$solid = new \SplFixedArray(256);
|
||||
self::$hardness = new \SplFixedArray(256);
|
||||
self::$transparent = new \SplFixedArray(256);
|
||||
self::$diffusesSkyLight = new \SplFixedArray(256);
|
||||
self::$blastResistance = new \SplFixedArray(256);
|
||||
|
||||
self::registerBlock(new Air());
|
||||
self::registerBlock(new Stone());
|
||||
self::registerBlock(new Grass());
|
||||
self::registerBlock(new Dirt());
|
||||
self::registerBlock(new Cobblestone());
|
||||
self::registerBlock(new Planks());
|
||||
self::registerBlock(new Sapling());
|
||||
self::registerBlock(new Bedrock());
|
||||
self::registerBlock(new Water());
|
||||
self::registerBlock(new StillWater());
|
||||
self::registerBlock(new Lava());
|
||||
self::registerBlock(new StillLava());
|
||||
self::registerBlock(new Sand());
|
||||
self::registerBlock(new Gravel());
|
||||
self::registerBlock(new GoldOre());
|
||||
self::registerBlock(new IronOre());
|
||||
self::registerBlock(new CoalOre());
|
||||
self::registerBlock(new Wood());
|
||||
self::registerBlock(new Leaves());
|
||||
self::registerBlock(new Sponge());
|
||||
self::registerBlock(new Glass());
|
||||
self::registerBlock(new LapisOre());
|
||||
self::registerBlock(new Lapis());
|
||||
//TODO: DISPENSER
|
||||
self::registerBlock(new Sandstone());
|
||||
self::registerBlock(new NoteBlock());
|
||||
self::registerBlock(new Bed());
|
||||
self::registerBlock(new PoweredRail());
|
||||
self::registerBlock(new DetectorRail());
|
||||
//TODO: STICKY_PISTON
|
||||
self::registerBlock(new Cobweb());
|
||||
self::registerBlock(new TallGrass());
|
||||
self::registerBlock(new DeadBush());
|
||||
//TODO: PISTON
|
||||
//TODO: PISTONARMCOLLISION
|
||||
self::registerBlock(new Wool());
|
||||
|
||||
self::registerBlock(new Dandelion());
|
||||
self::registerBlock(new Flower());
|
||||
self::registerBlock(new BrownMushroom());
|
||||
self::registerBlock(new RedMushroom());
|
||||
self::registerBlock(new Gold());
|
||||
self::registerBlock(new Iron());
|
||||
self::registerBlock(new DoubleStoneSlab());
|
||||
self::registerBlock(new StoneSlab());
|
||||
self::registerBlock(new Bricks());
|
||||
self::registerBlock(new TNT());
|
||||
self::registerBlock(new Bookshelf());
|
||||
self::registerBlock(new MossyCobblestone());
|
||||
self::registerBlock(new Obsidian());
|
||||
self::registerBlock(new Torch());
|
||||
self::registerBlock(new Fire());
|
||||
self::registerBlock(new MonsterSpawner());
|
||||
self::registerBlock(new WoodenStairs(Block::OAK_STAIRS, 0, "Oak Stairs"));
|
||||
self::registerBlock(new Chest());
|
||||
//TODO: REDSTONE_WIRE
|
||||
self::registerBlock(new DiamondOre());
|
||||
self::registerBlock(new Diamond());
|
||||
self::registerBlock(new CraftingTable());
|
||||
self::registerBlock(new Wheat());
|
||||
self::registerBlock(new Farmland());
|
||||
self::registerBlock(new Furnace());
|
||||
self::registerBlock(new BurningFurnace());
|
||||
self::registerBlock(new SignPost());
|
||||
self::registerBlock(new WoodenDoor(Block::OAK_DOOR_BLOCK, 0, "Oak Door", Item::OAK_DOOR));
|
||||
self::registerBlock(new Ladder());
|
||||
self::registerBlock(new Rail());
|
||||
self::registerBlock(new CobblestoneStairs());
|
||||
self::registerBlock(new WallSign());
|
||||
self::registerBlock(new Lever());
|
||||
self::registerBlock(new StonePressurePlate());
|
||||
self::registerBlock(new IronDoor());
|
||||
self::registerBlock(new WoodenPressurePlate());
|
||||
self::registerBlock(new RedstoneOre());
|
||||
self::registerBlock(new GlowingRedstoneOre());
|
||||
self::registerBlock(new RedstoneTorchUnlit());
|
||||
self::registerBlock(new RedstoneTorch());
|
||||
self::registerBlock(new StoneButton());
|
||||
self::registerBlock(new SnowLayer());
|
||||
self::registerBlock(new Ice());
|
||||
self::registerBlock(new Snow());
|
||||
self::registerBlock(new Cactus());
|
||||
self::registerBlock(new Clay());
|
||||
self::registerBlock(new Sugarcane());
|
||||
//TODO: JUKEBOX
|
||||
self::registerBlock(new WoodenFence());
|
||||
self::registerBlock(new Pumpkin());
|
||||
self::registerBlock(new Netherrack());
|
||||
self::registerBlock(new SoulSand());
|
||||
self::registerBlock(new Glowstone());
|
||||
//TODO: PORTAL
|
||||
self::registerBlock(new LitPumpkin());
|
||||
self::registerBlock(new Cake());
|
||||
//TODO: REPEATER_BLOCK
|
||||
//TODO: POWERED_REPEATER
|
||||
//TODO: INVISIBLEBEDROCK
|
||||
self::registerBlock(new Trapdoor());
|
||||
//TODO: MONSTER_EGG
|
||||
self::registerBlock(new StoneBricks());
|
||||
self::registerBlock(new BrownMushroomBlock());
|
||||
self::registerBlock(new RedMushroomBlock());
|
||||
self::registerBlock(new IronBars());
|
||||
self::registerBlock(new GlassPane());
|
||||
self::registerBlock(new Melon());
|
||||
self::registerBlock(new PumpkinStem());
|
||||
self::registerBlock(new MelonStem());
|
||||
self::registerBlock(new Vine());
|
||||
self::registerBlock(new FenceGate(Block::OAK_FENCE_GATE, 0, "Oak Fence Gate"));
|
||||
self::registerBlock(new BrickStairs());
|
||||
self::registerBlock(new StoneBrickStairs());
|
||||
self::registerBlock(new Mycelium());
|
||||
self::registerBlock(new WaterLily());
|
||||
self::registerBlock(new NetherBrick(Block::NETHER_BRICK_BLOCK, 0, "Nether Bricks"));
|
||||
self::registerBlock(new NetherBrickFence());
|
||||
self::registerBlock(new NetherBrickStairs());
|
||||
self::registerBlock(new NetherWartPlant());
|
||||
self::registerBlock(new EnchantingTable());
|
||||
self::registerBlock(new BrewingStand());
|
||||
//TODO: CAULDRON_BLOCK
|
||||
//TODO: END_PORTAL
|
||||
self::registerBlock(new EndPortalFrame());
|
||||
self::registerBlock(new EndStone());
|
||||
//TODO: DRAGON_EGG
|
||||
self::registerBlock(new RedstoneLamp());
|
||||
self::registerBlock(new LitRedstoneLamp());
|
||||
//TODO: DROPPER
|
||||
self::registerBlock(new ActivatorRail());
|
||||
self::registerBlock(new CocoaBlock());
|
||||
self::registerBlock(new SandstoneStairs());
|
||||
self::registerBlock(new EmeraldOre());
|
||||
//TODO: ENDER_CHEST
|
||||
self::registerBlock(new TripwireHook());
|
||||
self::registerBlock(new Tripwire());
|
||||
self::registerBlock(new Emerald());
|
||||
self::registerBlock(new WoodenStairs(Block::SPRUCE_STAIRS, 0, "Spruce Stairs"));
|
||||
self::registerBlock(new WoodenStairs(Block::BIRCH_STAIRS, 0, "Birch Stairs"));
|
||||
self::registerBlock(new WoodenStairs(Block::JUNGLE_STAIRS, 0, "Jungle Stairs"));
|
||||
//TODO: COMMAND_BLOCK
|
||||
//TODO: BEACON
|
||||
self::registerBlock(new CobblestoneWall());
|
||||
self::registerBlock(new FlowerPot());
|
||||
self::registerBlock(new Carrot());
|
||||
self::registerBlock(new Potato());
|
||||
self::registerBlock(new WoodenButton());
|
||||
self::registerBlock(new Skull());
|
||||
self::registerBlock(new Anvil());
|
||||
self::registerBlock(new TrappedChest());
|
||||
self::registerBlock(new WeightedPressurePlateLight());
|
||||
self::registerBlock(new WeightedPressurePlateHeavy());
|
||||
//TODO: COMPARATOR_BLOCK
|
||||
//TODO: POWERED_COMPARATOR
|
||||
self::registerBlock(new DaylightSensor());
|
||||
self::registerBlock(new Redstone());
|
||||
self::registerBlock(new NetherQuartzOre());
|
||||
//TODO: HOPPER_BLOCK
|
||||
self::registerBlock(new Quartz());
|
||||
self::registerBlock(new QuartzStairs());
|
||||
self::registerBlock(new DoubleWoodenSlab());
|
||||
self::registerBlock(new WoodenSlab());
|
||||
self::registerBlock(new StainedClay());
|
||||
self::registerBlock(new StainedGlassPane());
|
||||
self::registerBlock(new Leaves2());
|
||||
self::registerBlock(new Wood2());
|
||||
self::registerBlock(new WoodenStairs(Block::ACACIA_STAIRS, 0, "Acacia Stairs"));
|
||||
self::registerBlock(new WoodenStairs(Block::DARK_OAK_STAIRS, 0, "Dark Oak Stairs"));
|
||||
//TODO: SLIME
|
||||
|
||||
self::registerBlock(new IronTrapdoor());
|
||||
self::registerBlock(new Prismarine());
|
||||
self::registerBlock(new SeaLantern());
|
||||
self::registerBlock(new HayBale());
|
||||
self::registerBlock(new Carpet());
|
||||
self::registerBlock(new HardenedClay());
|
||||
self::registerBlock(new Coal());
|
||||
self::registerBlock(new PackedIce());
|
||||
self::registerBlock(new DoublePlant());
|
||||
//TODO: STANDING_BANNER
|
||||
//TODO: WALL_BANNER
|
||||
//TODO: DAYLIGHT_DETECTOR_INVERTED
|
||||
self::registerBlock(new RedSandstone());
|
||||
self::registerBlock(new RedSandstoneStairs());
|
||||
self::registerBlock(new DoubleStoneSlab2());
|
||||
self::registerBlock(new StoneSlab2());
|
||||
self::registerBlock(new FenceGate(Block::SPRUCE_FENCE_GATE, 0, "Spruce Fence Gate"));
|
||||
self::registerBlock(new FenceGate(Block::BIRCH_FENCE_GATE, 0, "Birch Fence Gate"));
|
||||
self::registerBlock(new FenceGate(Block::JUNGLE_FENCE_GATE, 0, "Jungle Fence Gate"));
|
||||
self::registerBlock(new FenceGate(Block::DARK_OAK_FENCE_GATE, 0, "Dark Oak Fence Gate"));
|
||||
self::registerBlock(new FenceGate(Block::ACACIA_FENCE_GATE, 0, "Acacia Fence Gate"));
|
||||
//TODO: REPEATING_COMMAND_BLOCK
|
||||
//TODO: CHAIN_COMMAND_BLOCK
|
||||
|
||||
self::registerBlock(new WoodenDoor(Block::SPRUCE_DOOR_BLOCK, 0, "Spruce Door", Item::SPRUCE_DOOR));
|
||||
self::registerBlock(new WoodenDoor(Block::BIRCH_DOOR_BLOCK, 0, "Birch Door", Item::BIRCH_DOOR));
|
||||
self::registerBlock(new WoodenDoor(Block::JUNGLE_DOOR_BLOCK, 0, "Jungle Door", Item::JUNGLE_DOOR));
|
||||
self::registerBlock(new WoodenDoor(Block::ACACIA_DOOR_BLOCK, 0, "Acacia Door", Item::ACACIA_DOOR));
|
||||
self::registerBlock(new WoodenDoor(Block::DARK_OAK_DOOR_BLOCK, 0, "Dark Oak Door", Item::DARK_OAK_DOOR));
|
||||
self::registerBlock(new GrassPath());
|
||||
self::registerBlock(new ItemFrame());
|
||||
//TODO: CHORUS_FLOWER
|
||||
self::registerBlock(new Purpur());
|
||||
|
||||
self::registerBlock(new PurpurStairs());
|
||||
|
||||
//TODO: UNDYED_SHULKER_BOX
|
||||
self::registerBlock(new EndStoneBricks());
|
||||
//TODO: FROSTED_ICE
|
||||
self::registerBlock(new EndRod());
|
||||
//TODO: END_GATEWAY
|
||||
|
||||
self::registerBlock(new Magma());
|
||||
self::registerBlock(new NetherWartBlock());
|
||||
self::registerBlock(new NetherBrick(Block::RED_NETHER_BRICK, 0, "Red Nether Bricks"));
|
||||
self::registerBlock(new BoneBlock());
|
||||
|
||||
//TODO: SHULKER_BOX
|
||||
self::registerBlock(new GlazedTerracotta(Block::PURPLE_GLAZED_TERRACOTTA, 0, "Purple Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::WHITE_GLAZED_TERRACOTTA, 0, "White Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::ORANGE_GLAZED_TERRACOTTA, 0, "Orange Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::MAGENTA_GLAZED_TERRACOTTA, 0, "Magenta Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::LIGHT_BLUE_GLAZED_TERRACOTTA, 0, "Light Blue Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::YELLOW_GLAZED_TERRACOTTA, 0, "Yellow Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::LIME_GLAZED_TERRACOTTA, 0, "Lime Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::PINK_GLAZED_TERRACOTTA, 0, "Pink Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::GRAY_GLAZED_TERRACOTTA, 0, "Grey Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::SILVER_GLAZED_TERRACOTTA, 0, "Light Grey Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::CYAN_GLAZED_TERRACOTTA, 0, "Cyan Glazed Terracotta"));
|
||||
|
||||
self::registerBlock(new GlazedTerracotta(Block::BLUE_GLAZED_TERRACOTTA, 0, "Blue Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::BROWN_GLAZED_TERRACOTTA, 0, "Brown Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::GREEN_GLAZED_TERRACOTTA, 0, "Green Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::RED_GLAZED_TERRACOTTA, 0, "Red Glazed Terracotta"));
|
||||
self::registerBlock(new GlazedTerracotta(Block::BLACK_GLAZED_TERRACOTTA, 0, "Black Glazed Terracotta"));
|
||||
self::registerBlock(new Concrete());
|
||||
self::registerBlock(new ConcretePowder());
|
||||
|
||||
//TODO: CHORUS_PLANT
|
||||
self::registerBlock(new StainedGlass());
|
||||
|
||||
self::registerBlock(new Podzol());
|
||||
self::registerBlock(new Beetroot());
|
||||
self::registerBlock(new Stonecutter());
|
||||
self::registerBlock(new GlowingObsidian());
|
||||
self::registerBlock(new NetherReactor());
|
||||
//TODO: INFO_UPDATE
|
||||
//TODO: INFO_UPDATE2
|
||||
//TODO: MOVINGBLOCK
|
||||
//TODO: OBSERVER
|
||||
//TODO: STRUCTURE_BLOCK
|
||||
|
||||
//TODO: RESERVED6
|
||||
|
||||
foreach(self::$list as $id => $block){
|
||||
if($block === null){
|
||||
self::registerBlock(new UnknownBlock($id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a block type into the index. Plugins may use this method to register new block types or override
|
||||
* existing ones.
|
||||
*
|
||||
* NOTE: If you are registering a new block type, you will need to add it to the creative inventory yourself - it
|
||||
* will not automatically appear there.
|
||||
*
|
||||
* @param Block $block
|
||||
* @param bool $override Whether to override existing registrations
|
||||
*
|
||||
* @throws \RuntimeException if something attempted to override an already-registered block without specifying the
|
||||
* $override parameter.
|
||||
*/
|
||||
public static function registerBlock(Block $block, bool $override = false) : void{
|
||||
$id = $block->getId();
|
||||
|
||||
if(!$override and self::isRegistered($id)){
|
||||
throw new \RuntimeException("Trying to overwrite an already registered block");
|
||||
}
|
||||
|
||||
self::$list[$id] = clone $block;
|
||||
|
||||
for($meta = 0; $meta < 16; ++$meta){
|
||||
$variant = clone $block;
|
||||
$variant->setDamage($meta);
|
||||
self::$fullList[($id << 4) | $meta] = $variant;
|
||||
}
|
||||
|
||||
self::$solid[$id] = $block->isSolid();
|
||||
self::$transparent[$id] = $block->isTransparent();
|
||||
self::$hardness[$id] = $block->getHardness();
|
||||
self::$light[$id] = $block->getLightLevel();
|
||||
self::$lightFilter[$id] = $block->getLightFilter() + 1; //opacity plus 1 standard light filter
|
||||
self::$diffusesSkyLight[$id] = $block->diffusesSkyLight();
|
||||
self::$blastResistance[$id] = $block->getBlastResistance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Block instance with the specified ID, meta and position.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $meta
|
||||
* @param Position $pos
|
||||
*
|
||||
* @return Block
|
||||
*/
|
||||
public static function get(int $id, int $meta = 0, Position $pos = null) : Block{
|
||||
if($meta < 0 or $meta > 0xf){
|
||||
throw new \InvalidArgumentException("Block meta value $meta is out of bounds");
|
||||
}
|
||||
|
||||
try{
|
||||
if(self::$fullList !== null){
|
||||
$block = clone self::$fullList[($id << 4) | $meta];
|
||||
}else{
|
||||
$block = new UnknownBlock($id, $meta);
|
||||
}
|
||||
}catch(\RuntimeException $e){
|
||||
throw new \InvalidArgumentException("Block ID $id is out of bounds");
|
||||
}
|
||||
|
||||
if($pos !== null){
|
||||
$block->x = $pos->x;
|
||||
$block->y = $pos->y;
|
||||
$block->z = $pos->z;
|
||||
$block->level = $pos->level;
|
||||
}
|
||||
|
||||
return $block;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @return \SplFixedArray
|
||||
*/
|
||||
public static function getBlockStatesArray() : \SplFixedArray{
|
||||
return self::$fullList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a specified block ID is already registered in the block factory.
|
||||
*
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*/
|
||||
public static function isRegistered(int $id) : bool{
|
||||
$b = self::$list[$id];
|
||||
return $b !== null and !($b instanceof UnknownBlock);
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
interface BlockIds{
|
||||
@ -27,20 +29,20 @@ interface BlockIds{
|
||||
const STONE = 1;
|
||||
const GRASS = 2;
|
||||
const DIRT = 3;
|
||||
const COBBLESTONE = 4, COBBLE = 4;
|
||||
const PLANK = 5, PLANKS = 5, WOODEN_PLANK = 5, WOODEN_PLANKS = 5;
|
||||
const SAPLING = 6, SAPLINGS = 6;
|
||||
const COBBLESTONE = 4;
|
||||
const PLANKS = 5, WOODEN_PLANKS = 5;
|
||||
const SAPLING = 6;
|
||||
const BEDROCK = 7;
|
||||
const WATER = 8;
|
||||
const STILL_WATER = 9;
|
||||
const LAVA = 10;
|
||||
const STILL_LAVA = 11;
|
||||
const FLOWING_WATER = 8;
|
||||
const STILL_WATER = 9, WATER = 9;
|
||||
const FLOWING_LAVA = 10;
|
||||
const LAVA = 11, STILL_LAVA = 11;
|
||||
const SAND = 12;
|
||||
const GRAVEL = 13;
|
||||
const GOLD_ORE = 14;
|
||||
const IRON_ORE = 15;
|
||||
const COAL_ORE = 16;
|
||||
const LOG = 17, WOOD = 17, TRUNK = 17;
|
||||
const LOG = 17, WOOD = 17;
|
||||
const LEAVES = 18;
|
||||
const SPONGE = 19;
|
||||
const GLASS = 20;
|
||||
@ -48,35 +50,35 @@ interface BlockIds{
|
||||
const LAPIS_BLOCK = 22;
|
||||
const DISPENSER = 23;
|
||||
const SANDSTONE = 24;
|
||||
const NOTE_BLOCK = 25, NOTEBLOCK = 25;
|
||||
const NOTEBLOCK = 25, NOTE_BLOCK = 25;
|
||||
const BED_BLOCK = 26;
|
||||
const POWERED_RAIL = 27;
|
||||
const GOLDEN_RAIL = 27, POWERED_RAIL = 27;
|
||||
const DETECTOR_RAIL = 28;
|
||||
const STICKY_PISTON = 29;
|
||||
const COBWEB = 30;
|
||||
const TALL_GRASS = 31;
|
||||
const BUSH = 32, DEAD_BUSH = 32;
|
||||
const COBWEB = 30, WEB = 30;
|
||||
const TALLGRASS = 31, TALL_GRASS = 31;
|
||||
const DEADBUSH = 32, DEAD_BUSH = 32;
|
||||
const PISTON = 33;
|
||||
const PISTON_HEAD = 34;
|
||||
const PISTONARMCOLLISION = 34, PISTON_ARM_COLLISION = 34;
|
||||
const WOOL = 35;
|
||||
|
||||
const DANDELION = 37;
|
||||
const POPPY = 38, ROSE = 38, RED_FLOWER = 38;
|
||||
const DANDELION = 37, YELLOW_FLOWER = 37;
|
||||
const POPPY = 38, RED_FLOWER = 38;
|
||||
const BROWN_MUSHROOM = 39;
|
||||
const RED_MUSHROOM = 40;
|
||||
const GOLD_BLOCK = 41;
|
||||
const IRON_BLOCK = 42;
|
||||
const DOUBLE_SLAB = 43, DOUBLE_SLABS = 43;
|
||||
const SLAB = 44, SLABS = 44, STONE_SLAB = 44;
|
||||
const BRICKS = 45, BRICKS_BLOCK = 45;
|
||||
const DOUBLE_STONE_SLAB = 43;
|
||||
const STONE_SLAB = 44;
|
||||
const BRICK_BLOCK = 45;
|
||||
const TNT = 46;
|
||||
const BOOKSHELF = 47;
|
||||
const MOSS_STONE = 48, MOSSY_STONE = 48;
|
||||
const MOSSY_COBBLESTONE = 48, MOSS_STONE = 48;
|
||||
const OBSIDIAN = 49;
|
||||
const TORCH = 50;
|
||||
const FIRE = 51;
|
||||
const MONSTER_SPAWNER = 52;
|
||||
const WOOD_STAIRS = 53, WOODEN_STAIRS = 53, OAK_WOOD_STAIRS = 53, OAK_WOODEN_STAIRS = 53;
|
||||
const MOB_SPAWNER = 52, MONSTER_SPAWNER = 52;
|
||||
const OAK_STAIRS = 53, WOODEN_STAIRS = 53;
|
||||
const CHEST = 54;
|
||||
const REDSTONE_WIRE = 55;
|
||||
const DIAMOND_ORE = 56;
|
||||
@ -86,11 +88,11 @@ interface BlockIds{
|
||||
const FARMLAND = 60;
|
||||
const FURNACE = 61;
|
||||
const BURNING_FURNACE = 62, LIT_FURNACE = 62;
|
||||
const SIGN_POST = 63;
|
||||
const DOOR_BLOCK = 64, WOODEN_DOOR_BLOCK = 64, WOOD_DOOR_BLOCK = 64;
|
||||
const SIGN_POST = 63, STANDING_SIGN = 63;
|
||||
const OAK_DOOR_BLOCK = 64, WOODEN_DOOR_BLOCK = 64;
|
||||
const LADDER = 65;
|
||||
const RAIL = 66;
|
||||
const COBBLESTONE_STAIRS = 67, COBBLE_STAIRS = 67;
|
||||
const COBBLESTONE_STAIRS = 67, STONE_STAIRS = 67;
|
||||
const WALL_SIGN = 68;
|
||||
const LEVER = 69;
|
||||
const STONE_PRESSURE_PLATE = 70;
|
||||
@ -99,117 +101,120 @@ interface BlockIds{
|
||||
const REDSTONE_ORE = 73;
|
||||
const GLOWING_REDSTONE_ORE = 74, LIT_REDSTONE_ORE = 74;
|
||||
const UNLIT_REDSTONE_TORCH = 75;
|
||||
const REDSTONE_TORCH = 76, LIT_REDSTONE_TORCH = 76;
|
||||
const LIT_REDSTONE_TORCH = 76, REDSTONE_TORCH = 76;
|
||||
const STONE_BUTTON = 77;
|
||||
const SNOW = 78, SNOW_LAYER = 78;
|
||||
const SNOW_LAYER = 78;
|
||||
const ICE = 79;
|
||||
const SNOW_BLOCK = 80;
|
||||
const SNOW = 80, SNOW_BLOCK = 80;
|
||||
const CACTUS = 81;
|
||||
const CLAY_BLOCK = 82;
|
||||
const REEDS = 83, SUGARCANE_BLOCK = 83;
|
||||
|
||||
const REEDS_BLOCK = 83, SUGARCANE_BLOCK = 83;
|
||||
const JUKEBOX = 84;
|
||||
const FENCE = 85;
|
||||
const PUMPKIN = 86;
|
||||
const NETHERRACK = 87;
|
||||
const SOUL_SAND = 88;
|
||||
const GLOWSTONE = 89, GLOWSTONE_BLOCK = 89;
|
||||
const PORTAL_BLOCK = 90, PORTAL = 90;
|
||||
const GLOWSTONE = 89;
|
||||
const PORTAL = 90;
|
||||
const JACK_O_LANTERN = 91, LIT_PUMPKIN = 91;
|
||||
const CAKE_BLOCK = 92;
|
||||
const REPEATER_BLOCK = 93, UNPOWERED_REPEATER_BLOCK = 93;
|
||||
const POWERED_REPEATER_BLOCK = 94;
|
||||
const INVISIBLE_BEDROCK = 95;
|
||||
const REPEATER_BLOCK = 93, UNPOWERED_REPEATER = 93;
|
||||
const POWERED_REPEATER = 94;
|
||||
const INVISIBLEBEDROCK = 95, INVISIBLE_BEDROCK = 95;
|
||||
const TRAPDOOR = 96, WOODEN_TRAPDOOR = 96;
|
||||
const MONSTER_EGG_BLOCK = 97;
|
||||
const STONE_BRICKS = 98, STONE_BRICK = 98;
|
||||
const MONSTER_EGG = 97;
|
||||
const STONEBRICK = 98, STONE_BRICK = 98, STONE_BRICKS = 98;
|
||||
const BROWN_MUSHROOM_BLOCK = 99;
|
||||
const RED_MUSHROOM_BLOCK = 100;
|
||||
const IRON_BARS = 101, IRON_BAR = 101;
|
||||
const GLASS_PANE = 102, GLASS_PANEL = 102;
|
||||
const IRON_BARS = 101;
|
||||
const GLASS_PANE = 102;
|
||||
const MELON_BLOCK = 103;
|
||||
const PUMPKIN_STEM = 104;
|
||||
const MELON_STEM = 105;
|
||||
const VINES = 106, VINE = 106;
|
||||
const VINE = 106, VINES = 106;
|
||||
const FENCE_GATE = 107, OAK_FENCE_GATE = 107;
|
||||
const BRICK_STAIRS = 108;
|
||||
const STONE_BRICK_STAIRS = 109;
|
||||
const MYCELIUM = 110;
|
||||
const LILY_PAD = 111, WATER_LILY = 111;
|
||||
const NETHER_BRICKS = 112, NETHER_BRICK_BLOCK = 112;
|
||||
const LILY_PAD = 111, WATERLILY = 111, WATER_LILY = 111;
|
||||
const NETHER_BRICK_BLOCK = 112;
|
||||
const NETHER_BRICK_FENCE = 113;
|
||||
const NETHER_BRICK_STAIRS = 114, NETHER_BRICKS_STAIRS = 114;
|
||||
const NETHER_WART_BLOCK = 115;
|
||||
const ENCHANTING_TABLE = 116, ENCHANT_TABLE = 116, ENCHANTMENT_TABLE = 116;
|
||||
const NETHER_BRICK_STAIRS = 114;
|
||||
const NETHER_WART_PLANT = 115;
|
||||
const ENCHANTING_TABLE = 116, ENCHANTMENT_TABLE = 116;
|
||||
const BREWING_STAND_BLOCK = 117;
|
||||
const CAULDRON_BLOCK = 118;
|
||||
|
||||
const END_PORTAL_FRAME = 120, END_PORTAL = 120;
|
||||
const END_PORTAL = 119;
|
||||
const END_PORTAL_FRAME = 120;
|
||||
const END_STONE = 121;
|
||||
|
||||
const REDSTONE_LAMP = 123, INACTIVE_REDSTONE_LAMP = 123;
|
||||
const LIT_REDSTONE_LAMP = 124, ACTIVE_REDSTONE_LAMP = 124;
|
||||
const DRAGON_EGG = 122;
|
||||
const REDSTONE_LAMP = 123;
|
||||
const LIT_REDSTONE_LAMP = 124;
|
||||
const DROPPER = 125;
|
||||
const ACTIVATOR_RAIL = 126;
|
||||
const COCOA_BLOCK = 127, COCOA_PODS = 127;
|
||||
const COCOA = 127, COCOA_BLOCK = 127;
|
||||
const SANDSTONE_STAIRS = 128;
|
||||
const EMERALD_ORE = 129;
|
||||
|
||||
const ENDER_CHEST = 130;
|
||||
const TRIPWIRE_HOOK = 131;
|
||||
const TRIPWIRE = 132;
|
||||
const TRIPWIRE = 132, TRIP_WIRE = 132;
|
||||
const EMERALD_BLOCK = 133;
|
||||
const SPRUCE_WOOD_STAIRS = 134, SPRUCE_WOODEN_STAIRS = 134;
|
||||
const BIRCH_WOOD_STAIRS = 135, BIRCH_WOODEN_STAIRS = 135;
|
||||
const JUNGLE_WOOD_STAIRS = 136, JUNGLE_WOODEN_STAIRS = 136;
|
||||
|
||||
const SPRUCE_STAIRS = 134;
|
||||
const BIRCH_STAIRS = 135;
|
||||
const JUNGLE_STAIRS = 136;
|
||||
const COMMAND_BLOCK = 137;
|
||||
const BEACON = 138;
|
||||
const COBBLESTONE_WALL = 139, COBBLE_WALL = 139, STONE_WALL = 139;
|
||||
const COBBLESTONE_WALL = 139, STONE_WALL = 139;
|
||||
const FLOWER_POT_BLOCK = 140;
|
||||
const CARROT_BLOCK = 141;
|
||||
const POTATO_BLOCK = 142;
|
||||
const CARROTS = 141, CARROT_BLOCK = 141;
|
||||
const POTATOES = 142, POTATO_BLOCK = 142;
|
||||
const WOODEN_BUTTON = 143;
|
||||
const MOB_HEAD_BLOCK = 144, SKULL_BLOCK = 144;
|
||||
const ANVIL = 145;
|
||||
const TRAPPED_CHEST = 146;
|
||||
const WEIGHTED_PRESSURE_PLATE_LIGHT = 147, LIGHT_WEIGHTED_PRESSURE_PLATE = 147, GOLD_PRESSURE_PLATE = 147;
|
||||
const WEIGHTED_PRESSURE_PLATE_HEAVY = 148, HEAVY_WEIGHTED_PRESSURE_PLATE = 148, IRON_PRESSURE_PLATE = 148;
|
||||
const COMPARATOR_BLOCK = 149, UNPOWERED_COMPARATOR_BLOCK = 149;
|
||||
const POWERED_COMPARATOR_BLOCK = 150;
|
||||
const DAYLIGHT_SENSOR = 151;
|
||||
const LIGHT_WEIGHTED_PRESSURE_PLATE = 147;
|
||||
const HEAVY_WEIGHTED_PRESSURE_PLATE = 148;
|
||||
const COMPARATOR_BLOCK = 149, UNPOWERED_COMPARATOR = 149;
|
||||
const POWERED_COMPARATOR = 150;
|
||||
const DAYLIGHT_DETECTOR = 151, DAYLIGHT_SENSOR = 151;
|
||||
const REDSTONE_BLOCK = 152;
|
||||
const NETHER_QUARTZ_ORE = 153;
|
||||
const NETHER_QUARTZ_ORE = 153, QUARTZ_ORE = 153;
|
||||
const HOPPER_BLOCK = 154;
|
||||
const QUARTZ_BLOCK = 155;
|
||||
const QUARTZ_STAIRS = 156;
|
||||
const DOUBLE_WOOD_SLAB = 157, DOUBLE_WOODEN_SLAB = 157, DOUBLE_WOOD_SLABS = 157, DOUBLE_WOODEN_SLABS = 157;
|
||||
const WOOD_SLAB = 158, WOODEN_SLAB = 158, WOOD_SLABS = 158, WOODEN_SLABS = 158;
|
||||
const STAINED_CLAY = 159, STAINED_HARDENED_CLAY = 159;
|
||||
|
||||
const DOUBLE_WOODEN_SLAB = 157;
|
||||
const WOODEN_SLAB = 158;
|
||||
const STAINED_CLAY = 159, STAINED_HARDENED_CLAY = 159, TERRACOTTA = 159;
|
||||
const STAINED_GLASS_PANE = 160;
|
||||
const LEAVES2 = 161;
|
||||
const WOOD2 = 162, TRUNK2 = 162, LOG2 = 162;
|
||||
const ACACIA_WOOD_STAIRS = 163, ACACIA_WOODEN_STAIRS = 163;
|
||||
const DARK_OAK_WOOD_STAIRS = 164, DARK_OAK_WOODEN_STAIRS = 164;
|
||||
const SLIME_BLOCK = 165;
|
||||
const LOG2 = 162, WOOD2 = 162;
|
||||
const ACACIA_STAIRS = 163;
|
||||
const DARK_OAK_STAIRS = 164;
|
||||
const SLIME = 165, SLIME_BLOCK = 165;
|
||||
|
||||
const IRON_TRAPDOOR = 167;
|
||||
const PRISMARINE = 168;
|
||||
const SEA_LANTERN = 169;
|
||||
const HAY_BALE = 170;
|
||||
const SEALANTERN = 169, SEA_LANTERN = 169;
|
||||
const HAY_BALE = 170, HAY_BLOCK = 170;
|
||||
const CARPET = 171;
|
||||
const HARDENED_CLAY = 172;
|
||||
const COAL_BLOCK = 173;
|
||||
const PACKED_ICE = 174;
|
||||
const DOUBLE_PLANT = 175;
|
||||
|
||||
const INVERTED_DAYLIGHT_SENSOR = 178, DAYLIGHT_SENSOR_INVERTED = 178;
|
||||
const STANDING_BANNER = 176;
|
||||
const WALL_BANNER = 177;
|
||||
const DAYLIGHT_DETECTOR_INVERTED = 178, DAYLIGHT_SENSOR_INVERTED = 178;
|
||||
const RED_SANDSTONE = 179;
|
||||
const RED_SANDSTONE_STAIRS = 180;
|
||||
const DOUBLE_RED_SANDSTONE_SLAB = 181;
|
||||
const RED_SANDSTONE_SLAB = 182;
|
||||
const SPRUCE_FENCE_GATE = 183, FENCE_GATE_SPRUCE = 183;
|
||||
const BIRCH_FENCE_GATE = 184, FENCE_GATE_BIRCH = 184;
|
||||
const JUNGLE_FENCE_GATE = 185, FENCE_GATE_JUNGLE = 185;
|
||||
const DARK_OAK_FENCE_GATE = 186, FENCE_GATE_DARK_OAK = 186;
|
||||
const ACACIA_FENCE_GATE = 187, FENCE_GATE_ACACIA = 187;
|
||||
const DOUBLE_STONE_SLAB2 = 181;
|
||||
const STONE_SLAB2 = 182;
|
||||
const SPRUCE_FENCE_GATE = 183;
|
||||
const BIRCH_FENCE_GATE = 184;
|
||||
const JUNGLE_FENCE_GATE = 185;
|
||||
const DARK_OAK_FENCE_GATE = 186;
|
||||
const ACACIA_FENCE_GATE = 187;
|
||||
const REPEATING_COMMAND_BLOCK = 188;
|
||||
const CHAIN_COMMAND_BLOCK = 189;
|
||||
|
||||
const SPRUCE_DOOR_BLOCK = 193;
|
||||
const BIRCH_DOOR_BLOCK = 194;
|
||||
@ -217,16 +222,58 @@ interface BlockIds{
|
||||
const ACACIA_DOOR_BLOCK = 196;
|
||||
const DARK_OAK_DOOR_BLOCK = 197;
|
||||
const GRASS_PATH = 198;
|
||||
const ITEM_FRAME_BLOCK = 199;
|
||||
const FRAME_BLOCK = 199, ITEM_FRAME_BLOCK = 199;
|
||||
const CHORUS_FLOWER = 200;
|
||||
const PURPUR_BLOCK = 201;
|
||||
|
||||
const PURPUR_STAIRS = 203;
|
||||
|
||||
const UNDYED_SHULKER_BOX = 205;
|
||||
const END_BRICKS = 206;
|
||||
const FROSTED_ICE = 207;
|
||||
const END_ROD = 208;
|
||||
const END_GATEWAY = 209;
|
||||
|
||||
const MAGMA = 213;
|
||||
const NETHER_WART_BLOCK = 214;
|
||||
const RED_NETHER_BRICK = 215;
|
||||
const BONE_BLOCK = 216;
|
||||
|
||||
const SHULKER_BOX = 218;
|
||||
const PURPLE_GLAZED_TERRACOTTA = 219;
|
||||
const WHITE_GLAZED_TERRACOTTA = 220;
|
||||
const ORANGE_GLAZED_TERRACOTTA = 221;
|
||||
const MAGENTA_GLAZED_TERRACOTTA = 222;
|
||||
const LIGHT_BLUE_GLAZED_TERRACOTTA = 223;
|
||||
const YELLOW_GLAZED_TERRACOTTA = 224;
|
||||
const LIME_GLAZED_TERRACOTTA = 225;
|
||||
const PINK_GLAZED_TERRACOTTA = 226;
|
||||
const GRAY_GLAZED_TERRACOTTA = 227;
|
||||
const SILVER_GLAZED_TERRACOTTA = 228;
|
||||
const CYAN_GLAZED_TERRACOTTA = 229;
|
||||
|
||||
const BLUE_GLAZED_TERRACOTTA = 231;
|
||||
const BROWN_GLAZED_TERRACOTTA = 232;
|
||||
const GREEN_GLAZED_TERRACOTTA = 233;
|
||||
const RED_GLAZED_TERRACOTTA = 234;
|
||||
const BLACK_GLAZED_TERRACOTTA = 235;
|
||||
const CONCRETE = 236;
|
||||
const CONCRETEPOWDER = 237, CONCRETE_POWDER = 237;
|
||||
|
||||
const CHORUS_PLANT = 240;
|
||||
const STAINED_GLASS = 241;
|
||||
|
||||
const PODZOL = 243;
|
||||
const BEETROOT_BLOCK = 244;
|
||||
const STONECUTTER = 245;
|
||||
const GLOWING_OBSIDIAN = 246;
|
||||
const NETHER_REACTOR = 247;
|
||||
const UPDATE_BLOCK = 248;
|
||||
const ATEUPD_BLOCK = 249;
|
||||
const BLOCK_MOVED_BY_PISTON = 250;
|
||||
const GLOWINGOBSIDIAN = 246, GLOWING_OBSIDIAN = 246;
|
||||
const NETHERREACTOR = 247, NETHER_REACTOR = 247;
|
||||
const INFO_UPDATE = 248;
|
||||
const INFO_UPDATE2 = 249;
|
||||
const MOVINGBLOCK = 250, MOVING_BLOCK = 250;
|
||||
const OBSERVER = 251;
|
||||
const INFO_RESERVED6 = 255;
|
||||
const STRUCTURE_BLOCK = 252;
|
||||
|
||||
const RESERVED6 = 255;
|
||||
|
||||
}
|
||||
|
69
src/pocketmine/block/BoneBlock.php
Normal file
69
src/pocketmine/block/BoneBlock.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?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\block\utils\PillarRotationHelper;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class BoneBlock extends Solid{
|
||||
|
||||
protected $id = Block::BONE_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Bone Block";
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
$this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face);
|
||||
return $this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0x03;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
@ -19,28 +19,42 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
|
||||
class Bookshelf extends Solid{
|
||||
|
||||
protected $id = self::BOOKSHELF;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Bookshelf";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 1.5;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_AXE;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::BOOK, 0, 3)
|
||||
];
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
return 300;
|
||||
}
|
||||
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
@ -27,19 +29,25 @@ class BrewingStand extends Transparent{
|
||||
|
||||
protected $id = self::BREWING_STAND_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Brewing Stand";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//TODO
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
@ -27,23 +29,23 @@ class BrickStairs extends Stair{
|
||||
|
||||
protected $id = self::BRICK_STAIRS;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getResistance(){
|
||||
public function getBlastResistance() : float{
|
||||
return 30;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Brick Stairs";
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -26,35 +28,33 @@ use pocketmine\item\Tool;
|
||||
|
||||
class Bricks extends Solid{
|
||||
|
||||
protected $id = self::BRICKS_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
protected $id = self::BRICK_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getResistance(){
|
||||
public function getBlastResistance() : float{
|
||||
return 30;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Bricks";
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return [
|
||||
[Item::BRICKS_BLOCK, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
@ -19,53 +19,19 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\Player;
|
||||
|
||||
class BrownMushroom extends Flowable{
|
||||
class BrownMushroom extends RedMushroom{
|
||||
|
||||
protected $id = self::BROWN_MUSHROOM;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Brown Mushroom";
|
||||
}
|
||||
|
||||
public function getLightLevel(){
|
||||
public function getLightLevel() : int{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(0)->isTransparent() === true){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->isTransparent() === false){
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
41
src/pocketmine/block/BrownMushroomBlock.php
Normal file
41
src/pocketmine/block/BrownMushroomBlock.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?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;
|
||||
|
||||
class BrownMushroomBlock extends RedMushroomBlock{
|
||||
|
||||
protected $id = Block::BROWN_MUSHROOM_BLOCK;
|
||||
|
||||
public function getName() : string{
|
||||
return "Brown Mushroom Block";
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
return [
|
||||
Item::get(Item::BROWN_MUSHROOM, 0, mt_rand(0, 2))
|
||||
];
|
||||
}
|
||||
}
|
@ -19,14 +19,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\tile\Furnace as TileFurnace;
|
||||
@ -36,82 +35,46 @@ class BurningFurnace extends Solid{
|
||||
|
||||
protected $id = self::BURNING_FURNACE;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Burning Furnace";
|
||||
}
|
||||
|
||||
public function canBeActivated(){
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 3.5;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getLightLevel(){
|
||||
public function getLightLevel() : int{
|
||||
return 13;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
$faces = [
|
||||
0 => 4,
|
||||
1 => 2,
|
||||
2 => 5,
|
||||
3 => 3,
|
||||
3 => 3
|
||||
];
|
||||
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
$nbt = new CompoundTag("", [
|
||||
new ListTag("Items", []),
|
||||
new StringTag("id", Tile::FURNACE),
|
||||
new IntTag("x", $this->x),
|
||||
new IntTag("y", $this->y),
|
||||
new IntTag("z", $this->z)
|
||||
]);
|
||||
$nbt->Items->setTagType(NBT::TAG_Compound);
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
|
||||
if($item->hasCustomName()){
|
||||
$nbt->CustomName = new StringTag("CustomName", $item->getCustomName());
|
||||
}
|
||||
|
||||
if($item->hasCustomBlockData()){
|
||||
foreach($item->getCustomBlockData() as $key => $v){
|
||||
$nbt->{$key} = $v;
|
||||
}
|
||||
}
|
||||
|
||||
Tile::createTile("Furnace", $this->getLevel(), $nbt);
|
||||
Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this, $face, $item, $player));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onBreak(Item $item){
|
||||
$this->getLevel()->setBlock($this, new Air(), true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($player instanceof Player){
|
||||
$furnace = $this->getLevel()->getTile($this);
|
||||
if(!($furnace instanceof TileFurnace)){
|
||||
$nbt = new CompoundTag("", [
|
||||
new ListTag("Items", []),
|
||||
new StringTag("id", Tile::FURNACE),
|
||||
new IntTag("x", $this->x),
|
||||
new IntTag("y", $this->y),
|
||||
new IntTag("z", $this->z)
|
||||
]);
|
||||
$nbt->Items->setTagType(NBT::TAG_Compound);
|
||||
$furnace = Tile::createTile("Furnace", $this->getLevel(), $nbt);
|
||||
$furnace = Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this));
|
||||
}
|
||||
|
||||
if(isset($furnace->namedtag->Lock) and $furnace->namedtag->Lock instanceof StringTag){
|
||||
@ -126,12 +89,15 @@ class BurningFurnace extends Solid{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
$drops = [];
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
$drops[] = [Item::FURNACE, 0, 1];
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return $drops;
|
||||
return [];
|
||||
}
|
||||
}
|
51
src/pocketmine/block/Button.php
Normal file
51
src/pocketmine/block/Button.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
abstract class Button extends Flowable{
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
//TODO: check valid target block
|
||||
$this->meta = $face;
|
||||
|
||||
return $this->level->setBlock($this, $this, true, true);
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
//TODO
|
||||
return true;
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
@ -36,23 +38,23 @@ class Cactus extends Transparent{
|
||||
|
||||
protected $id = self::CACTUS;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 0.4;
|
||||
}
|
||||
|
||||
public function hasEntityCollision(){
|
||||
public function hasEntityCollision() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Cactus";
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox(){
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
|
||||
return new AxisAlignedBB(
|
||||
$this->x + 0.0625,
|
||||
@ -64,14 +66,18 @@ class Cactus extends Transparent{
|
||||
);
|
||||
}
|
||||
|
||||
public function onEntityCollide(Entity $entity){
|
||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_CONTACT, 1);
|
||||
$entity->attack($ev->getFinalDamage(), $ev);
|
||||
public function ticksRandomly() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
public function onEntityCollide(Entity $entity) : void{
|
||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_CONTACT, 1);
|
||||
$entity->attack($ev);
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
$down = $this->getSide(0);
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() !== self::SAND and $down->getId() !== self::CACTUS){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
}else{
|
||||
@ -83,12 +89,12 @@ class Cactus extends Transparent{
|
||||
}
|
||||
}
|
||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
||||
if($this->getSide(0)->getId() !== self::CACTUS){
|
||||
if($this->meta == 0x0F){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::CACTUS){
|
||||
if($this->meta === 0x0f){
|
||||
for($y = 1; $y < 3; ++$y){
|
||||
$b = $this->getLevel()->getBlock(new Vector3($this->x, $this->y + $y, $this->z));
|
||||
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z);
|
||||
if($b->getId() === self::AIR){
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($b, new Cactus()));
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS)));
|
||||
if(!$ev->isCancelled()){
|
||||
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
|
||||
}
|
||||
@ -106,13 +112,13 @@ class Cactus extends Transparent{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() === self::SAND or $down->getId() === self::CACTUS){
|
||||
$block0 = $this->getSide(2);
|
||||
$block1 = $this->getSide(3);
|
||||
$block2 = $this->getSide(4);
|
||||
$block3 = $this->getSide(5);
|
||||
$block0 = $this->getSide(Vector3::SIDE_NORTH);
|
||||
$block1 = $this->getSide(Vector3::SIDE_SOUTH);
|
||||
$block2 = $this->getSide(Vector3::SIDE_WEST);
|
||||
$block3 = $this->getSide(Vector3::SIDE_EAST);
|
||||
if($block0->isTransparent() === true and $block1->isTransparent() === true and $block2->isTransparent() === true and $block3->isTransparent() === true){
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
|
||||
@ -123,9 +129,7 @@ class Cactus extends Transparent{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Effect;
|
||||
@ -27,34 +29,31 @@ use pocketmine\item\FoodSource;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Cake extends Transparent implements FoodSource{
|
||||
|
||||
protected $id = self::CAKE_BLOCK;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function canBeActivated(){
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Cake Block";
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox(){
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
|
||||
$f = (1 + $this->getDamage() * 2) / 16;
|
||||
$f = $this->getDamage() * 0.125; //1 slice width
|
||||
|
||||
return new AxisAlignedBB(
|
||||
$this->x + $f,
|
||||
$this->x + 0.0625 + $f,
|
||||
$this->y,
|
||||
$this->z + 0.0625,
|
||||
$this->x + 1 - 0.0625,
|
||||
@ -63,10 +62,10 @@ class Cake extends Transparent implements FoodSource{
|
||||
);
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() !== self::AIR){
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -74,10 +73,10 @@ class Cake extends Transparent implements FoodSource{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(0)->getId() === self::AIR){ //Replace with common break method
|
||||
$this->getLevel()->setBlock($this, new Air(), true);
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
@ -86,15 +85,22 @@ class Cake extends Transparent implements FoodSource{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
if($player instanceof Player and $player->getHealth() < $player->getMaxHealth()){
|
||||
$ev = new EntityEatBlockEvent($player, $this);
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
//TODO: refactor this into generic food handling
|
||||
if($player instanceof Player and $player->getFood() < $player->getMaxFood()){
|
||||
$player->getServer()->getPluginManager()->callEvent($ev = new EntityEatBlockEvent($player, $this));
|
||||
|
||||
if(!$ev->isCancelled()){
|
||||
$player->addFood($ev->getFoodRestore());
|
||||
$player->addSaturation($ev->getSaturationRestore());
|
||||
foreach($ev->getAdditionalEffects() as $effect){
|
||||
$player->addEffect($effect);
|
||||
}
|
||||
|
||||
$this->getLevel()->setBlock($this, $ev->getResidue());
|
||||
return true;
|
||||
}
|
||||
@ -114,8 +120,8 @@ class Cake extends Transparent implements FoodSource{
|
||||
public function getResidue(){
|
||||
$clone = clone $this;
|
||||
$clone->meta++;
|
||||
if($clone->meta >= 0x06){
|
||||
$clone = new Air();
|
||||
if($clone->meta > 0x06){
|
||||
$clone = BlockFactory::get(Block::AIR);
|
||||
}
|
||||
return $clone;
|
||||
}
|
||||
|
@ -19,52 +19,38 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Carpet extends Flowable{
|
||||
|
||||
protected $id = self::CARPET;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 0.1;
|
||||
}
|
||||
|
||||
public function isSolid(){
|
||||
public function isSolid() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
static $names = [
|
||||
0 => "White Carpet",
|
||||
1 => "Orange Carpet",
|
||||
2 => "Magenta Carpet",
|
||||
3 => "Light Blue Carpet",
|
||||
4 => "Yellow Carpet",
|
||||
5 => "Lime Carpet",
|
||||
6 => "Pink Carpet",
|
||||
7 => "Gray Carpet",
|
||||
8 => "Light Gray Carpet",
|
||||
9 => "Cyan Carpet",
|
||||
10 => "Purple Carpet",
|
||||
11 => "Blue Carpet",
|
||||
12 => "Brown Carpet",
|
||||
13 => "Green Carpet",
|
||||
14 => "Red Carpet",
|
||||
15 => "Black Carpet",
|
||||
];
|
||||
return $names[$this->meta & 0x0f];
|
||||
public function getName() : string{
|
||||
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Carpet";
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox(){
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
@ -76,10 +62,10 @@ class Carpet extends Flowable{
|
||||
);
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() !== self::AIR){
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -87,9 +73,9 @@ class Carpet extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(0)->getId() === self::AIR){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
|
@ -19,30 +19,28 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
|
||||
class Carrot extends Crops{
|
||||
|
||||
protected $id = self::CARROT_BLOCK;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Carrot Block";
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
$drops = [];
|
||||
if($this->meta >= 0x07){
|
||||
$drops[] = [Item::CARROT, 0, mt_rand(1, 4)];
|
||||
}else{
|
||||
$drops[] = [Item::CARROT, 0, 1];
|
||||
}
|
||||
|
||||
return $drops;
|
||||
public function getDrops(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::CARROT, 0, $this->meta >= 0x07 ? mt_rand(1, 4) : 1)
|
||||
];
|
||||
}
|
||||
}
|
@ -19,15 +19,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\tile\Chest as TileChest;
|
||||
@ -37,27 +36,23 @@ class Chest extends Transparent{
|
||||
|
||||
protected $id = self::CHEST;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function canBeActivated(){
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 2.5;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Chest";
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_AXE;
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox(){
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return new AxisAlignedBB(
|
||||
$this->x + 0.0625,
|
||||
$this->y,
|
||||
@ -68,12 +63,12 @@ class Chest extends Transparent{
|
||||
);
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
$faces = [
|
||||
0 => 4,
|
||||
1 => 2,
|
||||
2 => 5,
|
||||
3 => 3,
|
||||
3 => 3
|
||||
];
|
||||
|
||||
$chest = null;
|
||||
@ -95,27 +90,8 @@ class Chest extends Transparent{
|
||||
}
|
||||
}
|
||||
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
$nbt = new CompoundTag("", [
|
||||
new ListTag("Items", []),
|
||||
new StringTag("id", Tile::CHEST),
|
||||
new IntTag("x", $this->x),
|
||||
new IntTag("y", $this->y),
|
||||
new IntTag("z", $this->z)
|
||||
]);
|
||||
$nbt->Items->setTagType(NBT::TAG_Compound);
|
||||
|
||||
if($item->hasCustomName()){
|
||||
$nbt->CustomName = new StringTag("CustomName", $item->getCustomName());
|
||||
}
|
||||
|
||||
if($item->hasCustomBlockData()){
|
||||
foreach($item->getCustomBlockData() as $key => $v){
|
||||
$nbt->{$key} = $v;
|
||||
}
|
||||
}
|
||||
|
||||
$tile = Tile::createTile("Chest", $this->getLevel(), $nbt);
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
$tile = Tile::createTile(Tile::CHEST, $this->getLevel(), TileChest::createNBT($this, $face, $item, $player));
|
||||
|
||||
if($chest instanceof TileChest and $tile instanceof TileChest){
|
||||
$chest->pairWith($tile);
|
||||
@ -125,43 +101,33 @@ class Chest extends Transparent{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onBreak(Item $item){
|
||||
public function onBreak(Item $item, Player $player = null) : bool{
|
||||
$t = $this->getLevel()->getTile($this);
|
||||
if($t instanceof TileChest){
|
||||
$t->unpair();
|
||||
}
|
||||
$this->getLevel()->setBlock($this, new Air(), true, true);
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($player instanceof Player){
|
||||
$top = $this->getSide(1);
|
||||
if($top->isTransparent() !== true){
|
||||
return true;
|
||||
}
|
||||
|
||||
$t = $this->getLevel()->getTile($this);
|
||||
$chest = null;
|
||||
if($t instanceof TileChest){
|
||||
$chest = $t;
|
||||
}else{
|
||||
$nbt = new CompoundTag("", [
|
||||
new ListTag("Items", []),
|
||||
new StringTag("id", Tile::CHEST),
|
||||
new IntTag("x", $this->x),
|
||||
new IntTag("y", $this->y),
|
||||
new IntTag("z", $this->z)
|
||||
]);
|
||||
$nbt->Items->setTagType(NBT::TAG_Compound);
|
||||
$chest = Tile::createTile("Chest", $this->getLevel(), $nbt);
|
||||
$chest = Tile::createTile(Tile::CHEST, $this->getLevel(), TileChest::createNBT($this));
|
||||
}
|
||||
|
||||
if(isset($chest->namedtag->Lock) and $chest->namedtag->Lock instanceof StringTag){
|
||||
if($chest->namedtag->Lock->getValue() !== $item->getCustomName()){
|
||||
return true;
|
||||
}
|
||||
if(
|
||||
!$this->getSide(Vector3::SIDE_UP)->isTransparent() or
|
||||
($chest->isPaired() and !$chest->getPair()->getBlock()->getSide(Vector3::SIDE_UP)->isTransparent()) or
|
||||
(isset($chest->namedtag->Lock) and $chest->namedtag->Lock instanceof StringTag and $chest->namedtag->Lock->getValue() !== $item->getCustomName())
|
||||
){
|
||||
return true;
|
||||
}
|
||||
|
||||
$player->addWindow($chest->getInventory());
|
||||
@ -170,9 +136,11 @@ class Chest extends Transparent{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
return 300;
|
||||
}
|
||||
}
|
@ -19,34 +19,37 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
|
||||
class Clay extends Solid{
|
||||
|
||||
protected $id = self::CLAY_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 0.6;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Clay Block";
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
return [
|
||||
[Item::CLAY, 0, 4],
|
||||
ItemFactory::get(Item::CLAY_BALL, 0, 4)
|
||||
];
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,29 +30,31 @@ class Coal extends Solid{
|
||||
|
||||
protected $id = self::COAL_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 5;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Coal Block";
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return [
|
||||
[Item::COAL_BLOCK, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
return 16000;
|
||||
}
|
||||
}
|
@ -19,39 +19,42 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
|
||||
class CoalOre extends Solid{
|
||||
|
||||
protected $id = self::COAL_ORE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 3;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Coal Ore";
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return [
|
||||
[Item::COAL, 0, 1],
|
||||
ItemFactory::get(Item::COAL, 0, 1)
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,29 +30,27 @@ class Cobblestone extends Solid{
|
||||
|
||||
protected $id = self::COBBLESTONE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Cobblestone";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return [
|
||||
[Item::COBBLESTONE, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
@ -27,19 +29,19 @@ class CobblestoneStairs extends Stair{
|
||||
|
||||
protected $id = self::COBBLESTONE_STAIRS;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Cobblestone Stairs";
|
||||
}
|
||||
|
||||
|
@ -19,35 +19,33 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
|
||||
class StoneWall extends Transparent{
|
||||
class CobblestoneWall extends Transparent{
|
||||
const NONE_MOSSY_WALL = 0;
|
||||
const MOSSY_WALL = 1;
|
||||
|
||||
protected $id = self::STONE_WALL;
|
||||
protected $id = self::COBBLESTONE_WALL;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function isSolid(){
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
if($this->meta === 0x01){
|
||||
return "Mossy Cobblestone Wall";
|
||||
}
|
||||
@ -55,38 +53,38 @@ class StoneWall extends Transparent{
|
||||
return "Cobblestone Wall";
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox(){
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
//walls don't have any special collision boxes like fences do
|
||||
|
||||
$north = $this->canConnect($this->getSide(Vector3::SIDE_NORTH));
|
||||
$south = $this->canConnect($this->getSide(Vector3::SIDE_SOUTH));
|
||||
$west = $this->canConnect($this->getSide(Vector3::SIDE_WEST));
|
||||
$east = $this->canConnect($this->getSide(Vector3::SIDE_EAST));
|
||||
|
||||
$n = $north ? 0 : 0.25;
|
||||
$s = $south ? 1 : 0.75;
|
||||
$w = $west ? 0 : 0.25;
|
||||
$e = $east ? 1 : 0.75;
|
||||
|
||||
if($north and $south and !$west and !$east){
|
||||
$w = 0.3125;
|
||||
$e = 0.6875;
|
||||
}elseif(!$north and !$south and $west and $east){
|
||||
$n = 0.3125;
|
||||
$s = 0.6875;
|
||||
$inset = 0.25;
|
||||
if(
|
||||
$this->getSide(Vector3::SIDE_UP)->getId() === Block::AIR and //if there is a block on top, it stays as a post
|
||||
(
|
||||
($north and $south and !$west and !$east) or
|
||||
(!$north and !$south and $west and $east)
|
||||
)
|
||||
){
|
||||
//If connected to two sides on the same axis but not any others, AND there is not a block on top, there is no post and the wall is thinner
|
||||
$inset = 0.3125;
|
||||
}
|
||||
|
||||
return new AxisAlignedBB(
|
||||
$this->x + $w,
|
||||
$this->x + ($west ? 0 : $inset),
|
||||
$this->y,
|
||||
$this->z + $n,
|
||||
$this->x + $e,
|
||||
$this->z + ($north ? 0 : $inset),
|
||||
$this->x + 1 - ($east ? 0 : $inset),
|
||||
$this->y + 1.5,
|
||||
$this->z + $s
|
||||
$this->z + 1 - ($south ? 0 : $inset)
|
||||
);
|
||||
}
|
||||
|
||||
public function canConnect(Block $block){
|
||||
return ($block->getId() !== self::COBBLE_WALL and $block->getId() !== self::FENCE_GATE) ? $block->isSolid() and !$block->isTransparent() : true;
|
||||
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
|
||||
}
|
||||
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
@ -29,32 +31,36 @@ class Cobweb extends Flowable{
|
||||
|
||||
protected $id = self::COBWEB;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function hasEntityCollision(){
|
||||
public function hasEntityCollision() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Cobweb";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 4;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SWORD;
|
||||
}
|
||||
|
||||
public function onEntityCollide(Entity $entity){
|
||||
public function onEntityCollide(Entity $entity) : void{
|
||||
$entity->resetFallDistance();
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
//TODO: correct drops
|
||||
return [];
|
||||
}
|
||||
|
||||
public function diffusesSkyLight() : bool{
|
||||
return true;
|
||||
}
|
||||
}
|
@ -19,17 +19,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class CocoaBlock extends Solid{
|
||||
class CocoaBlock extends Transparent{
|
||||
|
||||
protected $id = self::COCOA_BLOCK;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Cocoa Block";
|
||||
}
|
||||
|
||||
//TODO
|
||||
}
|
||||
|
58
src/pocketmine/block/Concrete.php
Normal file
58
src/pocketmine/block/Concrete.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?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\block\utils\ColorBlockMetaHelper;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
|
||||
class Concrete extends Solid{
|
||||
|
||||
protected $id = Block::CONCRETE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Concrete";
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 1.8;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
78
src/pocketmine/block/ConcretePowder.php
Normal file
78
src/pocketmine/block/ConcretePowder.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?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\block\utils\ColorBlockMetaHelper;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\level\Level;
|
||||
|
||||
class ConcretePowder extends Fallable{
|
||||
|
||||
protected $id = self::CONCRETE_POWDER;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Concrete Powder";
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL and ($block = $this->checkAdjacentWater()) !== null){
|
||||
$this->level->setBlock($this, $block);
|
||||
return $type;
|
||||
}
|
||||
|
||||
return parent::onUpdate($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|Block
|
||||
*/
|
||||
public function tickFalling() : ?Block{
|
||||
return $this->checkAdjacentWater();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|Block
|
||||
*/
|
||||
private function checkAdjacentWater() : ?Block{
|
||||
for($i = 1; $i < 6; ++$i){ //Do not check underneath
|
||||
if($this->getSide($i) instanceof Water){
|
||||
return Block::get(Block::CONCRETE, $this->meta);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -19,48 +19,45 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\inventory\BigCraftingGrid;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\Player;
|
||||
|
||||
//TODO: check orientation
|
||||
class Workbench extends Solid{
|
||||
class CraftingTable extends Solid{
|
||||
|
||||
protected $id = self::WORKBENCH;
|
||||
protected $id = self::CRAFTING_TABLE;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function canBeActivated(){
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 2.5;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Crafting Table";
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_AXE;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($player instanceof Player){
|
||||
$player->setCraftingGrid(new BigCraftingGrid($player));
|
||||
$player->craftingType = 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
public function getFuelTime() : int{
|
||||
return 300;
|
||||
}
|
||||
}
|
@ -19,24 +19,22 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\event\block\BlockGrowEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\Server;
|
||||
|
||||
abstract class Crops extends Flowable{
|
||||
|
||||
public function canBeActivated(){
|
||||
return true;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->getId() === self::FARMLAND){
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
if($blockReplace->getSide(Vector3::SIDE_DOWN)->getId() === Block::FARMLAND){
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -45,7 +43,7 @@ abstract class Crops extends Flowable{
|
||||
}
|
||||
|
||||
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
||||
$block = clone $this;
|
||||
$block->meta += mt_rand(2, 5);
|
||||
@ -67,14 +65,18 @@ abstract class Crops extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
public function ticksRandomly() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(0)->isTransparent() === true){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
||||
if(mt_rand(0, 2) == 1){
|
||||
if(mt_rand(0, 2) === 1){
|
||||
if($this->meta < 0x07){
|
||||
$block = clone $this;
|
||||
++$block->meta;
|
||||
|
@ -19,29 +19,32 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Dandelion extends Flowable{
|
||||
|
||||
protected $id = self::DANDELION;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Dandelion";
|
||||
}
|
||||
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->getId() === 2 or $down->getId() === 3 or $down->getId() === 60){
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() === Block::GRASS or $down->getId() === Block::DIRT or $down->getId() === Block::FARMLAND){
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -49,9 +52,9 @@ class Dandelion extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(0)->isTransparent() === true){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
|
@ -1,31 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class DarkOakWoodStairs extends WoodStairs{
|
||||
|
||||
protected $id = self::DARK_OAK_WOOD_STAIRS;
|
||||
|
||||
public function getName(){
|
||||
return "Dark Oak Wood Stairs";
|
||||
}
|
||||
}
|
@ -19,21 +19,29 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class DaylightSensor extends Transparent{
|
||||
|
||||
protected $id = self::DAYLIGHT_SENSOR;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Daylight Sensor";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 0.2;
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
return 300;
|
||||
}
|
||||
|
||||
//TODO
|
||||
}
|
||||
|
@ -19,26 +19,31 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
|
||||
class DeadBush extends Flowable{
|
||||
|
||||
protected $id = self::DEAD_BUSH;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Dead Bush";
|
||||
}
|
||||
|
||||
|
||||
public function onUpdate($type){
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(0)->isTransparent() === true){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
@ -48,4 +53,17 @@ class DeadBush extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SHEARS;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isShears()){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [
|
||||
ItemFactory::get(Item::STICK, 0, mt_rand(0, 2))
|
||||
];
|
||||
}
|
||||
}
|
@ -19,17 +19,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class DetectorRail extends Rail{
|
||||
|
||||
protected $id = self::DETECTOR_RAIL;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Detector Rail";
|
||||
}
|
||||
|
||||
//TODO
|
||||
}
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,29 +30,27 @@ class Diamond extends Solid{
|
||||
|
||||
protected $id = self::DIAMOND_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 5;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Diamond Block";
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
||||
return [
|
||||
[Item::DIAMOND_BLOCK, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
@ -19,38 +19,41 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
|
||||
class DiamondOre extends Solid{
|
||||
|
||||
protected $id = self::DIAMOND_ORE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 3;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Diamond Ore";
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
||||
return [
|
||||
[Item::DIAMOND, 0, 1],
|
||||
ItemFactory::get(Item::DIAMOND, 0, 1)
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -29,30 +31,33 @@ class Dirt extends Solid{
|
||||
|
||||
protected $id = self::DIRT;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function canBeActivated(){
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
if($this->meta === 1){
|
||||
return "Coarse Dirt";
|
||||
}
|
||||
return "Dirt";
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($item->isHoe()){
|
||||
$item->useOn($this);
|
||||
$this->getLevel()->setBlock($this, Block::get(Item::FARMLAND, 0), true);
|
||||
if($this->meta === 1){
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
||||
}else{
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND), true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -31,11 +33,7 @@ use pocketmine\Player;
|
||||
|
||||
abstract class Door extends Transparent{
|
||||
|
||||
public function canBeActivated(){
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isSolid(){
|
||||
public function isSolid() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -56,7 +54,7 @@ abstract class Door extends Transparent{
|
||||
return $down & 0x07 | ($isUp ? 8 : 0) | ($isRight ? 0x10 : 0);
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox(){
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
|
||||
$f = 0.1875;
|
||||
$damage = $this->getFullDamage();
|
||||
@ -203,12 +201,12 @@ abstract class Door extends Transparent{
|
||||
return $bb;
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(0)->getId() === self::AIR){ //Replace with common break method
|
||||
$this->getLevel()->setBlock($this, new Air(), false);
|
||||
if($this->getSide(1) instanceof Door){
|
||||
$this->getLevel()->setBlock($this->getSide(1), new Air(), false);
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false);
|
||||
if($this->getSide(Vector3::SIDE_UP) instanceof Door){
|
||||
$this->getLevel()->setBlock($this->getSide(Vector3::SIDE_UP), BlockFactory::get(Block::AIR), false);
|
||||
}
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
@ -218,64 +216,59 @@ abstract class Door extends Transparent{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
if($face === 1){
|
||||
$blockUp = $this->getSide(1);
|
||||
$blockDown = $this->getSide(0);
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
if($face === Vector3::SIDE_UP){
|
||||
$blockUp = $this->getSide(Vector3::SIDE_UP);
|
||||
$blockDown = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($blockUp->canBeReplaced() === false or $blockDown->isTransparent() === true){
|
||||
return false;
|
||||
}
|
||||
$direction = $player instanceof Player ? $player->getDirection() : 0;
|
||||
$face = [
|
||||
$faces = [
|
||||
0 => 3,
|
||||
1 => 4,
|
||||
2 => 2,
|
||||
3 => 5,
|
||||
3 => 5
|
||||
];
|
||||
$next = $this->getSide($face[(($direction + 2) % 4)]);
|
||||
$next2 = $this->getSide($face[$direction]);
|
||||
$next = $this->getSide($faces[($direction + 2) % 4]);
|
||||
$next2 = $this->getSide($faces[$direction]);
|
||||
$metaUp = 0x08;
|
||||
if($next->getId() === $this->getId() or ($next2->isTransparent() === false and $next->isTransparent() === true)){ //Door hinge
|
||||
$metaUp |= 0x01;
|
||||
}
|
||||
|
||||
$this->setDamage($player->getDirection() & 0x03);
|
||||
$this->getLevel()->setBlock($block, $this, true, true); //Bottom
|
||||
$this->getLevel()->setBlock($blockUp, $b = Block::get($this->getId(), $metaUp), true); //Top
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true); //Bottom
|
||||
$this->getLevel()->setBlock($blockUp, $b = BlockFactory::get($this->getId(), $metaUp), true); //Top
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onBreak(Item $item){
|
||||
public function onBreak(Item $item, Player $player = null) : bool{
|
||||
if(($this->getDamage() & 0x08) === 0x08){
|
||||
$down = $this->getSide(0);
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() === $this->getId()){
|
||||
$this->getLevel()->setBlock($down, new Air(), true);
|
||||
$this->getLevel()->setBlock($down, BlockFactory::get(Block::AIR), true);
|
||||
}
|
||||
}else{
|
||||
$up = $this->getSide(1);
|
||||
$up = $this->getSide(Vector3::SIDE_UP);
|
||||
if($up->getId() === $this->getId()){
|
||||
$this->getLevel()->setBlock($up, new Air(), true);
|
||||
$this->getLevel()->setBlock($up, BlockFactory::get(Block::AIR), true);
|
||||
}
|
||||
}
|
||||
$this->getLevel()->setBlock($this, new Air(), true);
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if(($this->getDamage() & 0x08) === 0x08){ //Top
|
||||
$down = $this->getSide(0);
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() === $this->getId()){
|
||||
$meta = $down->getDamage() ^ 0x04;
|
||||
$this->getLevel()->setBlock($down, Block::get($this->getId(), $meta), true);
|
||||
$players = $this->getLevel()->getChunkPlayers($this->x >> 4, $this->z >> 4);
|
||||
if($player instanceof Player){
|
||||
unset($players[$player->getLoaderId()]);
|
||||
}
|
||||
|
||||
$this->level->setBlock($down, BlockFactory::get($this->getId(), $meta), true);
|
||||
$this->level->addSound(new DoorSound($this));
|
||||
return true;
|
||||
}
|
||||
@ -283,14 +276,14 @@ abstract class Door extends Transparent{
|
||||
return false;
|
||||
}else{
|
||||
$this->meta ^= 0x04;
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
$players = $this->getLevel()->getChunkPlayers($this->x >> 4, $this->z >> 4);
|
||||
if($player instanceof Player){
|
||||
unset($players[$player->getLoaderId()]);
|
||||
}
|
||||
$this->level->setBlock($this, $this, true);
|
||||
$this->level->addSound(new DoorSound($this));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -19,24 +19,30 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class DoublePlant extends Flowable{
|
||||
const BITFLAG_TOP = 0x08;
|
||||
|
||||
protected $id = self::DOUBLE_PLANT;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function canBeReplaced(){
|
||||
return true;
|
||||
public function canBeReplaced() : bool{
|
||||
return $this->meta === 2 or $this->meta === 3; //grass or fern
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
static $names = [
|
||||
0 => "Sunflower",
|
||||
1 => "Lilac",
|
||||
@ -45,14 +51,44 @@ class DoublePlant extends Flowable{
|
||||
4 => "Rose Bush",
|
||||
5 => "Peony"
|
||||
];
|
||||
return $names[$this->meta & 0x07];
|
||||
return $names[$this->getVariant()] ?? "";
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
$id = $blockReplace->getSide(Vector3::SIDE_DOWN)->getId();
|
||||
if(($id === Block::GRASS or $id === Block::DIRT) and $blockReplace->getSide(Vector3::SIDE_UP)->canBeReplaced()){
|
||||
$this->getLevel()->setBlock($blockReplace, $this, false, false);
|
||||
$this->getLevel()->setBlock($blockReplace->getSide(Vector3::SIDE_UP), BlockFactory::get($this->id, $this->meta | self::BITFLAG_TOP), false, false);
|
||||
|
||||
public function onUpdate($type){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this double-plant has a corresponding other half.
|
||||
* @return bool
|
||||
*/
|
||||
public function isValidHalfPlant() : bool{
|
||||
if($this->meta & self::BITFLAG_TOP){
|
||||
$other = $this->getSide(Vector3::SIDE_DOWN);
|
||||
}else{
|
||||
$other = $this->getSide(Vector3::SIDE_UP);
|
||||
}
|
||||
|
||||
return (
|
||||
$other->getId() === $this->getId() and
|
||||
$other->getVariant() === $this->getVariant() and
|
||||
($other->getDamage() & self::BITFLAG_TOP) !== ($this->getDamage() & self::BITFLAG_TOP)
|
||||
);
|
||||
}
|
||||
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(0)->isTransparent() === true){ //Replace with common break method
|
||||
$this->getLevel()->setBlock($this, new Air(), true, true);
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if(!$this->isValidHalfPlant() or (($this->meta & self::BITFLAG_TOP) === 0 and $down->isTransparent())){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
@ -61,10 +97,33 @@ class DoublePlant extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
//TODO
|
||||
public function onBreak(Item $item, Player $player = null) : bool{
|
||||
if(parent::onBreak($item, $player) and $this->isValidHalfPlant()){
|
||||
$this->getLevel()->useBreakOn($this->getSide(($this->meta & self::BITFLAG_TOP) !== 0 ? Vector3::SIDE_DOWN : Vector3::SIDE_UP), $item, $player, $player !== null);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0x07;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($this->meta & self::BITFLAG_TOP){
|
||||
if(!$item->isShears() and ($this->meta === 2 or $this->meta === 3)){ //grass or fern
|
||||
if(mt_rand(0, 24) === 0){
|
||||
return [
|
||||
ItemFactory::get(Item::SEEDS, 0, 1)
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
@ -19,49 +19,29 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\item\ItemFactory;
|
||||
|
||||
class DoubleSlab extends Solid{
|
||||
abstract class DoubleSlab extends Solid{
|
||||
|
||||
protected $id = self::DOUBLE_SLAB;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
return 2;
|
||||
abstract public function getSlabId() : int;
|
||||
|
||||
public function getName() : string{
|
||||
return "Double " . BlockFactory::get($this->getSlabId(), $this->getVariant())->getName() . " Slab";
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
static $names = [
|
||||
0 => "Stone",
|
||||
1 => "Sandstone",
|
||||
2 => "Wooden",
|
||||
3 => "Cobblestone",
|
||||
4 => "Brick",
|
||||
5 => "Stone Brick",
|
||||
6 => "Quartz",
|
||||
7 => "Nether Brick",
|
||||
public function getDrops(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get($this->getSlabId(), $this->getVariant(), 2)
|
||||
];
|
||||
return "Double " . $names[$this->meta & 0x07] . " Slab";
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return [
|
||||
[Item::SLAB, $this->meta & 0x07, 2],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -19,38 +19,35 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
|
||||
class MossStone extends Solid{
|
||||
class DoubleStoneSlab extends DoubleSlab{
|
||||
|
||||
protected $id = self::MOSS_STONE;
|
||||
protected $id = self::DOUBLE_STONE_SLAB;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
public function getSlabId() : int{
|
||||
return self::STONE_SLAB;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
return "Moss Stone";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return [
|
||||
[Item::MOSS_STONE, $this->meta, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
@ -19,14 +19,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class DoubleStoneSlab2 extends DoubleStoneSlab{
|
||||
|
||||
class FenceGateDarkOak extends FenceGate{
|
||||
protected $id = self::DOUBLE_STONE_SLAB2;
|
||||
|
||||
protected $id = self::FENCE_GATE_DARK_OAK;
|
||||
|
||||
public function getName(){
|
||||
return "Dark Oak Fence Gate";
|
||||
public function getSlabId() : int{
|
||||
return self::STONE_SLAB2;
|
||||
}
|
||||
|
||||
}
|
43
src/pocketmine/block/DoubleWoodenSlab.php
Normal file
43
src/pocketmine/block/DoubleWoodenSlab.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?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\Tool;
|
||||
|
||||
class DoubleWoodenSlab extends DoubleSlab{
|
||||
|
||||
protected $id = self::DOUBLE_WOODEN_SLAB;
|
||||
|
||||
public function getSlabId() : int{
|
||||
return self::WOODEN_SLAB;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_AXE;
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,29 +30,27 @@ class Emerald extends Solid{
|
||||
|
||||
protected $id = self::EMERALD_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 5;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Emerald Block";
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
||||
return [
|
||||
[Item::EMERALD_BLOCK, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
@ -19,38 +19,41 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
|
||||
class EmeraldOre extends Solid{
|
||||
|
||||
protected $id = self::EMERALD_ORE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Emerald Ore";
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 3;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
||||
return [
|
||||
[Item::EMERALD, 0, 1],
|
||||
ItemFactory::get(Item::EMERALD, 0, 1)
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
@ -19,70 +19,51 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\inventory\EnchantInventory;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\tile\EnchantTable as TileEnchantTable;
|
||||
use pocketmine\tile\Tile;
|
||||
|
||||
class EnchantingTable extends Transparent{
|
||||
|
||||
protected $id = self::ENCHANTING_TABLE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
$nbt = new CompoundTag("", [
|
||||
new StringTag("id", Tile::ENCHANT_TABLE),
|
||||
new IntTag("x", $this->x),
|
||||
new IntTag("y", $this->y),
|
||||
new IntTag("z", $this->z)
|
||||
]);
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
|
||||
if($item->hasCustomName()){
|
||||
$nbt->CustomName = new StringTag("CustomName", $item->getCustomName());
|
||||
}
|
||||
|
||||
if($item->hasCustomBlockData()){
|
||||
foreach($item->getCustomBlockData() as $key => $v){
|
||||
$nbt->{$key} = $v;
|
||||
}
|
||||
}
|
||||
|
||||
Tile::createTile(Tile::ENCHANT_TABLE, $this->getLevel(), $nbt);
|
||||
Tile::createTile(Tile::ENCHANT_TABLE, $this->getLevel(), TileEnchantTable::createNBT($this, $face, $item, $player));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function canBeActivated(){
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 5;
|
||||
}
|
||||
|
||||
public function getResistance(){
|
||||
public function getBlastResistance() : float{
|
||||
return 6000;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Enchanting Table";
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($player instanceof Player){
|
||||
//TODO lock
|
||||
|
||||
@ -92,13 +73,11 @@ class EnchantingTable extends Transparent{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,31 +30,31 @@ class EndPortalFrame extends Solid{
|
||||
|
||||
protected $id = self::END_PORTAL_FRAME;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getLightLevel(){
|
||||
public function getLightLevel() : int{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "End Portal Frame";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public function getResistance(){
|
||||
public function getBlastResistance() : float{
|
||||
return 18000000;
|
||||
}
|
||||
|
||||
public function isBreakable(Item $item){
|
||||
public function isBreakable(Item $item) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox(){
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
|
104
src/pocketmine/block/EndRod.php
Normal file
104
src/pocketmine/block/EndRod.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?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\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class EndRod extends Flowable{
|
||||
|
||||
protected $id = Block::END_ROD;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "End Rod";
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
if($face === Vector3::SIDE_UP or $face === Vector3::SIDE_DOWN){
|
||||
$this->meta = $face;
|
||||
}else{
|
||||
$this->meta = $face ^ 0x01;
|
||||
}
|
||||
if($blockClicked instanceof EndRod and $blockClicked->getDamage() === $this->meta){
|
||||
$this->meta ^= 0x01;
|
||||
}
|
||||
|
||||
return $this->level->setBlock($blockReplace, $this, true, true);
|
||||
}
|
||||
|
||||
public function isSolid() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getLightLevel() : int{
|
||||
return 14;
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
$m = $this->meta & ~0x01;
|
||||
$width = 0.375;
|
||||
|
||||
switch($m){
|
||||
case 0x00: //up/down
|
||||
return new AxisAlignedBB(
|
||||
$this->x + $width,
|
||||
$this->y,
|
||||
$this->z + $width,
|
||||
$this->x + 1 - $width,
|
||||
$this->y + 1,
|
||||
$this->z + 1 - $width
|
||||
);
|
||||
case 0x02: //north/south
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y + $width,
|
||||
$this->z + $width,
|
||||
$this->x + 1,
|
||||
$this->y + 1 - $width,
|
||||
$this->z + 1 - $width
|
||||
);
|
||||
case 0x04: //east/west
|
||||
return new AxisAlignedBB(
|
||||
$this->x + $width,
|
||||
$this->y + $width,
|
||||
$this->z,
|
||||
$this->x + 1 - $width,
|
||||
$this->y + 1 - $width,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
@ -27,19 +29,19 @@ class EndStone extends Solid{
|
||||
|
||||
protected $id = self::END_STONE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "End Stone";
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 3;
|
||||
}
|
||||
}
|
57
src/pocketmine/block/EndStoneBricks.php
Normal file
57
src/pocketmine/block/EndStoneBricks.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?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\item\Tool;
|
||||
|
||||
class EndStoneBricks extends Solid{
|
||||
|
||||
protected $id = self::END_BRICKS;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "End Stone Bricks";
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.8;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
@ -19,45 +19,39 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\ByteTag;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\DoubleTag;
|
||||
use pocketmine\nbt\tag\FloatTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
|
||||
abstract class Fallable extends Solid{
|
||||
|
||||
public function onUpdate($type){
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() === self::AIR or ($down instanceof Liquid)){
|
||||
$fall = Entity::createEntity("FallingSand", $this->getLevel(), new CompoundTag("", [
|
||||
"Pos" => new ListTag("Pos", [
|
||||
new DoubleTag("", $this->x + 0.5),
|
||||
new DoubleTag("", $this->y),
|
||||
new DoubleTag("", $this->z + 0.5)
|
||||
]),
|
||||
"Motion" => new ListTag("Motion", [
|
||||
new DoubleTag("", 0),
|
||||
new DoubleTag("", 0),
|
||||
new DoubleTag("", 0)
|
||||
]),
|
||||
"Rotation" => new ListTag("Rotation", [
|
||||
new FloatTag("", 0),
|
||||
new FloatTag("", 0)
|
||||
]),
|
||||
"TileID" => new IntTag("TileID", $this->getId()),
|
||||
"Data" => new ByteTag("Data", $this->getDamage()),
|
||||
]));
|
||||
if($down->getId() === self::AIR or $down instanceof Liquid or $down instanceof Fire){
|
||||
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||
|
||||
$fall->spawnToAll();
|
||||
$nbt = Entity::createBaseNBT($this->add(0.5, 0, 0.5));
|
||||
$nbt->setInt("TileID", $this->getId());
|
||||
$nbt->setByte("Data", $this->getDamage());
|
||||
|
||||
$fall = Entity::createEntity("FallingSand", $this->getLevel(), $nbt);
|
||||
|
||||
if($fall !== null){
|
||||
$fall->spawnToAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|Block
|
||||
*/
|
||||
public function tickFalling() : ?Block{
|
||||
return null;
|
||||
}
|
||||
}
|
@ -19,46 +19,98 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
|
||||
class Farmland extends Solid{
|
||||
class Farmland extends Transparent{
|
||||
|
||||
protected $id = self::FARMLAND;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Farmland";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 0.6;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox(){
|
||||
public function ticksRandomly() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 0.9375,
|
||||
$this->y + 1, //TODO: this should be 0.9375, but MCPE currently treats them as a full block (https://bugs.mojang.com/browse/MCPE-12109)
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL and $this->getSide(Vector3::SIDE_UP)->isSolid()){
|
||||
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
||||
return $type;
|
||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
||||
if(!$this->canHydrate()){
|
||||
if($this->meta > 0){
|
||||
$this->meta--;
|
||||
$this->level->setBlock($this, $this, false, false);
|
||||
}else{
|
||||
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), false, true);
|
||||
}
|
||||
|
||||
return $type;
|
||||
}elseif($this->meta < 7){
|
||||
$this->meta = 7;
|
||||
$this->level->setBlock($this, $this, false, false);
|
||||
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function canHydrate() : bool{
|
||||
//TODO: check rain
|
||||
$start = $this->add(-4, 0, -4);
|
||||
$end = $this->add(4, 1, 4);
|
||||
for($y = $start->y; $y <= $end->y; ++$y){
|
||||
for($z = $start->z; $z <= $end->z; ++$z){
|
||||
for($x = $start->x; $x <= $end->x; ++$x){
|
||||
$id = $this->level->getBlockIdAt($x, $y, $z);
|
||||
if($id === Block::STILL_WATER or $id === Block::FLOWING_WATER){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
return [
|
||||
[Item::DIRT, 0, 1],
|
||||
ItemFactory::get(Item::DIRT, 0, 1)
|
||||
];
|
||||
}
|
||||
}
|
@ -19,73 +19,91 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
|
||||
class Fence extends Transparent{
|
||||
const FENCE_OAK = 0;
|
||||
const FENCE_SPRUCE = 1;
|
||||
const FENCE_BIRCH = 2;
|
||||
const FENCE_JUNGLE = 3;
|
||||
const FENCE_ACACIA = 4;
|
||||
const FENCE_DARKOAK = 5;
|
||||
abstract class Fence extends Transparent{
|
||||
|
||||
protected $id = self::FENCE;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
return 2;
|
||||
public function getThickness() : float{
|
||||
return 0.25;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
return Tool::TYPE_AXE;
|
||||
}
|
||||
|
||||
|
||||
public function getName(){
|
||||
static $names = [
|
||||
self::FENCE_OAK => "Oak Fence",
|
||||
self::FENCE_SPRUCE => "Spruce Fence",
|
||||
self::FENCE_BIRCH => "Birch Fence",
|
||||
self::FENCE_JUNGLE => "Jungle Fence",
|
||||
self::FENCE_ACACIA => "Acacia Fence",
|
||||
self::FENCE_DARKOAK => "Dark Oak Fence",
|
||||
"",
|
||||
""
|
||||
];
|
||||
return $names[$this->meta & 0x07];
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
$north = $this->canConnect($this->getSide(Vector3::SIDE_NORTH));
|
||||
$south = $this->canConnect($this->getSide(Vector3::SIDE_SOUTH));
|
||||
$west = $this->canConnect($this->getSide(Vector3::SIDE_WEST));
|
||||
$east = $this->canConnect($this->getSide(Vector3::SIDE_EAST));
|
||||
|
||||
$n = $north ? 0 : 0.375;
|
||||
$s = $south ? 1 : 0.625;
|
||||
$w = $west ? 0 : 0.375;
|
||||
$e = $east ? 1 : 0.625;
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
$width = 0.5 - $this->getThickness() / 2;
|
||||
|
||||
return new AxisAlignedBB(
|
||||
$this->x + $w,
|
||||
$this->x + ($this->canConnect($this->getSide(Vector3::SIDE_WEST)) ? 0 : $width),
|
||||
$this->y,
|
||||
$this->z + $n,
|
||||
$this->x + $e,
|
||||
$this->z + ($this->canConnect($this->getSide(Vector3::SIDE_NORTH)) ? 0 : $width),
|
||||
$this->x + 1 - ($this->canConnect($this->getSide(Vector3::SIDE_EAST)) ? 0 : $width),
|
||||
$this->y + 1.5,
|
||||
$this->z + $s
|
||||
$this->z + 1 - ($this->canConnect($this->getSide(Vector3::SIDE_SOUTH)) ? 0 : $width)
|
||||
);
|
||||
}
|
||||
|
||||
protected function recalculateCollisionBoxes() : array{
|
||||
$inset = 0.5 - $this->getThickness() / 2;
|
||||
|
||||
/** @var AxisAlignedBB[] $bbs */
|
||||
$bbs = [];
|
||||
|
||||
$connectWest = $this->canConnect($this->getSide(Vector3::SIDE_WEST));
|
||||
$connectEast = $this->canConnect($this->getSide(Vector3::SIDE_EAST));
|
||||
|
||||
if($connectWest or $connectEast){
|
||||
//X axis (west/east)
|
||||
$bbs[] = new AxisAlignedBB(
|
||||
$this->x + ($connectWest ? 0 : $inset),
|
||||
$this->y,
|
||||
$this->z + $inset,
|
||||
$this->x + 1 - ($connectEast ? 0 : $inset),
|
||||
$this->y + 1.5,
|
||||
$this->z + 1 - $inset
|
||||
);
|
||||
}
|
||||
|
||||
$connectNorth = $this->canConnect($this->getSide(Vector3::SIDE_NORTH));
|
||||
$connectSouth = $this->canConnect($this->getSide(Vector3::SIDE_SOUTH));
|
||||
|
||||
if($connectNorth or $connectSouth){
|
||||
//Z axis (north/south)
|
||||
$bbs[] = new AxisAlignedBB(
|
||||
$this->x + $inset,
|
||||
$this->y,
|
||||
$this->z + ($connectNorth ? 0 : $inset),
|
||||
$this->x + 1 - $inset,
|
||||
$this->y + 1.5,
|
||||
$this->z + 1 - ($connectSouth ? 0 : $inset)
|
||||
);
|
||||
}
|
||||
|
||||
if(empty($bbs)){
|
||||
//centre post AABB (only needed if not connected on any axis - other BBs overlapping will do this if any connections are made)
|
||||
return [
|
||||
new AxisAlignedBB(
|
||||
$this->x + $inset,
|
||||
$this->y,
|
||||
$this->z + $inset,
|
||||
$this->x + 1 - $inset,
|
||||
$this->y + 1.5,
|
||||
$this->z + 1 - $inset
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
return $bbs;
|
||||
}
|
||||
|
||||
public function canConnect(Block $block){
|
||||
return ($block instanceof Fence or $block instanceof FenceGate) ? true : $block->isSolid() and !$block->isTransparent();
|
||||
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,40 +19,29 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\level\sound\DoorSound;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class FenceGate extends Transparent{
|
||||
|
||||
protected $id = self::FENCE_GATE;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
return "Oak Fence Gate";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function canBeActivated(){
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_AXE;
|
||||
}
|
||||
|
||||
|
||||
protected function recalculateBoundingBox(){
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
|
||||
if(($this->getDamage() & 0x04) > 0){
|
||||
return null;
|
||||
@ -80,20 +69,18 @@ class FenceGate extends Transparent{
|
||||
}
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
$this->meta = ($player instanceof Player ? ($player->getDirection() - 1) & 0x03 : 0);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
$this->meta = (($this->meta ^ 0x04) & ~0x02);
|
||||
|
||||
if($player !== null){
|
||||
@ -104,4 +91,8 @@ class FenceGate extends Transparent{
|
||||
$this->level->addSound(new DoorSound($this));
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
return 300;
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class FenceGateSpruce extends FenceGate{
|
||||
|
||||
protected $id = self::FENCE_GATE_SPRUCE;
|
||||
|
||||
public function getName(){
|
||||
return "Spruce Fence Gate";
|
||||
}
|
||||
}
|
@ -19,51 +19,55 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Arrow;
|
||||
use pocketmine\entity\Effect;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\projectile\Arrow;
|
||||
use pocketmine\event\entity\EntityCombustByBlockEvent;
|
||||
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Server;
|
||||
|
||||
class Fire extends Flowable{
|
||||
|
||||
protected $id = self::FIRE;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function hasEntityCollision(){
|
||||
public function hasEntityCollision() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Fire Block";
|
||||
}
|
||||
|
||||
public function getLightLevel(){
|
||||
public function getLightLevel() : int{
|
||||
return 15;
|
||||
}
|
||||
|
||||
public function isBreakable(Item $item){
|
||||
public function isBreakable(Item $item) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function canBeReplaced(){
|
||||
public function canBeReplaced() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onEntityCollide(Entity $entity){
|
||||
if(!$entity->hasEffect(Effect::FIRE_RESISTANCE)){
|
||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, 1);
|
||||
$entity->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
public function ticksRandomly() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onEntityCollide(Entity $entity) : void{
|
||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, 1);
|
||||
$entity->attack($ev);
|
||||
|
||||
$ev = new EntityCombustByBlockEvent($this, $entity, 8);
|
||||
if($entity instanceof Arrow){
|
||||
@ -75,11 +79,11 @@ class Fire extends Flowable{
|
||||
}
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
for($s = 0; $s <= 5; ++$s){
|
||||
$side = $this->getSide($s);
|
||||
@ -87,14 +91,14 @@ class Fire extends Flowable{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$this->getLevel()->setBlock($this, new Air(), true);
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
||||
if($this->getSide(0)->getId() !== self::NETHERRACK){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::NETHERRACK){
|
||||
if(mt_rand(0, 2) === 0){
|
||||
if($this->meta === 0x0F){
|
||||
$this->level->setBlock($this, new Air());
|
||||
$this->level->setBlock($this, BlockFactory::get(Block::AIR));
|
||||
}else{
|
||||
$this->meta++;
|
||||
$this->level->setBlock($this, $this);
|
||||
@ -103,6 +107,8 @@ class Fire extends Flowable{
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: fire spread
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -19,27 +19,27 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
|
||||
abstract class Flowable extends Transparent{
|
||||
|
||||
public function canBeFlowedInto(){
|
||||
public function canBeFlowedInto() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getResistance(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function isSolid(){
|
||||
public function isSolid() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox(){
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return null;
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -39,11 +41,11 @@ class Flower extends Flowable{
|
||||
|
||||
protected $id = self::RED_FLOWER;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
static $names = [
|
||||
self::TYPE_POPPY => "Poppy",
|
||||
self::TYPE_BLUE_ORCHID => "Blue Orchid",
|
||||
@ -53,23 +55,15 @@ class Flower extends Flowable{
|
||||
self::TYPE_ORANGE_TULIP => "Orange Tulip",
|
||||
self::TYPE_WHITE_TULIP => "White Tulip",
|
||||
self::TYPE_PINK_TULIP => "Pink Tulip",
|
||||
self::TYPE_OXEYE_DAISY => "Oxeye Daisy",
|
||||
9 => "Unknown",
|
||||
10 => "Unknown",
|
||||
11 => "Unknown",
|
||||
12 => "Unknown",
|
||||
13 => "Unknown",
|
||||
14 => "Unknown",
|
||||
15 => "Unknown"
|
||||
self::TYPE_OXEYE_DAISY => "Oxeye Daisy"
|
||||
];
|
||||
return $names[$this->meta];
|
||||
return $names[$this->meta] ?? "Unknown";
|
||||
}
|
||||
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() === Block::GRASS or $down->getId() === Block::DIRT or $down->getId() === Block::FARMLAND){
|
||||
$this->getLevel()->setBlock($block, $this, true);
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -77,7 +71,7 @@ class Flower extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
|
@ -19,16 +19,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\ShortTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\tile\FlowerPot as TileFlowerPot;
|
||||
use pocketmine\tile\Tile;
|
||||
@ -39,20 +37,17 @@ class FlowerPot extends Flowable{
|
||||
const STATE_FULL = 1;
|
||||
|
||||
protected $id = self::FLOWER_POT_BLOCK;
|
||||
protected $itemId = Item::FLOWER_POT;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
return "Flower Pot Block";
|
||||
public function getName() : string{
|
||||
return "Flower Pot";
|
||||
}
|
||||
|
||||
public function canBeActivated(): bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox(){
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return new AxisAlignedBB(
|
||||
$this->x + 0.3125,
|
||||
$this->y,
|
||||
@ -63,35 +58,19 @@ class FlowerPot extends Flowable{
|
||||
);
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
$nbt = new CompoundTag("", [
|
||||
new StringTag("id", Tile::FLOWER_POT),
|
||||
new IntTag("x", $block->x),
|
||||
new IntTag("y", $block->y),
|
||||
new IntTag("z", $block->z),
|
||||
new ShortTag("item", 0),
|
||||
new IntTag("mData", 0),
|
||||
]);
|
||||
|
||||
if($item->hasCustomBlockData()){
|
||||
foreach($item->getCustomBlockData() as $key => $v){
|
||||
$nbt->{$key} = $v;
|
||||
}
|
||||
}
|
||||
|
||||
Tile::createTile(Tile::FLOWER_POT, $this->getLevel(), $nbt);
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
Tile::createTile(Tile::FLOWER_POT, $this->getLevel(), TileFlowerPot::createNBT($this, $face, $item, $player));
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(0)->isTransparent() === true){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
@ -101,7 +80,7 @@ class FlowerPot extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
$pot = $this->getLevel()->getTile($this);
|
||||
if(!($pot instanceof TileFlowerPot)){
|
||||
return false;
|
||||
@ -112,25 +91,22 @@ class FlowerPot extends Flowable{
|
||||
|
||||
$this->setDamage(self::STATE_FULL); //specific damage value is unnecessary, it just needs to be non-zero to show an item.
|
||||
$this->getLevel()->setBlock($this, $this, true, false);
|
||||
$pot->setItem($item);
|
||||
$pot->setItem($item->pop());
|
||||
|
||||
if($player instanceof Player){
|
||||
if($player->isSurvival()){
|
||||
$item->setCount($item->getCount() - 1);
|
||||
$player->getInventory()->setItemInHand($item->getCount() > 0 ? $item : Item::get(Item::AIR));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
$items = [[Item::FLOWER_POT, 0, 1]];
|
||||
public function getDrops(Item $item) : array{
|
||||
$items = parent::getDrops($item);
|
||||
|
||||
$tile = $this->getLevel()->getTile($this);
|
||||
if($tile instanceof TileFlowerPot){
|
||||
if(($item = $tile->getItem())->getId() !== Item::AIR){
|
||||
$items[] = [$item->getId(), $item->getDamage(), 1];
|
||||
$item = $tile->getItem();
|
||||
if($item->getId() !== Item::AIR){
|
||||
$items[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
@ -26,11 +28,11 @@ class Furnace extends BurningFurnace{
|
||||
|
||||
protected $id = self::FURNACE;
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Furnace";
|
||||
}
|
||||
|
||||
public function getLightLevel(){
|
||||
public function getLightLevel() : int{
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -27,19 +29,19 @@ class Glass extends Transparent{
|
||||
|
||||
protected $id = self::GLASS;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Glass";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 0.3;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
return [];
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -27,19 +29,19 @@ class GlassPane extends Thin{
|
||||
|
||||
protected $id = self::GLASS_PANE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Glass Pane";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 0.3;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
return [];
|
||||
}
|
||||
}
|
67
src/pocketmine/block/GlazedTerracotta.php
Normal file
67
src/pocketmine/block/GlazedTerracotta.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?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\item\Tool;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class GlazedTerracotta extends Solid{
|
||||
|
||||
public function getHardness() : float{
|
||||
return 1.4;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
if($player !== null){
|
||||
$faces = [
|
||||
0 => 4,
|
||||
1 => 3,
|
||||
2 => 5,
|
||||
3 => 2
|
||||
];
|
||||
$this->meta = $faces[(~($player->getDirection() - 1)) & 0x03];
|
||||
}
|
||||
|
||||
return $this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
@ -26,16 +28,23 @@ class GlowingObsidian extends Solid{
|
||||
|
||||
protected $id = self::GLOWING_OBSIDIAN;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Glowing Obsidian";
|
||||
}
|
||||
|
||||
public function getLightLevel(){
|
||||
public function getLightLevel() : int{
|
||||
return 12;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 10;
|
||||
}
|
||||
|
||||
public function getBlastResistance() : float{
|
||||
return 50;
|
||||
}
|
||||
}
|
@ -19,26 +19,27 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
|
||||
class GlowingRedstoneOre extends RedstoneOre{
|
||||
|
||||
protected $id = self::GLOWING_REDSTONE_ORE;
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Glowing Redstone Ore";
|
||||
}
|
||||
|
||||
public function getLightLevel(){
|
||||
public function getLightLevel() : int{
|
||||
return 9;
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_SCHEDULED or $type === Level::BLOCK_UPDATE_RANDOM){
|
||||
$this->getLevel()->setBlock($this, Block::get(Item::REDSTONE_ORE, $this->meta), false, false);
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::REDSTONE_ORE, $this->meta), false, false);
|
||||
|
||||
return Level::BLOCK_UPDATE_WEAK;
|
||||
}
|
||||
|
@ -19,38 +19,41 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
|
||||
class Glowstone extends Transparent{
|
||||
|
||||
protected $id = self::GLOWSTONE_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
protected $id = self::GLOWSTONE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Glowstone";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 0.3;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getLightLevel(){
|
||||
public function getLightLevel() : int{
|
||||
return 15;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
return [
|
||||
[Item::GLOWSTONE_DUST, 0, mt_rand(2, 4)],
|
||||
ItemFactory::get(Item::GLOWSTONE_DUST, 0, mt_rand(2, 4))
|
||||
];
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,29 +30,27 @@ class Gold extends Solid{
|
||||
|
||||
protected $id = self::GOLD_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Gold Block";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 3;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
||||
return [
|
||||
[Item::GOLD_BLOCK, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,29 +30,27 @@ class GoldOre extends Solid{
|
||||
|
||||
protected $id = self::GOLD_ORE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Gold Ore";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 3;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
||||
return [
|
||||
[Item::GOLD_ORE, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
@ -19,71 +19,90 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\event\block\BlockSpreadEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\level\generator\object\TallGrass as TallGrassObject;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
class Grass extends Solid{
|
||||
|
||||
protected $id = self::GRASS;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function canBeActivated(){
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Grass";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 0.6;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
return [
|
||||
[Item::DIRT, 0, 1],
|
||||
ItemFactory::get(Item::DIRT, 0, 1)
|
||||
];
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
if($type === Level::BLOCK_UPDATE_RANDOM){
|
||||
$block = $this->getLevel()->getBlock(new Vector3($this->x, $this->y, $this->z));
|
||||
if($block->getSide(1)->getLightLevel() < 4){
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($block, $this, new Dirt()));
|
||||
}elseif($block->getSide(1)->getLightLevel() >= 9){
|
||||
for($l = 0; $l < 4; ++$l){
|
||||
$x = mt_rand($this->x - 1, $this->x + 1);
|
||||
$y = mt_rand($this->y - 2, $this->y + 2);
|
||||
$z = mt_rand($this->z - 1, $this->z + 1);
|
||||
$block = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
|
||||
if($block->getId() === Block::DIRT && $block->getDamage() === 0x0F && $block->getSide(1)->getLightLevel() >= 4 && $block->z <= 2){
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($block, $this, new Grass()));
|
||||
if(!$ev->isCancelled()){
|
||||
$this->getLevel()->setBlock($block, $ev->getNewState());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public function ticksRandomly() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_RANDOM){
|
||||
$lightAbove = $this->level->getFullLightAt($this->x, $this->y + 1, $this->z);
|
||||
if($lightAbove < 4 and BlockFactory::$lightFilter[$this->level->getBlockIdAt($this->x, $this->y + 1, $this->z)] >= 3){ //2 plus 1 standard filter amount
|
||||
//grass dies
|
||||
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($this, $this, BlockFactory::get(Block::DIRT)));
|
||||
if(!$ev->isCancelled()){
|
||||
$this->level->setBlock($this, $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{
|
||||
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){
|
||||
$item->count--;
|
||||
TallGrassObject::growGrass($this->getLevel(), $this, new Random(mt_rand()), 8, 2);
|
||||
@ -91,12 +110,12 @@ class Grass extends Solid{
|
||||
return true;
|
||||
}elseif($item->isHoe()){
|
||||
$item->useOn($this);
|
||||
$this->getLevel()->setBlock($this, new Farmland());
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND));
|
||||
|
||||
return true;
|
||||
}elseif($item->isShovel() and $this->getSide(1)->getId() === Block::AIR){
|
||||
}elseif($item->isShovel() and $this->getSide(Vector3::SIDE_UP)->getId() === Block::AIR){
|
||||
$item->useOn($this);
|
||||
$this->getLevel()->setBlock($this, new GrassPath());
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::GRASS_PATH));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -19,46 +19,60 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
|
||||
class GrassPath extends Transparent{
|
||||
|
||||
protected $id = self::GRASS_PATH;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Grass Path";
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox(){
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 0.9375,
|
||||
$this->y + 1, //TODO: this should be 0.9375, but MCPE currently treats them as a full block (https://bugs.mojang.com/browse/MCPE-12109)
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 0.6;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function onUpdate(int $type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL and $this->getSide(Vector3::SIDE_UP)->isSolid()){
|
||||
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
||||
return $type;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
return [
|
||||
[Item::DIRT, 0, 1],
|
||||
ItemFactory::get(Item::DIRT, 0, 1)
|
||||
];
|
||||
}
|
||||
}
|
@ -19,41 +19,42 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\Tool;
|
||||
|
||||
class Gravel extends Fallable{
|
||||
|
||||
protected $id = self::GRAVEL;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Gravel";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 0.6;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_SHOVEL;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
public function getDrops(Item $item) : array{
|
||||
if(mt_rand(1, 10) === 1){
|
||||
return [
|
||||
[Item::FLINT, 0, 1],
|
||||
ItemFactory::get(Item::FLINT, 0, 1)
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
[Item::GRAVEL, 0, 1],
|
||||
];
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
@ -27,19 +29,19 @@ class HardenedClay extends Solid{
|
||||
|
||||
protected $id = self::HARDENED_CLAY;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Hardened Clay";
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
public function getToolType() : int{
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 1.25;
|
||||
}
|
||||
}
|
@ -19,47 +19,39 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\PillarRotationHelper;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class HayBale extends Solid{
|
||||
|
||||
protected $id = self::HAY_BALE;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
public function __construct(int $meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
public function getName() : string{
|
||||
return "Hay Bale";
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
public function getHardness() : float{
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$faces = [
|
||||
0 => 0,
|
||||
1 => 0,
|
||||
2 => 0b1000,
|
||||
3 => 0b1000,
|
||||
4 => 0b0100,
|
||||
5 => 0b0100,
|
||||
];
|
||||
|
||||
$this->meta = ($this->meta & 0x03) | $faces[$face];
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
$this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face);
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
public function getVariantBitmask() : int{
|
||||
return 0x03;
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user