mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-15 13:55:12 +00:00
Compare commits
611 Commits
1.7dev-501
...
1.7dev-100
Author | SHA1 | Date | |
---|---|---|---|
8c1c8f34cc | |||
2034caf71c | |||
89ccac7a8c | |||
f6e71d8296 | |||
b333a0e24c | |||
5b6762d0d5 | |||
68638f9779 | |||
8228774ad4 | |||
2a54726905 | |||
8b225fc4ef | |||
a014b44b69 | |||
c7544c1d25 | |||
eb28622823 | |||
68494f1c0d | |||
27ea0d360f | |||
d384df1f2e | |||
fe8102c062 | |||
8b15d85469 | |||
a5ba716232 | |||
db432bb024 | |||
91486a23a5 | |||
c276ef2b7f | |||
5138bdc4bd | |||
a30a157d8c | |||
e565cdeea4 | |||
556a465c05 | |||
280f2b7259 | |||
933b0e8b41 | |||
58279d4cfe | |||
1e21066c1c | |||
76854da7ba | |||
46cbcb0c42 | |||
af9b0b019d | |||
7db8845375 | |||
f47f593555 | |||
691df5c11d | |||
9a1d3aec6b | |||
670a53ba3b | |||
f22ad14c67 | |||
64540f36be | |||
e66b1953de | |||
aa6666872a | |||
646455f6e8 | |||
05a1e61e5b | |||
5f52e00213 | |||
476ac39988 | |||
5f1ae1059e | |||
08d8adae5b | |||
8d988af7db | |||
db5890fddb | |||
5b532fdcf5 | |||
e85fc54037 | |||
7fb237938c | |||
9a5f9c8586 | |||
4b16be7e0b | |||
47faf5a994 | |||
3f31f6d310 | |||
c06c1c7ce0 | |||
a889a0e517 | |||
9ed0d9d36f | |||
3134fa2744 | |||
2660448601 | |||
eb354916d4 | |||
033b44df5a | |||
ef2dd1de92 | |||
5b7b2dd0e2 | |||
3a10df634b | |||
f1aecc3a71 | |||
42d04a4418 | |||
3fe4ebc301 | |||
d97abfaa7b | |||
526f05631e | |||
ebaef89e06 | |||
6ab0cff9d3 | |||
ae31ce1d25 | |||
a1cf5dbd1e | |||
c86132028e | |||
5ce55bd3b0 | |||
c81f178cdb | |||
fc795b80ae | |||
99134de6b6 | |||
1fc388d6de | |||
eba1ca030c | |||
8ce0fab8cc | |||
5ed2d6022c | |||
37d085f793 | |||
69c54de460 | |||
b9d3bd22a3 | |||
d4d57aa9ea | |||
4ce1f228e6 | |||
4b03dbebba | |||
1d5978df98 | |||
5d32587cf7 | |||
d53258c943 | |||
773f760fff | |||
c20b16a0fe | |||
b151cb26a5 | |||
49622cc2a5 | |||
56328f66a7 | |||
f41a731493 | |||
ec332e3e60 | |||
a1090623a2 | |||
8572e9e560 | |||
bc836aaec1 | |||
145a4fad0f | |||
08c48d8145 | |||
81ecb56095 | |||
a6d7365a28 | |||
1f4f8ab3f0 | |||
1420cd1fa5 | |||
30a83544a0 | |||
7e20385bdb | |||
c7e803372c | |||
cf3638ad8d | |||
0dd8fd2651 | |||
c0c684b12e | |||
924334a776 | |||
be7c27f60d | |||
2b37b4a659 | |||
a4c50d3204 | |||
eb9f60f41c | |||
071aa44d29 | |||
25089f5e70 | |||
22dd8faf1d | |||
7354a55af8 | |||
611f5d684b | |||
9a099d3f5d | |||
5eb1ee3416 | |||
e4b6a18404 | |||
364d278714 | |||
c464d39401 | |||
a185b78486 | |||
c19cf22ac5 | |||
d2fb32c28a | |||
49fbbea7bf | |||
1648fff916 | |||
73e09392b6 | |||
209e28dfe5 | |||
ac5a91b67e | |||
24c5d7557e | |||
3d89bf5693 | |||
e48ec9fb71 | |||
95606b6e04 | |||
c243daabe1 | |||
357674cb54 | |||
9d5eeb328e | |||
b2ee6b2ca5 | |||
2860e9e8ee | |||
e82073834f | |||
7fcc538a75 | |||
7f6b8ad7c2 | |||
313b224bec | |||
d12b1d3e07 | |||
eeeef8df51 | |||
9c786089f8 | |||
e3cae7364f | |||
d542bbc736 | |||
e88541b269 | |||
fdad965db8 | |||
dd844f7ad3 | |||
596c8a7b4f | |||
9c598d1345 | |||
a2af838b1d | |||
bf97eab98f | |||
a9a55e9558 | |||
95fb1d1602 | |||
fa644edef3 | |||
ddc9dca8b4 | |||
86eee429bb | |||
4f20a504e3 | |||
6a1f8640f6 | |||
8a0414f306 | |||
d478661961 | |||
b8064aa45c | |||
00f596c4f8 | |||
3f7b14bf59 | |||
ba0a256834 | |||
f2f8c235e7 | |||
69b3bb183d | |||
cd35bd6872 | |||
d09a43cfef | |||
40b995a435 | |||
590826b9bd | |||
a5e87484d9 | |||
8a86e0825b | |||
b39bbffdc5 | |||
bd3d2451bc | |||
606407933e | |||
ad09e8c8d0 | |||
486edf0e55 | |||
2ee01eb195 | |||
9098502199 | |||
b130374e46 | |||
31106bc227 | |||
cc1a3d695f | |||
8020780fc5 | |||
2f266a5922 | |||
3827892e48 | |||
e06b78b0ee | |||
74cff89df3 | |||
a9957c3db3 | |||
2e9bf7e93b | |||
dbcc69c2de | |||
cdd3fe81e1 | |||
a8a3eb3866 | |||
83a3c6f614 | |||
8cc6a32a04 | |||
c1a2144f60 | |||
b2491a5874 | |||
2e125168c3 | |||
5059a92b91 | |||
ea5db98d12 | |||
1f77c074e9 | |||
73a5788774 | |||
dc3bf8546e | |||
c7f8796136 | |||
c5336776a5 | |||
b623c4aba1 | |||
49a39fc7bd | |||
2e4519cb36 | |||
2ff3b12376 | |||
9e4bccd8c0 | |||
1c5180b720 | |||
fa6d44ea9e | |||
9d018e8d9e | |||
ae2e1fdd5a | |||
97bfcf6e71 | |||
5457c7a202 | |||
ee28296d60 | |||
06af742bef | |||
6bdf5e15c0 | |||
d4eba3f4b1 | |||
5a89e80873 | |||
28e601bbb9 | |||
7e9f1324a7 | |||
973d5dc251 | |||
533d139385 | |||
6a94c8183c | |||
629a254639 | |||
732b931556 | |||
2dd1878d57 | |||
3104a312b2 | |||
d6d47feda9 | |||
0ba1b58ee0 | |||
ab2df8b11b | |||
eb01dcaf60 | |||
f0535df96d | |||
f903dbfe00 | |||
e0d5c79848 | |||
e024f381c9 | |||
2a09aaf456 | |||
0ad8ea6e92 | |||
bd47852ca4 | |||
2b036b1a5c | |||
e5ec8fa603 | |||
abe5d94d5b | |||
da5febc34a | |||
3de5e132a2 | |||
37e8c8d324 | |||
aa11dbb928 | |||
e7adaef2d2 | |||
6bf9ae0a18 | |||
e7b2dc87d6 | |||
d7a02793fa | |||
6a996611f8 | |||
ad8d67137e | |||
cbbed6a6c1 | |||
99ef3e6576 | |||
eeaf75ac85 | |||
6954bfac4b | |||
f27b62027c | |||
093cb5b39e | |||
3f41628bf3 | |||
a3fa8adf4a | |||
08daf655e5 | |||
61fc090cf2 | |||
ecd830463c | |||
ffe89f5e1b | |||
88a05845c2 | |||
2cabdca3f7 | |||
be1ddb9f5b | |||
7fc3eeab00 | |||
9395dbf9fa | |||
a7396d7ae9 | |||
3b632c2870 | |||
7dd834bca0 | |||
2b6e135c83 | |||
c26e3aa9fa | |||
aeba15c5c6 | |||
4c583ec8ab | |||
af2435f199 | |||
456987e212 | |||
8e6ec04abc | |||
42a7b7fa36 | |||
ce4e0bf69c | |||
dc84484c2b | |||
e7e4645c0b | |||
4e9e285e37 | |||
3962d32ffe | |||
a84aba5517 | |||
0b82d5c8d4 | |||
3aef4c5a09 | |||
6307952ae9 | |||
cacd0f5d8f | |||
f66928c345 | |||
9abfd54cc1 | |||
4a85311c5f | |||
8a4f6eb6c2 | |||
6e7a693355 | |||
b7bd8dc7f1 | |||
b445825467 | |||
98d6aea7fe | |||
b75d121c7e | |||
88bbb03f12 | |||
9478bc281f | |||
7ec886faa2 | |||
610e62e2cd | |||
906442136b | |||
3600542d78 | |||
3b36d46a8f | |||
63fa6a36a9 | |||
e0ed877494 | |||
bab2daf711 | |||
5858025d90 | |||
dbac2abafb | |||
266d1cb935 | |||
ffbb44673f | |||
a84a8ecc14 | |||
687886e70b | |||
bad323f5cc | |||
ca9f700fb0 | |||
c51cc6b2fe | |||
03c66f0f86 | |||
610b041631 | |||
75289b1498 | |||
4eea54780a | |||
e860d32b3a | |||
c4486d9ad7 | |||
8222b16d9a | |||
dcb53b1cbb | |||
a52a2f6d26 | |||
906d7eb176 | |||
bf3f5532ac | |||
07bf1c9e22 | |||
b659a3d39f | |||
68b30108be | |||
f223fb2876 | |||
8bb785b7af | |||
806a2005d7 | |||
c794ced0ad | |||
f993358c5f | |||
1c12be6bf2 | |||
a1d9b8486e | |||
9397356ce4 | |||
e56e363dcc | |||
18b287c3ea | |||
9014eb72e9 | |||
82948726ed | |||
c601816586 | |||
54f7a88fbb | |||
d2d1df0447 | |||
f9b1afe4cf | |||
033cb8bd63 | |||
0ed9fcb641 | |||
efac23d4af | |||
48dc1c38f7 | |||
ffb3e2b47a | |||
ef816c0a52 | |||
3e35bc38e2 | |||
de0741f727 | |||
6fd4b9f1e2 | |||
6c8a1a5b80 | |||
3842ee15cf | |||
6c71b443e8 | |||
4a4900e5e7 | |||
26d4169fea | |||
7d88a8b315 | |||
41592a04b7 | |||
1d4bafb6ff | |||
28996f561f | |||
0658c0851b | |||
0df2064802 | |||
6543d96910 | |||
0bf5ab76fb | |||
8e1394bf53 | |||
6ddbdc9dc1 | |||
2a8be527d7 | |||
aca1422fca | |||
b0d0932ed9 | |||
fd5557861b | |||
1de7c5b114 | |||
2fb580db26 | |||
e5ca22a9a6 | |||
69ddaacc28 | |||
897a31e608 | |||
4943ff9dfc | |||
e36b38939c | |||
ecb3f9aeac | |||
f0696f77ef | |||
6813838754 | |||
65fe19ca71 | |||
a4f5cab12d | |||
29e06e30b2 | |||
3939e2d9dd | |||
2579438b84 | |||
95d42b9907 | |||
2eb6e075ae | |||
8f928915d9 | |||
3af8cf48b2 | |||
21c03670b6 | |||
0c868b16b6 | |||
1e67360048 | |||
3520dafd29 | |||
857b63ba8f | |||
9551e5b8e5 | |||
c7f15a556d | |||
efca9f0450 | |||
d728154e87 | |||
2e1a167bed | |||
6f6e3aaa21 | |||
9c65a2b890 | |||
beb5bf6dda | |||
7a5e5773b7 | |||
f1b0a4f1de | |||
751345c736 | |||
e850f34d76 | |||
8d7c65585c | |||
96f6362117 | |||
66c768d453 | |||
6fe7763db9 | |||
fda97decaa | |||
b3f44562e9 | |||
51350be190 | |||
7f4b5d282e | |||
94feecd44b | |||
45b02d92d4 | |||
fe4b5498e6 | |||
98b36fd73e | |||
07c7048433 | |||
f09cf92197 | |||
98eba11da5 | |||
a6c1e02847 | |||
b04cee12ea | |||
c4966404bb | |||
579c508761 | |||
43959bccb1 | |||
e6bd12dc2f | |||
7daca754b1 | |||
cb90e30bcf | |||
71d11c73f0 | |||
24116ba846 | |||
a0683dbb0f | |||
b6811b643c | |||
4d2549b50a | |||
1fb3274f37 | |||
6772a69c55 | |||
266a253c03 | |||
c62e1abf2f | |||
55f405f5c2 | |||
8fbd0e58f0 | |||
418d099a2e | |||
9d2eb5e911 | |||
b6c1124d50 | |||
03fda936a8 | |||
684fd46d09 | |||
90fc649441 | |||
0410df77aa | |||
0f30467f62 | |||
a84910f04c | |||
3ee225caec | |||
f963dbd10d | |||
debfbf0d93 | |||
5c37d298a6 | |||
3ca162f23f | |||
5f48433c95 | |||
33352638a9 | |||
db52501462 | |||
3a0cbd1cd4 | |||
1bdb68b7da | |||
6ce728169e | |||
06a3c7c478 | |||
70982c145b | |||
417f2d8998 | |||
7339c4ac2f | |||
43a0ede9d2 | |||
c747c7d025 | |||
c9e2e8980f | |||
9a956692de | |||
d30a6b60b7 | |||
41873bb115 | |||
8064152777 | |||
872df446bd | |||
376a615634 | |||
c16c9efdf3 | |||
c3cc6f9880 | |||
1e139743b8 | |||
bde0ba1100 | |||
50f273c041 | |||
db095f9705 | |||
f580f27ec7 | |||
a46029c0f6 | |||
1a615591e2 | |||
d19683b7dd | |||
f17b3b2a3b | |||
a0a2ea01bc | |||
5132ab6cd9 | |||
256bdf2581 | |||
8a3f8b4706 | |||
7264ce43ae | |||
66e475cbb8 | |||
1e896efff9 | |||
4db7a7e57f | |||
54b23968e7 | |||
bcb080e2b9 | |||
e5c58f9b04 | |||
af7aef70db | |||
3ea72a0bf9 | |||
be02fbb352 | |||
a67f7e3930 | |||
965c19375f | |||
63edcb8934 | |||
e7a012d69a | |||
99c55ac889 | |||
f14adf5827 | |||
c64b9ad63a | |||
dda71b06ae | |||
3c4dca7fdb | |||
ddbc5cf960 | |||
1edf69892a | |||
f10c2a2df2 | |||
3bbdc5ab5b | |||
082e3404c3 | |||
547833ae23 | |||
6e1df36188 | |||
329fe7d844 | |||
b7aaf54a6f | |||
6332814a04 | |||
9d4818d360 | |||
36f3accf4b | |||
8d08840ea4 | |||
7f0d0c9d63 | |||
bf55f03a3e | |||
a5c3fbdd7a | |||
a8bf2191b9 | |||
0688a86f57 | |||
2e11e448dd | |||
8bf275cb8b | |||
1896576a24 | |||
8f811c29d7 | |||
3a4f79629c | |||
375243860e | |||
a842a5319f | |||
c2b0f6af22 | |||
6490d99ac2 | |||
e0b063ac85 | |||
12ac2f4ac7 | |||
cc1951c7ba | |||
0e538ee51d | |||
1b4b832c8c | |||
4f8e4f0522 | |||
0ee78d2416 | |||
4c46087ffc | |||
bb3e72ea4b | |||
914e4c9a72 | |||
9fd7312629 | |||
24387d1efe | |||
3853938ef3 | |||
4ec8416f9a | |||
8aff793a4f | |||
d93ded9047 | |||
fbd04b0fe7 | |||
953f45c50f | |||
1822abc862 | |||
92e966686e | |||
3f50f88e2c | |||
532600ab67 | |||
78f8fe602c | |||
e75fbd7fb4 | |||
06f605879a | |||
4c7038f941 | |||
4bd4d42b82 | |||
f5ebfc3418 | |||
4ae278686c | |||
740786c99e | |||
6abf880e44 | |||
853411fa4f | |||
6e30d23254 | |||
717b36a983 | |||
90eed14cd6 | |||
4452e6ac93 | |||
56f1a6ba37 | |||
8c47a338df | |||
7c6535283e | |||
c669819bbb | |||
50f3231629 | |||
015cde2169 | |||
b9b50dd5dc | |||
da3640357c | |||
0004e7429f | |||
e2e6b7516a | |||
b903161a5d | |||
99fe63b2a3 | |||
dbc180315e | |||
45983acc0d | |||
a02af1053f | |||
7de88b9040 | |||
58327d0514 | |||
db31d13f96 | |||
55d0684565 | |||
7e3cd24444 | |||
2088a43c56 |
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
@ -28,7 +28,7 @@ NO support whatsoever will be provided for third-party modified variants of Pock
|
|||||||
|
|
||||||
Note that 32-bit platforms are no longer supported by PocketMine-MP and issues concerning 32-bit platforms will be closed.
|
Note that 32-bit platforms are no longer supported by PocketMine-MP and issues concerning 32-bit platforms will be closed.
|
||||||
-->
|
-->
|
||||||
* PocketMine-MP:
|
* PocketMine-MP: <!-- LATEST IS NOT A VALID VERSION -->
|
||||||
* PHP:
|
* PHP:
|
||||||
* Server OS:
|
* Server OS:
|
||||||
* Game version: PE/Win10 (delete as appropriate)
|
* Game version: PE/Win10 (delete as appropriate)
|
||||||
|
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -33,4 +33,8 @@ Requires translations:
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
<!-- Attach scripts or actions to test this pull request, as well as the result -->
|
<!--
|
||||||
|
Details should be provided of tests done. Simply saying "tested" or equivalent is not acceptable.
|
||||||
|
|
||||||
|
Attach scripts or actions to test this pull request, as well as the result
|
||||||
|
-->
|
||||||
|
12
.github/support.yml
vendored
Normal file
12
.github/support.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Configuration for support-requests - https://github.com/dessant/support-requests
|
||||||
|
|
||||||
|
# Label used to mark issues as support requests
|
||||||
|
supportLabel: "Support request"
|
||||||
|
# Comment to post on issues marked as support requests. Add a link
|
||||||
|
# to a support page, or set to `false` to disable
|
||||||
|
supportComment: >
|
||||||
|
This issue tracker is not a support forum. Please use the [forums](https://forums.pmmp.io) for support.
|
||||||
|
# Whether to close issues marked as support requests
|
||||||
|
close: true
|
||||||
|
# Whether to lock issues marked as support requests
|
||||||
|
lock: false
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,14 +1,15 @@
|
|||||||
players/*
|
players/*
|
||||||
worlds/*
|
worlds/*
|
||||||
plugins/*
|
plugins/*
|
||||||
bin/*
|
bin*/*
|
||||||
timings/*
|
timings/*
|
||||||
|
crashdumps/*
|
||||||
*.log
|
*.log
|
||||||
*.txt
|
*.txt
|
||||||
*.phar
|
*.phar
|
||||||
server.properties
|
server.properties
|
||||||
/pocketmine.yml
|
/pocketmine.yml
|
||||||
memoryDump_*/*
|
memory_dumps/*
|
||||||
resource_packs/
|
resource_packs/
|
||||||
|
|
||||||
# Common IDEs
|
# Common IDEs
|
||||||
|
@ -8,7 +8,7 @@ before_script:
|
|||||||
- echo | pecl install channel://pecl.php.net/yaml-2.0.2
|
- echo | pecl install channel://pecl.php.net/yaml-2.0.2
|
||||||
- git clone https://github.com/krakjoe/pthreads.git
|
- git clone https://github.com/krakjoe/pthreads.git
|
||||||
- cd pthreads
|
- cd pthreads
|
||||||
- git checkout 6c6b15138c923b69cfa46ee05fc2dd45da587287
|
- git checkout d32079fb4a88e6e008104d36dbbf0c2dd7deb403
|
||||||
- phpize
|
- phpize
|
||||||
- ./configure
|
- ./configure
|
||||||
- make
|
- make
|
||||||
|
@ -5,58 +5,48 @@
|
|||||||
|
|
||||||
## Creating an Issue
|
## Creating an Issue
|
||||||
- If you are reporting a bug:
|
- If you are reporting a bug:
|
||||||
- **make sure that you are using the latest supported version** before opening an issue.
|
- **make sure that you are using the latest supported version** before opening an issue.
|
||||||
- **test it on a clean test server, WITHOUT PLUGINS**, to see if the issue still occurs. If not then it may be a plugin issue. Please also indicate the result of such tests.
|
- **test it on a clean test server, WITHOUT PLUGINS**, to see if the issue still occurs. If not then it may be a plugin issue. Please also indicate the result of such tests.
|
||||||
|
- **[Search the issue tracker](https://github.com/pmmp/PocketMine-MP/issues?utf8=%E2%9C%93&q=is%3Aissue)** to check if anyone has already reported it, to avoid needlessly creating duplicate issues. Make sure you also check closed issues, as an issue you think is valid may already have been resolved.
|
||||||
- [Search the issue tracker](https://github.com/pmmp/PocketMine-MP/issues?utf8=%E2%9C%93&q=is%3Aissue) to check if anyone has already reported it, to avoid needlessly creating duplicate issues. Make sure you also check closed issues, as an issue you think is valid may already have been resolved.
|
- **Do not report plugin issues here.** If your issue is related to a plugin, contact the plugin's original author instead.
|
||||||
|
|
||||||
- If your issue is related to a plugin, **do not report here, contact the plugin's original author** instead.
|
|
||||||
|
|
||||||
- **Support requests are not bugs.** Issues such as "How do I do this" are not bugs and will be closed. If you need help, please see [here](README.md#discussion) and do not misuse our issue tracker.
|
- **Support requests are not bugs.** Issues such as "How do I do this" are not bugs and will be closed. If you need help, please see [here](README.md#discussion) and do not misuse our issue tracker.
|
||||||
|
|
||||||
- **No generic titles** such as "Question", "Help", "Crash Report" etc. A good issue report provides a quick summary in the title. If you just got a crash report but you don't understand it, please look for a line starting with `Message`. It summarizes the bug.
|
- **No generic titles** such as "Question", "Help", "Crash Report" etc. A good issue report provides a quick summary in the title. If you just got a crash report but you don't understand it, please look for a line starting with `Message`. It summarizes the bug.
|
||||||
|
- **Provide information in the issue body, not in the title.** No tags like `[BUG]` are allowed in the title, including `[SOLVED]` for solved issues.
|
||||||
- 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.
|
- **No generic issue reports.** For bugs, it is the issue author's responsibility to provide us an issue that is **trackable, debuggable, reproducible, reported professionally and is an actual bug**.
|
||||||
|
<br>Valid issue reports must include instructions how to reproduce the issue or a crashdump/backtrace (unless the cause of the issue is obvious).
|
||||||
- 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>**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>Valid issue reports must include instructions how to reproduce the issue or a crashdump/backtrace (unless the cause of the issue is obvious).
|
<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.
|
||||||
<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.
|
- To express appreciation, objection, confusion or other supported reactions on pull requests, issues or comments on them, use GitHub [reactions](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments) rather than posting an individual comment with an emoji only. This helps keeping the issue/pull request conversation clean and readable.
|
||||||
|
|
||||||
- If your issue is related to the PocketMine-MP website, forums, etc., please [talk to a human directly](README.md#discussion).
|
- If your issue is related to the PocketMine-MP website, forums, etc., please [talk to a human directly](README.md#discussion).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Contributing Code
|
## Contributing
|
||||||
- To contribute code to the repository, [fork it on GitHub](https://github.com/pmmp/PocketMine-MP/fork), create a branch on your fork, and make your changes on your fork. You can then make a [pull request](https://github.com/pmmp/PocketMine-MP/pull/new) to the project to compare your branch to ours and propose your changes to our repository. We use the Pull Request system to allow members of the team to review changes before they are merged.
|
To contribute to the repository, [fork it on GitHub](https://github.com/pmmp/PocketMine-MP/fork), create a branch on your fork, and make your changes on your fork. You can then make a [pull request](https://github.com/pmmp/PocketMine-MP/pull/new) to the project to compare your branch to ours and propose your changes to our repository. We use the Pull Request system to allow members of the team to review changes before they are merged.
|
||||||
|
|
||||||
- By proposing a pull request to the project, you agree to your code being distributed within PocketMine-MP under the [LGPL license](LICENSE).
|
### Licensing
|
||||||
|
By proposing a pull request to the project, you agree to your code being distributed within PocketMine-MP under the [LGPL license](LICENSE).
|
||||||
|
|
||||||
- At PocketMine, **we enforce a very high standard for contributions**. This is because PocketMine-MP and its related projects are used very widely in production. While this might seem like we are being mean at times, **our priority is what is best for PocketMine-MP itself**. We try to ensure that our project's codebase is as clean as possible and ensure that only top-quality material makes it through to PocketMine-MP itself. **If a contribution does not live up to our standards, changes may be requested or the pull request may be closed.**
|
### Contribution standards
|
||||||
|
- **We enforce a very high standard for contributions**. This is because PocketMine-MP and its related projects are used very widely in production. While this might seem like we are being mean at times, **our priority is what is best for PocketMine-MP itself**.
|
||||||
- **Your pull request will be checked and discussed in due time.** Since the team is scattered all around the world, your PR may not receive any attention for some time.
|
We try to ensure that our project's codebase is as clean as possible and ensure that only top-quality material makes it through to PocketMine-MP itself.
|
||||||
|
- **If a contribution does not meet our standards, changes may be requested or the pull request may be closed.**
|
||||||
- **Avoid using GitHub Web Editor**. The web editor lacks most useful GIT features and **should only be used for very minor changes**. It is immediately clear if the web editor has been used, and if so the PR is more likely to be rejected. If you want to make serious contributions, **please learn how to use [GIT version control](https://git-scm.com/)**.
|
|
||||||
|
|
||||||
- **Do not copy-paste code**. There are potential license issues implicit with copy-pasting, and copy-paste usually indicates a lack of understanding of the actual code. Copy-pasted code is obvious a mile off and **any PR like this is likely to be closed**. If you want to use somebody else's code from a Git repository, **use [GIT's cherry-pick feature](https://git-scm.com/docs/git-cherry-pick)** to cherry-pick the commit. **Cherry-picking is the politer way to copy somebody's changes** and retains all the original accreditation, so there is no need for copy-pasted commits with descriptions like `Some code, thanks @exampleperson`.
|
|
||||||
|
|
||||||
- In addition to the above, **make sure you can explain your changes**. If you can't provide a good explanation of changes, your PR may be rejected.
|
|
||||||
|
|
||||||
|
### Pull requests
|
||||||
- **Create a new branch for each pull request.** Do not create a pull request with commits that exist in another pull request.
|
- **Create a new branch for each pull request.** Do not create a pull request with commits that exist in another pull request.
|
||||||
|
|
||||||
- **Code should use the same style as in PocketMine-MP.** See [below](#code-syntax) for an example.
|
|
||||||
|
|
||||||
- **The code must be clear** and written in English, comments included.
|
|
||||||
|
|
||||||
- **Use descriptive commit titles.** You can see an example [here](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
|
- **Use descriptive commit titles.** You can see an example [here](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
|
||||||
|
- **Do not include multiple unrelated changes in one commit.** An atomic style for commits is preferred - this means that changes included in a commit should be part of a single distinct change set. See [this link](https://www.freshconsulting.com/atomic-commits/) for more information on atomic commits. See the [documentation on `git add`](https://git-scm.com/docs/git-add) for information on how to isolate local changes for committing.
|
||||||
- **Try to stick to one change per commit.** This ensures that if you create a PR with several changes, we can decide which ones we wish to include and which ones not to include.
|
- **Your pull request will be checked and discussed in due time.** Since the team is scattered all around the world, your PR may not receive any attention for some time.
|
||||||
|
- **It is inadvisable to create large pull requests with lots of changes** unless this has been discussed with the team beforehand. Large pull requests are difficult to review, and such pull requests may end up being closed. The only exception is when all features in the pull request are related to each other, and share the same core changes.
|
||||||
- **It is inadvisable to create pull requests with large commits** unless this has been discussed with the team beforehand. Large pull requests are difficult to review, and such pull requests may end up being closed. The only exception is when all features in the pull request are related to each other, and share the same core changes.
|
|
||||||
|
|
||||||
- **You may be asked to rebase your pull request** if the branch becomes outdated and/or if possibly conflicting changes are made to the target branch. To see how to do this, read [this page](https://github.com/edx/edx-platform/wiki/How-to-Rebase-a-Pull-Request).
|
- **You may be asked to rebase your pull request** if the branch becomes outdated and/or if possibly conflicting changes are made to the target branch. To see how to do this, read [this page](https://github.com/edx/edx-platform/wiki/How-to-Rebase-a-Pull-Request).
|
||||||
|
- **Details should be provided of tests done.** Simply saying "Tested" or equivalent is not acceptable.
|
||||||
|
|
||||||
|
### Code contributions
|
||||||
|
- **Avoid using GitHub Web Editor**. The web editor lacks most useful GIT features and **should only be used for very minor changes**. It is immediately clear if the web editor has been used, and if so the PR is more likely to be rejected. If you want to make serious contributions, **please learn how to use [GIT version control](https://git-scm.com/)**.
|
||||||
|
- **Do not copy-paste code**. There are potential license issues implicit with copy-pasting, and copy-paste usually indicates a lack of understanding of the actual code. Copy-pasted code is obvious a mile off and **any PR like this is likely to be closed**. If you want to use somebody else's code from a Git repository, **use [GIT's cherry-pick feature](https://git-scm.com/docs/git-cherry-pick)** to cherry-pick the commit. **Cherry-picking is the politer way to copy somebody's changes** and retains all the original accreditation, so there is no need for copy-pasted commits with descriptions like `Some code, thanks @exampleperson`.
|
||||||
|
- **Make sure you can explain your changes**. If you can't provide a good explanation of changes, your PR may be rejected.
|
||||||
|
- **Code should use the same style as in PocketMine-MP.** See [below](#code-syntax) for an example.
|
||||||
|
- **The code must be clear** and written in English, comments included.
|
||||||
|
|
||||||
|
|
||||||
**Thanks for contributing to PocketMine-MP!**
|
**Thanks for contributing to PocketMine-MP!**
|
||||||
@ -78,17 +68,18 @@ It is mainly [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accept
|
|||||||
- Strings SHOULD use the double quote `"` except when the single quote is required.
|
- Strings SHOULD use the double quote `"` except when the single quote is required.
|
||||||
- All code SHOULD have parameter and type declarations where possible.
|
- All code SHOULD have parameter and type declarations where possible.
|
||||||
- Strict types SHOULD be enabled on new files where it is sensible to do so.
|
- Strict types SHOULD be enabled on new files where it is sensible to do so.
|
||||||
|
- All constant declarations SHOULD be preceded by a visibility modifier.
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace pocketmine\example;
|
namespace pocketmine\example;
|
||||||
|
|
||||||
class ExampleClass{
|
class ExampleClass{
|
||||||
|
|
||||||
const EXAMPLE_CLASS_CONSTANT = 1;
|
public const EXAMPLE_CLASS_CONSTANT = 1;
|
||||||
|
|
||||||
public $examplePublicVariable = "defaultValue";
|
public $examplePublicVariable = "defaultValue";
|
||||||
private $examplePrivateVariable;
|
private $examplePrivateVariable;
|
||||||
@ -99,7 +90,7 @@ class ExampleClass{
|
|||||||
* @param string $firstArgument the first argument
|
* @param string $firstArgument the first argument
|
||||||
* @param string|null $secondArgument default null
|
* @param string|null $secondArgument default null
|
||||||
*/
|
*/
|
||||||
public function __construct(string $firstArgument, &$secondArgument = null){
|
public function __construct(string $firstArgument, ?string &$secondArgument = null){
|
||||||
if($firstArgument === "exampleValue"){ //Remember to use === instead of == when possible
|
if($firstArgument === "exampleValue"){ //Remember to use === instead of == when possible
|
||||||
//do things
|
//do things
|
||||||
}elseif($firstArgument === "otherValue"){
|
}elseif($firstArgument === "otherValue"){
|
||||||
@ -119,7 +110,6 @@ class ExampleClass{
|
|||||||
public function doStuff(string $stuff) : string{
|
public function doStuff(string $stuff) : string{
|
||||||
return $stuff;
|
return $stuff;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ If you don't find what you're looking for there, [talk to a human](#discussion).
|
|||||||
|
|
||||||
### Discussion
|
### Discussion
|
||||||
- [Forums](https://forums.pmmp.io/)
|
- [Forums](https://forums.pmmp.io/)
|
||||||
- [#pmmp + #pocketmine channel IRC](http://webchat.freenode.net/?channels=pmmp,pocketmine)
|
|
||||||
|
|
||||||
### Plugins
|
### Plugins
|
||||||
There are a very wide range of already-written plugins available which you can use to customise your server. Check out [Poggit](https://poggit.pmmp.io), or just search GitHub.
|
There are a very wide range of already-written plugins available which you can use to customise your server. Check out [Poggit](https://poggit.pmmp.io), or just search GitHub.
|
||||||
@ -23,7 +22,10 @@ There are a very wide range of already-written plugins available which you can u
|
|||||||
Yes you can! Contributions are welcomed provided that they comply with our [Contributing Guidelines](CONTRIBUTING.md). Please ensure you read the relevant sections of the guidelines carefully before making a Pull Request or opening an Issue.
|
Yes you can! Contributions are welcomed provided that they comply with our [Contributing Guidelines](CONTRIBUTING.md). Please ensure you read the relevant sections of the guidelines carefully before making a Pull Request or opening an Issue.
|
||||||
|
|
||||||
### Where can I get the latest .phar?
|
### Where can I get the latest .phar?
|
||||||
Head over to our [official Jenkins server](https://jenkins.pmmp.io/)
|
- Latest release builds can be found in our [GitHub releases](https://github.com/pmmp/PocketMine-MP/releases).
|
||||||
|
- Latest bleeding-edge development builds (and other builds in the build job channels) can be found on our [Jenkins server](https://jenkins.pmmp.io/).
|
||||||
|
|
||||||
|
**Note: Please avoid development builds unless there is no other alternative for what you need.** Development builds are subject to changes at any time without notice, and it is likely that your server or plugins might break without warning.
|
||||||
|
|
||||||
## Third-party Libraries/Protocols Used
|
## Third-party Libraries/Protocols Used
|
||||||
* __[PHP Sockets](http://php.net/manual/en/book.sockets.php)__
|
* __[PHP Sockets](http://php.net/manual/en/book.sockets.php)__
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "pmmp/pocketmine-mp",
|
"name": "pocketmine/pocketmine-mp",
|
||||||
"description": "A server software for Minecraft: Pocket Edition written in PHP",
|
"description": "A server software for Minecraft: Pocket Edition written in PHP",
|
||||||
"type": "project",
|
"type": "project",
|
||||||
"homepage": "https://pmmp.io",
|
"homepage": "https://pmmp.io",
|
||||||
"license": "LGPL-3.0",
|
"license": "LGPL-3.0",
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.2.0RC3",
|
"php": ">=7.2.0",
|
||||||
"ext-bcmath": "*",
|
"ext-bcmath": "*",
|
||||||
"ext-curl": "*",
|
"ext-curl": "*",
|
||||||
"ext-hash": "*",
|
"ext-hash": "*",
|
||||||
@ -21,11 +21,14 @@
|
|||||||
"ext-yaml": ">=2.0.0",
|
"ext-yaml": ">=2.0.0",
|
||||||
"ext-zip": "*",
|
"ext-zip": "*",
|
||||||
"ext-zlib": ">=1.2.11",
|
"ext-zlib": ">=1.2.11",
|
||||||
"pmmp/raklib": "dev-master#29ab14d5d8640a8ee359ce315b083a129e72db4a",
|
"pocketmine/raklib": "0.11.0",
|
||||||
"pmmp/pocketmine-spl": "^0.1.0"
|
"pocketmine/spl": "0.3.0",
|
||||||
|
"pocketmine/binaryutils": "0.0.1",
|
||||||
|
"pocketmine/nbt": "0.1.0",
|
||||||
|
"pocketmine/math": "0.1.0"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-0": {
|
"psr-4": {
|
||||||
"": ["src"]
|
"": ["src"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -36,7 +39,19 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "vcs",
|
"type": "vcs",
|
||||||
"url": "https://github.com/pmmp/PocketMine-SPL"
|
"url": "https://github.com/pmmp/SPL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "vcs",
|
||||||
|
"url": "https://github.com/pmmp/BinaryUtils"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "vcs",
|
||||||
|
"url": "https://github.com/pmmp/NBT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "vcs",
|
||||||
|
"url": "https://github.com/pmmp/Math"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
204
composer.lock
generated
204
composer.lock
generated
@ -4,20 +4,163 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "169d2724a6847e704f3bb76030bebc87",
|
"content-hash": "401dbada37e501304f05b0f1fa818953",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "pmmp/pocketmine-spl",
|
"name": "pocketmine/binaryutils",
|
||||||
"version": "0.1.0",
|
"version": "0.0.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/pmmp/PocketMine-SPL.git",
|
"url": "https://github.com/pmmp/BinaryUtils.git",
|
||||||
"reference": "c56936e6aaad925bb60002b29b1c70f497af4679"
|
"reference": "03e6851f814aba96487ec64181a6ae948edd9f7a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/pmmp/PocketMine-SPL/zipball/c56936e6aaad925bb60002b29b1c70f497af4679",
|
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/03e6851f814aba96487ec64181a6ae948edd9f7a",
|
||||||
"reference": "c56936e6aaad925bb60002b29b1c70f497af4679",
|
"reference": "03e6851f814aba96487ec64181a6ae948edd9f7a",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.2"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"pocketmine\\utils\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"license": [
|
||||||
|
"LGPL-3.0"
|
||||||
|
],
|
||||||
|
"description": "Classes and methods for conveniently handling binary data",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/pmmp/BinaryUtils/tree/master",
|
||||||
|
"issues": "https://github.com/pmmp/BinaryUtils/issues"
|
||||||
|
},
|
||||||
|
"time": "2018-03-17T11:57:06+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pocketmine/math",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/pmmp/Math.git",
|
||||||
|
"reference": "1df74f0352309a9c1e6728fa416a3f0493d07b16"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/pmmp/Math/zipball/1df74f0352309a9c1e6728fa416a3f0493d07b16",
|
||||||
|
"reference": "1df74f0352309a9c1e6728fa416a3f0493d07b16",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.2.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"pocketmine\\math\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"license": [
|
||||||
|
"LGPL-3.0"
|
||||||
|
],
|
||||||
|
"description": "PHP library containing math related code used in PocketMine-MP",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/pmmp/Math/tree/master",
|
||||||
|
"issues": "https://github.com/pmmp/Math/issues"
|
||||||
|
},
|
||||||
|
"time": "2018-03-18T18:01:56+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pocketmine/nbt",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/pmmp/NBT.git",
|
||||||
|
"reference": "d79f8615442887bb45cfacdb52e1e6eb47c38fd7"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/pmmp/NBT/zipball/d79f8615442887bb45cfacdb52e1e6eb47c38fd7",
|
||||||
|
"reference": "d79f8615442887bb45cfacdb52e1e6eb47c38fd7",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.2.0",
|
||||||
|
"pocketmine/binaryutils": "0.0.1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"pocketmine\\nbt\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"pocketmine\\nbt\\": "tests/phpunit/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"license": [
|
||||||
|
"LGPL-3.0"
|
||||||
|
],
|
||||||
|
"description": "PHP library for working with Named Binary Tags",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/pmmp/NBT/tree/0.1.0",
|
||||||
|
"issues": "https://github.com/pmmp/NBT/issues"
|
||||||
|
},
|
||||||
|
"time": "2018-04-13T18:43:03+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pocketmine/raklib",
|
||||||
|
"version": "0.11.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/pmmp/RakLib.git",
|
||||||
|
"reference": "1da1b4c6cc6bd5337ce5e468d22bbb013ae02b43"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/1da1b4c6cc6bd5337ce5e468d22bbb013ae02b43",
|
||||||
|
"reference": "1da1b4c6cc6bd5337ce5e468d22bbb013ae02b43",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-bcmath": "*",
|
||||||
|
"ext-pthreads": ">=3.1.7dev",
|
||||||
|
"ext-sockets": "*",
|
||||||
|
"php": ">=7.2.0RC3",
|
||||||
|
"pocketmine/binaryutils": "0.0.1",
|
||||||
|
"pocketmine/spl": "0.3.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"classmap": [
|
||||||
|
"./"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0"
|
||||||
|
],
|
||||||
|
"description": "A RakNet server implementation written in PHP",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/pmmp/RakLib/tree/0.11.0",
|
||||||
|
"issues": "https://github.com/pmmp/RakLib/issues"
|
||||||
|
},
|
||||||
|
"time": "2018-04-13T19:05:24+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pocketmine/spl",
|
||||||
|
"version": "0.3.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/pmmp/SPL.git",
|
||||||
|
"reference": "ee32424c100fd11ae7f7b8df7604623fd475f0ec"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/pmmp/SPL/zipball/ee32424c100fd11ae7f7b8df7604623fd475f0ec",
|
||||||
|
"reference": "ee32424c100fd11ae7f7b8df7604623fd475f0ec",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
@ -34,60 +177,21 @@
|
|||||||
],
|
],
|
||||||
"description": "Standard library files required by PocketMine-MP and related projects",
|
"description": "Standard library files required by PocketMine-MP and related projects",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/pmmp/PocketMine-SPL/tree/master"
|
"source": "https://github.com/pmmp/SPL/tree/master"
|
||||||
},
|
},
|
||||||
"time": "2017-12-10T12:18:30+00:00"
|
"time": "2018-03-17T11:56:20+00:00"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "pmmp/raklib",
|
|
||||||
"version": "dev-master",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/pmmp/RakLib.git",
|
|
||||||
"reference": "29ab14d5d8640a8ee359ce315b083a129e72db4a"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/29ab14d5d8640a8ee359ce315b083a129e72db4a",
|
|
||||||
"reference": "29ab14d5d8640a8ee359ce315b083a129e72db4a",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"ext-bcmath": "*",
|
|
||||||
"ext-pthreads": ">=3.1.7dev",
|
|
||||||
"ext-sockets": "*",
|
|
||||||
"php": ">=7.2.0RC3",
|
|
||||||
"pmmp/pocketmine-spl": "^0.1.0"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"classmap": [
|
|
||||||
"./"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"license": [
|
|
||||||
"GPL-3.0"
|
|
||||||
],
|
|
||||||
"description": "A RakNet server implementation written in PHP",
|
|
||||||
"support": {
|
|
||||||
"source": "https://github.com/pmmp/RakLib/tree/master",
|
|
||||||
"issues": "https://github.com/pmmp/RakLib/issues"
|
|
||||||
},
|
|
||||||
"time": "2017-12-10T12:24:38+00:00"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [],
|
"packages-dev": [],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
"stability-flags": {
|
"stability-flags": {
|
||||||
"php": 5,
|
"ext-pthreads": 20
|
||||||
"ext-pthreads": 20,
|
|
||||||
"pmmp/raklib": 20
|
|
||||||
},
|
},
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": {
|
"platform": {
|
||||||
"php": ">=7.2.0RC3",
|
"php": ">=7.2.0",
|
||||||
"ext-bcmath": "*",
|
"ext-bcmath": "*",
|
||||||
"ext-curl": "*",
|
"ext-curl": "*",
|
||||||
"ext-hash": "*",
|
"ext-hash": "*",
|
||||||
|
@ -2319,4 +2319,3 @@ GENERATE_LEGEND = YES
|
|||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|
||||||
DOT_CLEANUP = YES
|
DOT_CLEANUP = YES
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine;
|
namespace pocketmine;
|
||||||
|
|
||||||
use pocketmine\event\TranslationContainer;
|
use pocketmine\lang\TranslationContainer;
|
||||||
use pocketmine\utils\TextFormat;
|
use pocketmine\utils\TextFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -116,7 +116,7 @@ abstract class Achievement{
|
|||||||
public static function broadcast(Player $player, string $achievementId) : bool{
|
public static function broadcast(Player $player, string $achievementId) : bool{
|
||||||
if(isset(Achievement::$list[$achievementId])){
|
if(isset(Achievement::$list[$achievementId])){
|
||||||
$translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"] . TextFormat::RESET]);
|
$translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"] . TextFormat::RESET]);
|
||||||
if(Server::getInstance()->getConfigBool("announce-player-achievements", true) === true){
|
if(Server::getInstance()->getConfigBool("announce-player-achievements", true)){
|
||||||
Server::getInstance()->broadcastMessage($translation);
|
Server::getInstance()->broadcastMessage($translation);
|
||||||
}else{
|
}else{
|
||||||
$player->sendMessage($translation);
|
$player->sendMessage($translation);
|
||||||
|
@ -115,10 +115,10 @@ class CrashDump{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function extraData(){
|
private function extraData(){
|
||||||
global $arguments;
|
global $argv;
|
||||||
|
|
||||||
if($this->server->getProperty("auto-report.send-settings", true) !== false){
|
if($this->server->getProperty("auto-report.send-settings", true) !== false){
|
||||||
$this->data["parameters"] = (array) $arguments;
|
$this->data["parameters"] = (array) $argv;
|
||||||
$this->data["server.properties"] = @file_get_contents($this->server->getDataPath() . "server.properties");
|
$this->data["server.properties"] = @file_get_contents($this->server->getDataPath() . "server.properties");
|
||||||
$this->data["server.properties"] = preg_replace("#^rcon\\.password=(.*)$#m", "rcon.password=******", $this->data["server.properties"]);
|
$this->data["server.properties"] = preg_replace("#^rcon\\.password=(.*)$#m", "rcon.password=******", $this->data["server.properties"]);
|
||||||
$this->data["pocketmine.yml"] = @file_get_contents($this->server->getDataPath() . "pocketmine.yml");
|
$this->data["pocketmine.yml"] = @file_get_contents($this->server->getDataPath() . "pocketmine.yml");
|
||||||
@ -148,7 +148,7 @@ class CrashDump{
|
|||||||
$error = $lastExceptionError;
|
$error = $lastExceptionError;
|
||||||
}else{
|
}else{
|
||||||
$error = (array) error_get_last();
|
$error = (array) error_get_last();
|
||||||
$error["trace"] = getTrace(4); //Skipping CrashDump->baseCrash, CrashDump->construct, Server->crashDump
|
$error["trace"] = Utils::getTrace(4); //Skipping CrashDump->baseCrash, CrashDump->construct, Server->crashDump
|
||||||
$errorConversion = [
|
$errorConversion = [
|
||||||
E_ERROR => "E_ERROR",
|
E_ERROR => "E_ERROR",
|
||||||
E_WARNING => "E_WARNING",
|
E_WARNING => "E_WARNING",
|
||||||
@ -167,7 +167,7 @@ class CrashDump{
|
|||||||
E_USER_DEPRECATED => "E_USER_DEPRECATED"
|
E_USER_DEPRECATED => "E_USER_DEPRECATED"
|
||||||
];
|
];
|
||||||
$error["fullFile"] = $error["file"];
|
$error["fullFile"] = $error["file"];
|
||||||
$error["file"] = cleanPath($error["file"]);
|
$error["file"] = Utils::cleanPath($error["file"]);
|
||||||
$error["type"] = $errorConversion[$error["type"]] ?? $error["type"];
|
$error["type"] = $errorConversion[$error["type"]] ?? $error["type"];
|
||||||
if(($pos = strpos($error["message"], "\n")) !== false){
|
if(($pos = strpos($error["message"], "\n")) !== false){
|
||||||
$error["message"] = substr($error["message"], 0, $pos);
|
$error["message"] = substr($error["message"], 0, $pos);
|
||||||
@ -186,7 +186,7 @@ class CrashDump{
|
|||||||
$this->addLine("Line: " . $error["line"]);
|
$this->addLine("Line: " . $error["line"]);
|
||||||
$this->addLine("Type: " . $error["type"]);
|
$this->addLine("Type: " . $error["type"]);
|
||||||
|
|
||||||
if(strpos($error["file"], "src/pocketmine/") === false and strpos($error["file"], "src/raklib/") === false and file_exists($error["fullFile"])){
|
if(strpos($error["file"], "src/pocketmine/") === false and strpos($error["file"], "vendor/pocketmine/") === false and file_exists($error["fullFile"])){
|
||||||
$this->addLine();
|
$this->addLine();
|
||||||
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
|
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
|
||||||
$this->data["plugin"] = true;
|
$this->data["plugin"] = true;
|
||||||
@ -195,7 +195,7 @@ class CrashDump{
|
|||||||
$file = $reflection->getProperty("file");
|
$file = $reflection->getProperty("file");
|
||||||
$file->setAccessible(true);
|
$file->setAccessible(true);
|
||||||
foreach($this->server->getPluginManager()->getPlugins() as $plugin){
|
foreach($this->server->getPluginManager()->getPlugins() as $plugin){
|
||||||
$filePath = \pocketmine\cleanPath($file->getValue($plugin));
|
$filePath = Utils::cleanPath($file->getValue($plugin));
|
||||||
if(strpos($error["file"], $filePath) === 0){
|
if(strpos($error["file"], $filePath) === 0){
|
||||||
$this->data["plugin"] = $plugin->getName();
|
$this->data["plugin"] = $plugin->getName();
|
||||||
$this->addLine("BAD PLUGIN: " . $plugin->getDescription()->getFullName());
|
$this->addLine("BAD PLUGIN: " . $plugin->getDescription()->getFullName());
|
||||||
|
@ -24,9 +24,9 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine;
|
namespace pocketmine;
|
||||||
|
|
||||||
use pocketmine\event\server\LowMemoryEvent;
|
use pocketmine\event\server\LowMemoryEvent;
|
||||||
use pocketmine\event\Timings;
|
|
||||||
use pocketmine\scheduler\DumpWorkerMemoryTask;
|
use pocketmine\scheduler\DumpWorkerMemoryTask;
|
||||||
use pocketmine\scheduler\GarbageCollectionTask;
|
use pocketmine\scheduler\GarbageCollectionTask;
|
||||||
|
use pocketmine\timings\Timings;
|
||||||
use pocketmine\utils\MainLogger;
|
use pocketmine\utils\MainLogger;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
|
|
||||||
@ -265,7 +265,7 @@ class MemoryManager{
|
|||||||
*/
|
*/
|
||||||
public function dumpServerMemory(string $outputFolder, int $maxNesting, int $maxStringSize){
|
public function dumpServerMemory(string $outputFolder, int $maxNesting, int $maxStringSize){
|
||||||
MainLogger::getLogger()->notice("[Dump] After the memory dump is done, the server might crash");
|
MainLogger::getLogger()->notice("[Dump] After the memory dump is done, the server might crash");
|
||||||
self::dumpMemory($this->server, $this->server->getLoader(), $outputFolder, $maxNesting, $maxStringSize);
|
self::dumpMemory($this->server, $outputFolder, $maxNesting, $maxStringSize);
|
||||||
|
|
||||||
if($this->dumpWorkers){
|
if($this->dumpWorkers){
|
||||||
$scheduler = $this->server->getScheduler();
|
$scheduler = $this->server->getScheduler();
|
||||||
@ -278,13 +278,14 @@ class MemoryManager{
|
|||||||
/**
|
/**
|
||||||
* Static memory dumper accessible from any thread.
|
* Static memory dumper accessible from any thread.
|
||||||
*
|
*
|
||||||
* @param mixed $startingObject
|
* @param mixed $startingObject
|
||||||
* @param \ClassLoader $loader
|
* @param string $outputFolder
|
||||||
* @param string $outputFolder
|
* @param int $maxNesting
|
||||||
* @param int $maxNesting
|
* @param int $maxStringSize
|
||||||
* @param int $maxStringSize
|
*
|
||||||
|
* @throws \ReflectionException
|
||||||
*/
|
*/
|
||||||
public static function dumpMemory($startingObject, \ClassLoader $loader, string $outputFolder, int $maxNesting, int $maxStringSize){
|
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize){
|
||||||
$hardLimit = ini_get('memory_limit');
|
$hardLimit = ini_get('memory_limit');
|
||||||
ini_set('memory_limit', '-1');
|
ini_set('memory_limit', '-1');
|
||||||
gc_disable();
|
gc_disable();
|
||||||
@ -306,7 +307,7 @@ class MemoryManager{
|
|||||||
$staticProperties = [];
|
$staticProperties = [];
|
||||||
$staticCount = 0;
|
$staticCount = 0;
|
||||||
|
|
||||||
foreach($loader->getClasses() as $className){
|
foreach(get_declared_classes() as $className){
|
||||||
$reflection = new \ReflectionClass($className);
|
$reflection = new \ReflectionClass($className);
|
||||||
$staticProperties[$className] = [];
|
$staticProperties[$className] = [];
|
||||||
foreach($reflection->getProperties() as $property){
|
foreach($reflection->getProperties() as $property){
|
||||||
@ -330,7 +331,7 @@ class MemoryManager{
|
|||||||
file_put_contents($outputFolder . "/staticProperties.js", json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
file_put_contents($outputFolder . "/staticProperties.js", json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||||
MainLogger::getLogger()->info("[Dump] Wrote $staticCount static properties");
|
MainLogger::getLogger()->info("[Dump] Wrote $staticCount static properties");
|
||||||
|
|
||||||
if($GLOBALS !== null){ //This might be null if we're on a different thread
|
if(isset($GLOBALS)){ //This might be null if we're on a different thread
|
||||||
$globalVariables = [];
|
$globalVariables = [];
|
||||||
$globalCount = 0;
|
$globalCount = 0;
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($value === true){
|
if($value){
|
||||||
$this->server->addOp(strtolower($this->getName()));
|
$this->server->addOp(strtolower($this->getName()));
|
||||||
}else{
|
}else{
|
||||||
$this->server->removeOp(strtolower($this->getName()));
|
$this->server->removeOp(strtolower($this->getName()));
|
||||||
@ -84,7 +84,7 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function setBanned(bool $value){
|
public function setBanned(bool $value){
|
||||||
if($value === true){
|
if($value){
|
||||||
$this->server->getNameBans()->addBan($this->getName(), null, null, null);
|
$this->server->getNameBans()->addBan($this->getName(), null, null, null);
|
||||||
}else{
|
}else{
|
||||||
$this->server->getNameBans()->remove($this->getName());
|
$this->server->getNameBans()->remove($this->getName());
|
||||||
@ -96,7 +96,7 @@ class OfflinePlayer implements IPlayer, Metadatable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function setWhitelisted(bool $value){
|
public function setWhitelisted(bool $value){
|
||||||
if($value === true){
|
if($value){
|
||||||
$this->server->addWhitelist(strtolower($this->getName()));
|
$this->server->addWhitelist(strtolower($this->getName()));
|
||||||
}else{
|
}else{
|
||||||
$this->server->removeWhitelist(strtolower($this->getName()));
|
$this->server->removeWhitelist(strtolower($this->getName()));
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -71,37 +71,99 @@ namespace {
|
|||||||
|
|
||||||
namespace pocketmine {
|
namespace pocketmine {
|
||||||
|
|
||||||
use pocketmine\utils\Binary;
|
|
||||||
use pocketmine\utils\MainLogger;
|
use pocketmine\utils\MainLogger;
|
||||||
use pocketmine\utils\ServerKiller;
|
use pocketmine\utils\ServerKiller;
|
||||||
use pocketmine\utils\Terminal;
|
use pocketmine\utils\Terminal;
|
||||||
|
use pocketmine\utils\Timezone;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
use pocketmine\wizard\SetupWizard;
|
use pocketmine\wizard\SetupWizard;
|
||||||
use raklib\RakLib;
|
use raklib\RakLib;
|
||||||
|
|
||||||
const NAME = "PocketMine-MP";
|
const NAME = "PocketMine-MP";
|
||||||
const VERSION = "1.7dev";
|
const VERSION = "1.7dev";
|
||||||
const API_VERSION = "3.0.0-ALPHA10";
|
const API_VERSION = "3.0.0-ALPHA12";
|
||||||
const CODENAME = "[REDACTED]";
|
const CODENAME = "[REDACTED]";
|
||||||
|
|
||||||
const MIN_PHP_VERSION = "7.2.0RC3";
|
const MIN_PHP_VERSION = "7.2.0";
|
||||||
|
|
||||||
|
function critical_error($message){
|
||||||
|
echo "[ERROR] $message" . PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Startup code. Do not look at it, it may harm you.
|
* Startup code. Do not look at it, it may harm you.
|
||||||
* Most of them are hacks to fix date-related bugs, or basic functions used after this
|
|
||||||
* This is the only non-class based file on this project.
|
* This is the only non-class based file on this project.
|
||||||
* Enjoy it as much as I did writing it. I don't want to do it again.
|
* Enjoy it as much as I did writing it. I don't want to do it again.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(version_compare(MIN_PHP_VERSION, PHP_VERSION) > 0){
|
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;
|
critical_error(\pocketmine\NAME . " requires PHP >= " . MIN_PHP_VERSION . ", but you have PHP " . PHP_VERSION . ".");
|
||||||
echo "[CRITICAL] Please use the installer provided on the homepage, or update to a newer PHP version." . PHP_EOL;
|
critical_error("Please use the installer provided on the homepage, or update to a newer PHP version.");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!extension_loaded("pthreads")){
|
if(PHP_INT_SIZE < 8){
|
||||||
echo "[CRITICAL] Unable to find the pthreads extension." . PHP_EOL;
|
critical_error("Running " . \pocketmine\NAME . " with 32-bit systems/PHP is no longer supported.");
|
||||||
echo "[CRITICAL] Please use the installer provided on the homepage." . PHP_EOL;
|
critical_error("Please upgrade to a 64-bit system, or use a 64-bit PHP binary if this is a 64-bit system.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dependencies check */
|
||||||
|
|
||||||
|
$errors = 0;
|
||||||
|
|
||||||
|
if(php_sapi_name() !== "cli"){
|
||||||
|
critical_error("You must run " . \pocketmine\NAME . " using the CLI.");
|
||||||
|
++$errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
$extensions = [
|
||||||
|
"bcmath" => "BC Math",
|
||||||
|
"curl" => "cURL",
|
||||||
|
"json" => "JSON",
|
||||||
|
"mbstring" => "Multibyte String",
|
||||||
|
"openssl" => "OpenSSL",
|
||||||
|
"phar" => "Phar",
|
||||||
|
"pthreads" => "pthreads",
|
||||||
|
"sockets" => "Sockets",
|
||||||
|
"yaml" => "YAML",
|
||||||
|
"zip" => "Zip",
|
||||||
|
"zlib" => "Zlib"
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach($extensions as $ext => $name){
|
||||||
|
if(!extension_loaded($ext)){
|
||||||
|
critical_error("Unable to find the $name ($ext) extension.");
|
||||||
|
++$errors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(extension_loaded("pthreads")){
|
||||||
|
$pthreads_version = phpversion("pthreads");
|
||||||
|
if(substr_count($pthreads_version, ".") < 2){
|
||||||
|
$pthreads_version = "0.$pthreads_version";
|
||||||
|
}
|
||||||
|
if(version_compare($pthreads_version, "3.1.7-dev") < 0){
|
||||||
|
critical_error("pthreads >= 3.1.7-dev is required, while you have $pthreads_version.");
|
||||||
|
++$errors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(extension_loaded("leveldb")){
|
||||||
|
$leveldb_version = phpversion("leveldb");
|
||||||
|
if(version_compare($leveldb_version, "0.2.1") < 0){
|
||||||
|
critical_error("php-leveldb >= 0.2.1 is required, while you have $leveldb_version");
|
||||||
|
++$errors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(extension_loaded("pocketmine")){
|
||||||
|
critical_error("The native PocketMine extension is no longer supported.");
|
||||||
|
++$errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($errors > 0){
|
||||||
|
critical_error("Please use the installer provided on the homepage, or recompile PHP again.");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,12 +179,6 @@ namespace pocketmine {
|
|||||||
|
|
||||||
set_error_handler('\pocketmine\error_handler');
|
set_error_handler('\pocketmine\error_handler');
|
||||||
|
|
||||||
if(!extension_loaded("phar")){
|
|
||||||
echo "[CRITICAL] Unable to find the Phar extension." . PHP_EOL;
|
|
||||||
echo "[CRITICAL] Please use the installer provided on the homepage." . PHP_EOL;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(\Phar::running(true) !== ""){
|
if(\Phar::running(true) !== ""){
|
||||||
define('pocketmine\PATH', \Phar::running(true) . "/");
|
define('pocketmine\PATH', \Phar::running(true) . "/");
|
||||||
}else{
|
}else{
|
||||||
@ -132,8 +188,8 @@ namespace pocketmine {
|
|||||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', \pocketmine\PATH . 'vendor/autoload.php');
|
define('pocketmine\COMPOSER_AUTOLOADER_PATH', \pocketmine\PATH . 'vendor/autoload.php');
|
||||||
|
|
||||||
function composer_error_die($message){
|
function composer_error_die($message){
|
||||||
echo "[CRITICAL] $message" . PHP_EOL;
|
critical_error($message);
|
||||||
echo "[CRITICAL] Please install/update Composer dependencies or use provided builds." . PHP_EOL;
|
critical_error("Please install/update Composer dependencies or use provided builds.");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,8 +202,8 @@ namespace pocketmine {
|
|||||||
if(!class_exists(RakLib::class)){
|
if(!class_exists(RakLib::class)){
|
||||||
composer_error_die("Unable to find the RakLib library.");
|
composer_error_die("Unable to find the RakLib library.");
|
||||||
}
|
}
|
||||||
if(version_compare(RakLib::VERSION, "0.9.0") < 0){ //TODO: remove this check (it's managed by Composer now)
|
if(version_compare(RakLib::VERSION, "0.11.0") < 0){ //TODO: remove this check (it's managed by Composer now)
|
||||||
composer_error_die("RakLib version 0.9.0 is required, while you have version " . RakLib::VERSION . ".");
|
composer_error_die("RakLib version 0.11.0 is required, while you have version " . RakLib::VERSION . ".");
|
||||||
}
|
}
|
||||||
if(!class_exists(\BaseClassLoader::class)){
|
if(!class_exists(\BaseClassLoader::class)){
|
||||||
composer_error_die("Unable to find the PocketMine-SPL library.");
|
composer_error_die("Unable to find the PocketMine-SPL library.");
|
||||||
@ -157,8 +213,6 @@ namespace pocketmine {
|
|||||||
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
|
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
|
||||||
*/
|
*/
|
||||||
$autoloader = new \BaseClassLoader();
|
$autoloader = new \BaseClassLoader();
|
||||||
$autoloader->addPath(\pocketmine\PATH . "src");
|
|
||||||
$autoloader->addPath(\pocketmine\PATH . "src" . DIRECTORY_SEPARATOR . "spl");
|
|
||||||
$autoloader->register(false);
|
$autoloader->register(false);
|
||||||
|
|
||||||
set_time_limit(0); //Who set it to 30 seconds?!?!
|
set_time_limit(0); //Who set it to 30 seconds?!?!
|
||||||
@ -175,8 +229,8 @@ namespace pocketmine {
|
|||||||
|
|
||||||
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-profiler"]);
|
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-profiler"]);
|
||||||
|
|
||||||
define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR);
|
define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : \realpath(\getcwd()) . DIRECTORY_SEPARATOR);
|
||||||
define('pocketmine\PLUGIN_PATH', isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR);
|
define('pocketmine\PLUGIN_PATH', isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : \realpath(\getcwd()) . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR);
|
||||||
|
|
||||||
Terminal::init();
|
Terminal::init();
|
||||||
|
|
||||||
@ -186,176 +240,16 @@ namespace pocketmine {
|
|||||||
mkdir(\pocketmine\DATA, 0777, true);
|
mkdir(\pocketmine\DATA, 0777, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Logger has a dependency on timezone, so we'll set it to UTC until we can get the actual timezone.
|
//Logger has a dependency on timezone
|
||||||
date_default_timezone_set("UTC");
|
$tzError = Timezone::init();
|
||||||
|
|
||||||
$logger = new MainLogger(\pocketmine\DATA . "server.log");
|
$logger = new MainLogger(\pocketmine\DATA . "server.log");
|
||||||
$logger->registerStatic();
|
$logger->registerStatic();
|
||||||
|
|
||||||
do{
|
foreach($tzError as $e){
|
||||||
$timezone = ini_get("date.timezone");
|
$logger->warning($e);
|
||||||
if($timezone !== ""){
|
|
||||||
/*
|
|
||||||
* 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(($timezone = detect_system_timezone()) and date_default_timezone_set($timezone)){
|
|
||||||
//Success! Timezone has already been set and validated in the if statement.
|
|
||||||
//This here is just for redundancy just in case some program wants to read timezone data from the ini.
|
|
||||||
ini_set("date.timezone", $timezone);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($response = Utils::getURL("http://ip-api.com/json") //If system timezone detection fails or timezone is an invalid value.
|
|
||||||
and $ip_geolocation_data = json_decode($response, true)
|
|
||||||
and $ip_geolocation_data['status'] !== 'fail'
|
|
||||||
and date_default_timezone_set($ip_geolocation_data['timezone'])
|
|
||||||
){
|
|
||||||
//Again, for redundancy.
|
|
||||||
ini_set("date.timezone", $ip_geolocation_data['timezone']);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ini_set("date.timezone", "UTC");
|
|
||||||
date_default_timezone_set("UTC");
|
|
||||||
$logger->warning("Timezone could not be automatically determined or was set to an invalid value. An incorrect timezone will result in incorrect timestamps on console logs. It has been set to \"UTC\" by default. You can change it on the php.ini file.");
|
|
||||||
}while(false);
|
|
||||||
|
|
||||||
|
|
||||||
function detect_system_timezone(){
|
|
||||||
switch(Utils::getOS()){
|
|
||||||
case 'win':
|
|
||||||
$regex = '/(UTC)(\+*\-*\d*\d*\:*\d*\d*)/';
|
|
||||||
|
|
||||||
/*
|
|
||||||
* wmic timezone get Caption
|
|
||||||
* Get the timezone offset
|
|
||||||
*
|
|
||||||
* Sample Output var_dump
|
|
||||||
* array(3) {
|
|
||||||
* [0] =>
|
|
||||||
* string(7) "Caption"
|
|
||||||
* [1] =>
|
|
||||||
* string(20) "(UTC+09:30) Adelaide"
|
|
||||||
* [2] =>
|
|
||||||
* string(0) ""
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
exec("wmic timezone get Caption", $output);
|
|
||||||
|
|
||||||
$string = trim(implode("\n", $output));
|
|
||||||
|
|
||||||
//Detect the Time Zone string
|
|
||||||
preg_match($regex, $string, $matches);
|
|
||||||
|
|
||||||
if(!isset($matches[2])){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$offset = $matches[2];
|
|
||||||
|
|
||||||
if($offset == ""){
|
|
||||||
return "UTC";
|
|
||||||
}
|
|
||||||
|
|
||||||
return parse_offset($offset);
|
|
||||||
case 'linux':
|
|
||||||
// Ubuntu / Debian.
|
|
||||||
if(file_exists('/etc/timezone')){
|
|
||||||
$data = file_get_contents('/etc/timezone');
|
|
||||||
if($data){
|
|
||||||
return trim($data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RHEL / CentOS
|
|
||||||
if(file_exists('/etc/sysconfig/clock')){
|
|
||||||
$data = parse_ini_file('/etc/sysconfig/clock');
|
|
||||||
if(!empty($data['ZONE'])){
|
|
||||||
return trim($data['ZONE']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Portable method for incompatible linux distributions.
|
|
||||||
|
|
||||||
$offset = trim(exec('date +%:z'));
|
|
||||||
|
|
||||||
if($offset == "+00:00"){
|
|
||||||
return "UTC";
|
|
||||||
}
|
|
||||||
|
|
||||||
return parse_offset($offset);
|
|
||||||
case 'mac':
|
|
||||||
if(is_link('/etc/localtime')){
|
|
||||||
$filename = readlink('/etc/localtime');
|
|
||||||
if(strpos($filename, '/usr/share/zoneinfo/') === 0){
|
|
||||||
$timezone = substr($filename, 20);
|
|
||||||
return trim($timezone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $offset In the format of +09:00, +02:00, -04:00 etc.
|
|
||||||
*
|
|
||||||
* @return string|bool
|
|
||||||
*/
|
|
||||||
function parse_offset($offset){
|
|
||||||
//Make signed offsets unsigned for date_parse
|
|
||||||
if(strpos($offset, '-') !== false){
|
|
||||||
$negative_offset = true;
|
|
||||||
$offset = str_replace('-', '', $offset);
|
|
||||||
}else{
|
|
||||||
if(strpos($offset, '+') !== false){
|
|
||||||
$negative_offset = false;
|
|
||||||
$offset = str_replace('+', '', $offset);
|
|
||||||
}else{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$parsed = date_parse($offset);
|
|
||||||
$offset = $parsed['hour'] * 3600 + $parsed['minute'] * 60 + $parsed['second'];
|
|
||||||
|
|
||||||
//After date_parse is done, put the sign back
|
|
||||||
if($negative_offset == true){
|
|
||||||
$offset = -abs($offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
//And then, look the offset up.
|
|
||||||
//timezone_name_from_abbr is not used because it returns false on some(most) offsets because it's mapping function is weird.
|
|
||||||
//That's been a bug in PHP since 2008!
|
|
||||||
foreach(timezone_abbreviations_list() as $zones){
|
|
||||||
foreach($zones as $timezone){
|
|
||||||
if($timezone['offset'] == $offset){
|
|
||||||
return $timezone['timezone_id'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
unset($tzError);
|
||||||
|
|
||||||
if(isset($opts["enable-profiler"])){
|
if(isset($opts["enable-profiler"])){
|
||||||
if(function_exists("profiler_enable")){
|
if(function_exists("profiler_enable")){
|
||||||
@ -366,177 +260,39 @@ namespace pocketmine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function kill($pid){
|
if(extension_loaded("xdebug")){
|
||||||
switch(Utils::getOS()){
|
$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);
|
||||||
case "win":
|
|
||||||
exec("taskkill.exe /F /PID " . ((int) $pid) . " > NUL");
|
|
||||||
break;
|
|
||||||
case "mac":
|
|
||||||
case "linux":
|
|
||||||
default:
|
|
||||||
if(function_exists("posix_kill")){
|
|
||||||
posix_kill($pid, SIGKILL);
|
|
||||||
}else{
|
|
||||||
exec("kill -9 " . ((int) $pid) . " > /dev/null 2>&1");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
if(\Phar::running(true) === ""){
|
||||||
* @param object $value
|
$logger->warning("Non-packaged " . \pocketmine\NAME . " installation detected. Consider using a phar in production for better performance.");
|
||||||
* @param bool $includeCurrent
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
function getReferenceCount($value, $includeCurrent = true){
|
|
||||||
ob_start();
|
|
||||||
debug_zval_dump($value);
|
|
||||||
$ret = explode("\n", ob_get_contents());
|
|
||||||
ob_end_clean();
|
|
||||||
|
|
||||||
if(count($ret) >= 1 and preg_match('/^.* refcount\\(([0-9]+)\\)\\{$/', trim($ret[0]), $m) > 0){
|
|
||||||
return ((int) $m[1]) - ($includeCurrent ? 3 : 4); //$value + zval call + extra call
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
$gitHash = str_repeat("00", 20);
|
||||||
* @param int $start
|
|
||||||
* @param array|null $trace
|
if(\Phar::running(true) === ""){
|
||||||
*
|
if(Utils::execute("git rev-parse HEAD", $out) === 0){
|
||||||
* @return array
|
$gitHash = trim($out);
|
||||||
*/
|
if(Utils::execute("git diff --quiet") === 1 or Utils::execute("git diff --cached --quiet") === 1){ //Locally-modified
|
||||||
function getTrace($start = 0, $trace = null){
|
$gitHash .= "-dirty";
|
||||||
if($trace === null){
|
|
||||||
if(function_exists("xdebug_get_function_stack")){
|
|
||||||
$trace = array_reverse(xdebug_get_function_stack());
|
|
||||||
}else{
|
|
||||||
$e = new \Exception();
|
|
||||||
$trace = $e->getTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
$messages = [];
|
$phar = new \Phar(\Phar::running(false));
|
||||||
$j = 0;
|
$meta = $phar->getMetadata();
|
||||||
for($i = (int) $start; isset($trace[$i]); ++$i, ++$j){
|
if(isset($meta["git"])){
|
||||||
$params = "";
|
$gitHash = $meta["git"];
|
||||||
if(isset($trace[$i]["args"]) or isset($trace[$i]["params"])){
|
|
||||||
if(isset($trace[$i]["args"])){
|
|
||||||
$args = $trace[$i]["args"];
|
|
||||||
}else{
|
|
||||||
$args = $trace[$i]["params"];
|
|
||||||
}
|
|
||||||
|
|
||||||
$params = implode(", ", array_map(function($value){
|
|
||||||
return (is_object($value) ? get_class($value) . " object" : gettype($value) . " " . (is_array($value) ? "Array()" : Utils::printable(@strval($value))));
|
|
||||||
}, $args));
|
|
||||||
}
|
|
||||||
$messages[] = "#$j " . (isset($trace[$i]["file"]) ? cleanPath($trace[$i]["file"]) : "") . "(" . (isset($trace[$i]["line"]) ? $trace[$i]["line"] : "") . "): " . (isset($trace[$i]["class"]) ? $trace[$i]["class"] . (($trace[$i]["type"] === "dynamic" or $trace[$i]["type"] === "->") ? "->" : "::") : "") . $trace[$i]["function"] . "(" . Utils::printable($params) . ")";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $messages;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanPath($path){
|
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||||
return str_replace(["\\", ".php", "phar://", str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PATH), str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PLUGIN_PATH)], ["/", "", "", "", ""], $path);
|
|
||||||
}
|
|
||||||
|
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
|
||||||
|
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors
|
||||||
|
|
||||||
$exitCode = 0;
|
$exitCode = 0;
|
||||||
|
|
||||||
do{
|
do{
|
||||||
$errors = 0;
|
|
||||||
|
|
||||||
if(PHP_INT_SIZE < 8){
|
|
||||||
$logger->critical("Running " . \pocketmine\NAME . " with 32-bit systems/PHP is no longer supported. Please upgrade to a 64-bit system or use a 64-bit PHP binary.");
|
|
||||||
$exitCode = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(php_sapi_name() !== "cli"){
|
|
||||||
$logger->critical("You must run " . \pocketmine\NAME . " using the CLI.");
|
|
||||||
++$errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
$pthreads_version = phpversion("pthreads");
|
|
||||||
if(substr_count($pthreads_version, ".") < 2){
|
|
||||||
$pthreads_version = "0.$pthreads_version";
|
|
||||||
}
|
|
||||||
if(version_compare($pthreads_version, "3.1.7-dev") < 0){
|
|
||||||
$logger->critical("pthreads >= 3.1.7-dev is required, while you have $pthreads_version.");
|
|
||||||
++$errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(extension_loaded("leveldb")){
|
|
||||||
$leveldb_version = phpversion("leveldb");
|
|
||||||
if(version_compare($leveldb_version, "0.2.1") < 0){
|
|
||||||
$logger->critical("php-leveldb >= 0.2.1 is required, while you have $leveldb_version");
|
|
||||||
++$errors;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(extension_loaded("pocketmine")){
|
|
||||||
if(version_compare(phpversion("pocketmine"), "0.0.1") < 0){
|
|
||||||
$logger->critical("You have the native PocketMine extension, but your version is lower than 0.0.1.");
|
|
||||||
++$errors;
|
|
||||||
}elseif(version_compare(phpversion("pocketmine"), "0.0.4") > 0){
|
|
||||||
$logger->critical("You have the native PocketMine extension, but your version is higher than 0.0.4.");
|
|
||||||
++$errors;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(extension_loaded("xdebug")){
|
|
||||||
$logger->warning(PHP_EOL . PHP_EOL . PHP_EOL . "\tYou are running " . \pocketmine\NAME . " with xdebug enabled. This has a major impact on performance." . PHP_EOL . PHP_EOL);
|
|
||||||
}
|
|
||||||
|
|
||||||
$extensions = [
|
|
||||||
"bcmath" => "BC Math",
|
|
||||||
"curl" => "cURL",
|
|
||||||
"json" => "JSON",
|
|
||||||
"mbstring" => "Multibyte String",
|
|
||||||
"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"])){
|
if(!file_exists(\pocketmine\DATA . "server.properties") and !isset($opts["no-wizard"])){
|
||||||
$installer = new SetupWizard();
|
$installer = new SetupWizard();
|
||||||
if(!$installer->run()){
|
if(!$installer->run()){
|
||||||
@ -545,25 +301,20 @@ namespace pocketmine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(\Phar::running(true) === ""){
|
|
||||||
$logger->warning("Non-packaged " . \pocketmine\NAME . " installation detected. Consider using a phar in production for better performance.");
|
|
||||||
}
|
|
||||||
|
|
||||||
ThreadManager::init();
|
ThreadManager::init();
|
||||||
new Server($autoloader, $logger, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
|
new Server($autoloader, $logger, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
|
||||||
|
|
||||||
$logger->info("Stopping other threads");
|
$logger->info("Stopping other threads");
|
||||||
|
|
||||||
$killer = new ServerKiller(8);
|
$killer = new ServerKiller(8);
|
||||||
$killer->start();
|
$killer->start(PTHREADS_INHERIT_NONE);
|
||||||
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
|
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
|
||||||
|
|
||||||
if(ThreadManager::getInstance()->stopAll() > 0){
|
if(ThreadManager::getInstance()->stopAll() > 0){
|
||||||
if(\pocketmine\DEBUG > 1){
|
if(\pocketmine\DEBUG > 1){
|
||||||
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
|
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
|
||||||
}
|
}
|
||||||
kill(getmypid());
|
Utils::kill(getmypid());
|
||||||
}
|
}
|
||||||
}while(false);
|
}while(false);
|
||||||
|
|
||||||
|
@ -33,8 +33,6 @@ use pocketmine\command\CommandSender;
|
|||||||
use pocketmine\command\ConsoleCommandSender;
|
use pocketmine\command\ConsoleCommandSender;
|
||||||
use pocketmine\command\PluginIdentifiableCommand;
|
use pocketmine\command\PluginIdentifiableCommand;
|
||||||
use pocketmine\command\SimpleCommandMap;
|
use pocketmine\command\SimpleCommandMap;
|
||||||
use pocketmine\entity\Attribute;
|
|
||||||
use pocketmine\entity\Effect;
|
|
||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
use pocketmine\entity\Skin;
|
use pocketmine\entity\Skin;
|
||||||
use pocketmine\event\HandlerList;
|
use pocketmine\event\HandlerList;
|
||||||
@ -43,30 +41,22 @@ use pocketmine\event\level\LevelLoadEvent;
|
|||||||
use pocketmine\event\player\PlayerDataSaveEvent;
|
use pocketmine\event\player\PlayerDataSaveEvent;
|
||||||
use pocketmine\event\server\QueryRegenerateEvent;
|
use pocketmine\event\server\QueryRegenerateEvent;
|
||||||
use pocketmine\event\server\ServerCommandEvent;
|
use pocketmine\event\server\ServerCommandEvent;
|
||||||
use pocketmine\event\TextContainer;
|
|
||||||
use pocketmine\event\Timings;
|
|
||||||
use pocketmine\event\TimingsHandler;
|
|
||||||
use pocketmine\inventory\CraftingManager;
|
use pocketmine\inventory\CraftingManager;
|
||||||
use pocketmine\inventory\Recipe;
|
|
||||||
use pocketmine\item\enchantment\Enchantment;
|
use pocketmine\item\enchantment\Enchantment;
|
||||||
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\lang\BaseLang;
|
use pocketmine\lang\BaseLang;
|
||||||
use pocketmine\level\format\io\leveldb\LevelDB;
|
use pocketmine\lang\TextContainer;
|
||||||
use pocketmine\level\format\io\LevelProvider;
|
use pocketmine\level\format\io\LevelProvider;
|
||||||
use pocketmine\level\format\io\LevelProviderManager;
|
use pocketmine\level\format\io\LevelProviderManager;
|
||||||
use pocketmine\level\format\io\region\Anvil;
|
|
||||||
use pocketmine\level\format\io\region\McRegion;
|
|
||||||
use pocketmine\level\format\io\region\PMAnvil;
|
|
||||||
use pocketmine\level\generator\biome\Biome;
|
use pocketmine\level\generator\biome\Biome;
|
||||||
use pocketmine\level\generator\Flat;
|
|
||||||
use pocketmine\level\generator\Generator;
|
use pocketmine\level\generator\Generator;
|
||||||
use pocketmine\level\generator\hell\Nether;
|
|
||||||
use pocketmine\level\generator\normal\Normal;
|
|
||||||
use pocketmine\level\Level;
|
use pocketmine\level\Level;
|
||||||
use pocketmine\level\LevelException;
|
use pocketmine\level\LevelException;
|
||||||
use pocketmine\metadata\EntityMetadataStore;
|
use pocketmine\metadata\EntityMetadataStore;
|
||||||
use pocketmine\metadata\LevelMetadataStore;
|
use pocketmine\metadata\LevelMetadataStore;
|
||||||
use pocketmine\metadata\PlayerMetadataStore;
|
use pocketmine\metadata\PlayerMetadataStore;
|
||||||
|
use pocketmine\nbt\BigEndianNBTStream;
|
||||||
use pocketmine\nbt\NBT;
|
use pocketmine\nbt\NBT;
|
||||||
use pocketmine\nbt\tag\ByteTag;
|
use pocketmine\nbt\tag\ByteTag;
|
||||||
use pocketmine\nbt\tag\CompoundTag;
|
use pocketmine\nbt\tag\CompoundTag;
|
||||||
@ -77,6 +67,7 @@ use pocketmine\nbt\tag\ListTag;
|
|||||||
use pocketmine\nbt\tag\LongTag;
|
use pocketmine\nbt\tag\LongTag;
|
||||||
use pocketmine\nbt\tag\ShortTag;
|
use pocketmine\nbt\tag\ShortTag;
|
||||||
use pocketmine\nbt\tag\StringTag;
|
use pocketmine\nbt\tag\StringTag;
|
||||||
|
use pocketmine\network\AdvancedSourceInterface;
|
||||||
use pocketmine\network\CompressBatchedTask;
|
use pocketmine\network\CompressBatchedTask;
|
||||||
use pocketmine\network\mcpe\protocol\BatchPacket;
|
use pocketmine\network\mcpe\protocol\BatchPacket;
|
||||||
use pocketmine\network\mcpe\protocol\DataPacket;
|
use pocketmine\network\mcpe\protocol\DataPacket;
|
||||||
@ -100,6 +91,8 @@ use pocketmine\scheduler\FileWriteTask;
|
|||||||
use pocketmine\scheduler\SendUsageTask;
|
use pocketmine\scheduler\SendUsageTask;
|
||||||
use pocketmine\scheduler\ServerScheduler;
|
use pocketmine\scheduler\ServerScheduler;
|
||||||
use pocketmine\tile\Tile;
|
use pocketmine\tile\Tile;
|
||||||
|
use pocketmine\timings\Timings;
|
||||||
|
use pocketmine\timings\TimingsHandler;
|
||||||
use pocketmine\updater\AutoUpdater;
|
use pocketmine\updater\AutoUpdater;
|
||||||
use pocketmine\utils\Binary;
|
use pocketmine\utils\Binary;
|
||||||
use pocketmine\utils\Config;
|
use pocketmine\utils\Config;
|
||||||
@ -262,9 +255,6 @@ class Server{
|
|||||||
/** @var Player[] */
|
/** @var Player[] */
|
||||||
private $playerList = [];
|
private $playerList = [];
|
||||||
|
|
||||||
/** @var string[] */
|
|
||||||
private $identifiers = [];
|
|
||||||
|
|
||||||
/** @var Level[] */
|
/** @var Level[] */
|
||||||
private $levels = [];
|
private $levels = [];
|
||||||
|
|
||||||
@ -282,7 +272,7 @@ class Server{
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isRunning() : bool{
|
public function isRunning() : bool{
|
||||||
return $this->isRunning === true;
|
return $this->isRunning;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -520,16 +510,6 @@ class Server{
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Moved to {@link Level#getDifficultyFromString}
|
|
||||||
*
|
|
||||||
* @param string $str
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public static function getDifficultyFromString(string $str) : int{
|
|
||||||
return Level::getDifficultyFromString($str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns Server global difficulty. Note that this may be overridden in individual Levels.
|
* Returns Server global difficulty. Note that this may be overridden in individual Levels.
|
||||||
* @return int
|
* @return int
|
||||||
@ -639,7 +619,7 @@ class Server{
|
|||||||
/**
|
/**
|
||||||
* @return ResourcePackManager
|
* @return ResourcePackManager
|
||||||
*/
|
*/
|
||||||
public function getResourceManager() : ResourcePackManager{
|
public function getResourcePackManager() : ResourcePackManager{
|
||||||
return $this->resourceManager;
|
return $this->resourceManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -714,10 +694,6 @@ class Server{
|
|||||||
return $this->playerList;
|
return $this->playerList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addRecipe(Recipe $recipe){
|
|
||||||
$this->craftingManager->registerRecipe($recipe);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function shouldSavePlayerData() : bool{
|
public function shouldSavePlayerData() : bool{
|
||||||
return (bool) $this->getProperty("player.save-player-data", true);
|
return (bool) $this->getProperty("player.save-player-data", true);
|
||||||
}
|
}
|
||||||
@ -749,10 +725,13 @@ class Server{
|
|||||||
if($this->shouldSavePlayerData()){
|
if($this->shouldSavePlayerData()){
|
||||||
if(file_exists($path . "$name.dat")){
|
if(file_exists($path . "$name.dat")){
|
||||||
try{
|
try{
|
||||||
$nbt = new NBT(NBT::BIG_ENDIAN);
|
$nbt = new BigEndianNBTStream();
|
||||||
$nbt->readCompressed(file_get_contents($path . "$name.dat"));
|
$compound = $nbt->readCompressed(file_get_contents($path . "$name.dat"));
|
||||||
|
if(!($compound instanceof CompoundTag)){
|
||||||
|
throw new \RuntimeException("Invalid data found in \"$name.dat\", expected " . CompoundTag::class . ", got " . (is_object($compound) ? get_class($compound) : gettype($compound)));
|
||||||
|
}
|
||||||
|
|
||||||
return $nbt->getData();
|
return $compound;
|
||||||
}catch(\Throwable $e){ //zlib decode error / corrupt data
|
}catch(\Throwable $e){ //zlib decode error / corrupt data
|
||||||
rename($path . "$name.dat", $path . "$name.dat.bak");
|
rename($path . "$name.dat", $path . "$name.dat.bak");
|
||||||
$this->logger->notice($this->getLanguage()->translateString("pocketmine.data.playerCorrupted", [$name]));
|
$this->logger->notice($this->getLanguage()->translateString("pocketmine.data.playerCorrupted", [$name]));
|
||||||
@ -772,11 +751,11 @@ class Server{
|
|||||||
new DoubleTag("", $spawn->y),
|
new DoubleTag("", $spawn->y),
|
||||||
new DoubleTag("", $spawn->z)
|
new DoubleTag("", $spawn->z)
|
||||||
], NBT::TAG_Double),
|
], NBT::TAG_Double),
|
||||||
new StringTag("Level", $this->getDefaultLevel()->getName()),
|
new StringTag("Level", $this->getDefaultLevel()->getFolderName()),
|
||||||
//new StringTag("SpawnLevel", $this->getDefaultLevel()->getName()),
|
//new StringTag("SpawnLevel", $this->getDefaultLevel()->getFolderName()),
|
||||||
//new IntTag("SpawnX", (int) $spawn->x),
|
//new IntTag("SpawnX", $spawn->getFloorX()),
|
||||||
//new IntTag("SpawnY", (int) $spawn->y),
|
//new IntTag("SpawnY", $spawn->getFloorY()),
|
||||||
//new IntTag("SpawnZ", (int) $spawn->z),
|
//new IntTag("SpawnZ", $spawn->getFloorZ()),
|
||||||
//new ByteTag("SpawnForced", 1), //TODO
|
//new ByteTag("SpawnForced", 1), //TODO
|
||||||
new ListTag("Inventory", [], NBT::TAG_Compound),
|
new ListTag("Inventory", [], NBT::TAG_Compound),
|
||||||
new ListTag("EnderChestInventory", [], NBT::TAG_Compound),
|
new ListTag("EnderChestInventory", [], NBT::TAG_Compound),
|
||||||
@ -815,14 +794,12 @@ class Server{
|
|||||||
$this->pluginManager->callEvent($ev);
|
$this->pluginManager->callEvent($ev);
|
||||||
|
|
||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
$nbt = new NBT(NBT::BIG_ENDIAN);
|
$nbt = new BigEndianNBTStream();
|
||||||
try{
|
try{
|
||||||
$nbt->setData($ev->getSaveData());
|
|
||||||
|
|
||||||
if($async){
|
if($async){
|
||||||
$this->getScheduler()->scheduleAsyncTask(new FileWriteTask($this->getDataPath() . "players/" . strtolower($name) . ".dat", $nbt->writeCompressed()));
|
$this->getScheduler()->scheduleAsyncTask(new FileWriteTask($this->getDataPath() . "players/" . strtolower($name) . ".dat", $nbt->writeCompressed($ev->getSaveData())));
|
||||||
}else{
|
}else{
|
||||||
file_put_contents($this->getDataPath() . "players/" . strtolower($name) . ".dat", $nbt->writeCompressed());
|
file_put_contents($this->getDataPath() . "players/" . strtolower($name) . ".dat", $nbt->writeCompressed($ev->getSaveData()));
|
||||||
}
|
}
|
||||||
}catch(\Throwable $e){
|
}catch(\Throwable $e){
|
||||||
$this->logger->critical($this->getLanguage()->translateString("pocketmine.data.saveError", [$name, $e->getMessage()]));
|
$this->logger->critical($this->getLanguage()->translateString("pocketmine.data.saveError", [$name, $e->getMessage()]));
|
||||||
@ -893,23 +870,25 @@ class Server{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Player $player
|
* Returns the player online with the specified raw UUID, or null if not found
|
||||||
|
*
|
||||||
|
* @param string $rawUUID
|
||||||
|
*
|
||||||
|
* @return null|Player
|
||||||
*/
|
*/
|
||||||
public function removePlayer(Player $player){
|
public function getPlayerByRawUUID(string $rawUUID) : ?Player{
|
||||||
if(isset($this->identifiers[$hash = spl_object_hash($player)])){
|
return $this->playerList[$rawUUID] ?? null;
|
||||||
$identifier = $this->identifiers[$hash];
|
}
|
||||||
unset($this->players[$identifier]);
|
|
||||||
unset($this->identifiers[$hash]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach($this->players as $identifier => $p){
|
/**
|
||||||
if($player === $p){
|
* Returns the player online with a UUID equivalent to the specified UUID object, or null if not found
|
||||||
unset($this->players[$identifier]);
|
*
|
||||||
unset($this->identifiers[spl_object_hash($player)]);
|
* @param UUID $uuid
|
||||||
break;
|
*
|
||||||
}
|
* @return null|Player
|
||||||
}
|
*/
|
||||||
|
public function getPlayerByUUID(UUID $uuid) : ?Player{
|
||||||
|
return $this->getPlayerByRawUUID($uuid->toBinary());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1024,7 +1003,7 @@ class Server{
|
|||||||
$provider = LevelProviderManager::getProvider($path);
|
$provider = LevelProviderManager::getProvider($path);
|
||||||
|
|
||||||
if($provider === null){
|
if($provider === null){
|
||||||
$this->logger->error($this->getLanguage()->translateString("pocketmine.level.loadError", [$name, "Unknown provider"]));
|
$this->logger->error($this->getLanguage()->translateString("pocketmine.level.loadError", [$name, "Cannot identify format of world"]));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1050,11 +1029,11 @@ class Server{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a new level if it does not exists
|
* Generates a new level if it does not exist
|
||||||
*
|
*
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @param int|null $seed
|
* @param int|null $seed
|
||||||
* @param string|null $generator Class name that extends pocketmine\level\generator\Noise
|
* @param string|null $generator Class name that extends pocketmine\level\generator\Generator
|
||||||
* @param array $options
|
* @param array $options
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
@ -1101,8 +1080,9 @@ class Server{
|
|||||||
|
|
||||||
$this->getLogger()->notice($this->getLanguage()->translateString("pocketmine.level.backgroundGeneration", [$name]));
|
$this->getLogger()->notice($this->getLanguage()->translateString("pocketmine.level.backgroundGeneration", [$name]));
|
||||||
|
|
||||||
$centerX = $level->getSpawnLocation()->getX() >> 4;
|
$spawnLocation = $level->getSpawnLocation();
|
||||||
$centerZ = $level->getSpawnLocation()->getZ() >> 4;
|
$centerX = $spawnLocation->getFloorX() >> 4;
|
||||||
|
$centerZ = $spawnLocation->getFloorZ() >> 4;
|
||||||
|
|
||||||
$order = [];
|
$order = [];
|
||||||
|
|
||||||
@ -1137,10 +1117,9 @@ class Server{
|
|||||||
}
|
}
|
||||||
$path = $this->getDataPath() . "worlds/" . $name . "/";
|
$path = $this->getDataPath() . "worlds/" . $name . "/";
|
||||||
if(!($this->getLevelByName($name) instanceof Level)){
|
if(!($this->getLevelByName($name) instanceof Level)){
|
||||||
|
return is_dir($path) and !empty(array_filter(scandir($path, SCANDIR_SORT_NONE), function($v){
|
||||||
if(LevelProviderManager::getProvider($path) === null){
|
return $v !== ".." and $v !== ".";
|
||||||
return false;
|
}));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1264,24 +1243,12 @@ class Server{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*
|
|
||||||
* @param string $variable
|
|
||||||
* @param bool $defaultValue
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function getConfigBoolean(string $variable, bool $defaultValue = false) : bool{
|
|
||||||
return $this->getConfigBool($variable, $defaultValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $variable
|
* @param string $variable
|
||||||
* @param bool $value
|
* @param bool $value
|
||||||
*/
|
*/
|
||||||
public function setConfigBool(string $variable, bool $value){
|
public function setConfigBool(string $variable, bool $value){
|
||||||
$this->properties->set($variable, $value == true ? "1" : "0");
|
$this->properties->set($variable, $value ? "1" : "0");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1432,6 +1399,9 @@ class Server{
|
|||||||
* @param string $pluginPath
|
* @param string $pluginPath
|
||||||
*/
|
*/
|
||||||
public function __construct(\ClassLoader $autoloader, \ThreadedLogger $logger, string $dataPath, string $pluginPath){
|
public function __construct(\ClassLoader $autoloader, \ThreadedLogger $logger, string $dataPath, string $pluginPath){
|
||||||
|
if(self::$instance !== null){
|
||||||
|
throw new \InvalidStateException("Only one server instance can exist at once");
|
||||||
|
}
|
||||||
self::$instance = $this;
|
self::$instance = $this;
|
||||||
self::$sleeper = new \Threaded;
|
self::$sleeper = new \Threaded;
|
||||||
$this->autoloader = $autoloader;
|
$this->autoloader = $autoloader;
|
||||||
@ -1522,6 +1492,8 @@ class Server{
|
|||||||
if($processors > 0){
|
if($processors > 0){
|
||||||
$poolSize = max(1, $processors);
|
$poolSize = max(1, $processors);
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
$poolSize = (int) $poolSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerScheduler::$WORKERS = $poolSize;
|
ServerScheduler::$WORKERS = $poolSize;
|
||||||
@ -1548,7 +1520,7 @@ class Server{
|
|||||||
|
|
||||||
$this->scheduler = new ServerScheduler();
|
$this->scheduler = new ServerScheduler();
|
||||||
|
|
||||||
if($this->getConfigBool("enable-rcon", false) === true){
|
if($this->getConfigBool("enable-rcon", false)){
|
||||||
try{
|
try{
|
||||||
$this->rcon = new RCON(
|
$this->rcon = new RCON(
|
||||||
$this,
|
$this,
|
||||||
@ -1584,15 +1556,15 @@ class Server{
|
|||||||
|
|
||||||
$this->onlineMode = $this->getConfigBool("xbox-auth", true);
|
$this->onlineMode = $this->getConfigBool("xbox-auth", true);
|
||||||
if($this->onlineMode){
|
if($this->onlineMode){
|
||||||
$this->logger->notice($this->getLanguage()->translateString("pocketmine.server.auth", ["enabled", "will"]));
|
$this->logger->notice($this->getLanguage()->translateString("pocketmine.server.auth.enabled"));
|
||||||
$this->logger->notice($this->getLanguage()->translateString("pocketmine.server.authProperty", ["disable", "false"]));
|
$this->logger->notice($this->getLanguage()->translateString("pocketmine.server.authProperty.enabled"));
|
||||||
}else{
|
}else{
|
||||||
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.auth", ["disabled", "will not"]));
|
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.auth.disabled"));
|
||||||
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.authWarning"));
|
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.authWarning"));
|
||||||
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.authProperty", ["enable", "true"]));
|
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.authProperty.disabled"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->getConfigBool("hardcore", false) === true and $this->getDifficulty() < Level::DIFFICULTY_HARD){
|
if($this->getConfigBool("hardcore", false) and $this->getDifficulty() < Level::DIFFICULTY_HARD){
|
||||||
$this->setConfigInt("difficulty", Level::DIFFICULTY_HARD);
|
$this->setConfigInt("difficulty", Level::DIFFICULTY_HARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1621,6 +1593,7 @@ class Server{
|
|||||||
|
|
||||||
|
|
||||||
Timings::init();
|
Timings::init();
|
||||||
|
TimingsHandler::setEnabled((bool) $this->getProperty("settings.enable-profiling", false));
|
||||||
|
|
||||||
$this->consoleSender = new ConsoleCommandSender();
|
$this->consoleSender = new ConsoleCommandSender();
|
||||||
$this->commandMap = new SimpleCommandMap($this);
|
$this->commandMap = new SimpleCommandMap($this);
|
||||||
@ -1630,16 +1603,15 @@ class Server{
|
|||||||
BlockFactory::init();
|
BlockFactory::init();
|
||||||
Enchantment::init();
|
Enchantment::init();
|
||||||
ItemFactory::init();
|
ItemFactory::init();
|
||||||
|
Item::initCreativeItems();
|
||||||
Biome::init();
|
Biome::init();
|
||||||
Effect::init();
|
|
||||||
Attribute::init();
|
|
||||||
$this->craftingManager = new CraftingManager();
|
$this->craftingManager = new CraftingManager();
|
||||||
|
|
||||||
$this->resourceManager = new ResourcePackManager($this, $this->getDataPath() . "resource_packs" . DIRECTORY_SEPARATOR);
|
$this->resourceManager = new ResourcePackManager($this->getDataPath() . "resource_packs" . DIRECTORY_SEPARATOR);
|
||||||
|
|
||||||
$this->pluginManager = new PluginManager($this, $this->commandMap);
|
$this->pluginManager = new PluginManager($this, $this->commandMap);
|
||||||
$this->pluginManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender);
|
$this->pluginManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender);
|
||||||
$this->pluginManager->setUseTimings($this->getProperty("settings.enable-profiling", false));
|
|
||||||
$this->profilingTickRate = (float) $this->getProperty("settings.profile-report-trigger", 20);
|
$this->profilingTickRate = (float) $this->getProperty("settings.profile-report-trigger", 20);
|
||||||
$this->pluginManager->registerInterface(PharPluginLoader::class);
|
$this->pluginManager->registerInterface(PharPluginLoader::class);
|
||||||
$this->pluginManager->registerInterface(ScriptPluginLoader::class);
|
$this->pluginManager->registerInterface(ScriptPluginLoader::class);
|
||||||
@ -1656,26 +1628,18 @@ class Server{
|
|||||||
|
|
||||||
$this->network->registerInterface(new RakLibInterface($this));
|
$this->network->registerInterface(new RakLibInterface($this));
|
||||||
|
|
||||||
|
LevelProviderManager::init();
|
||||||
LevelProviderManager::addProvider(Anvil::class);
|
|
||||||
LevelProviderManager::addProvider(McRegion::class);
|
|
||||||
LevelProviderManager::addProvider(PMAnvil::class);
|
|
||||||
LevelProviderManager::addProvider(LevelDB::class);
|
|
||||||
if(extension_loaded("leveldb")){
|
if(extension_loaded("leveldb")){
|
||||||
$this->logger->debug($this->getLanguage()->translateString("pocketmine.debug.enable"));
|
$this->logger->debug($this->getLanguage()->translateString("pocketmine.debug.enable"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Generator::addGenerator(Flat::class, "flat");
|
Generator::registerDefaultGenerators();
|
||||||
Generator::addGenerator(Normal::class, "normal");
|
|
||||||
Generator::addGenerator(Normal::class, "default");
|
|
||||||
Generator::addGenerator(Nether::class, "hell");
|
|
||||||
Generator::addGenerator(Nether::class, "nether");
|
|
||||||
|
|
||||||
foreach((array) $this->getProperty("worlds", []) as $name => $options){
|
foreach((array) $this->getProperty("worlds", []) as $name => $options){
|
||||||
if(!is_array($options)){
|
if(!is_array($options)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if($this->loadLevel($name) === false){
|
if(!$this->loadLevel($name)){
|
||||||
$seed = $options["seed"] ?? time();
|
$seed = $options["seed"] ?? time();
|
||||||
if(is_string($seed) and !is_numeric($seed)){
|
if(is_string($seed) and !is_numeric($seed)){
|
||||||
$seed = Utils::javaStringHash($seed);
|
$seed = Utils::javaStringHash($seed);
|
||||||
@ -1704,7 +1668,7 @@ class Server{
|
|||||||
$default = "world";
|
$default = "world";
|
||||||
$this->setConfigString("level-name", "world");
|
$this->setConfigString("level-name", "world");
|
||||||
}
|
}
|
||||||
if($this->loadLevel($default) === false){
|
if(!$this->loadLevel($default)){
|
||||||
$seed = getopt("", ["level-seed::"])["level-seed"] ?? $this->properties->get("level-seed", time());
|
$seed = getopt("", ["level-seed::"])["level-seed"] ?? $this->properties->get("level-seed", time());
|
||||||
if(!is_numeric($seed) or bccomp($seed, "9223372036854775807") > 0){
|
if(!is_numeric($seed) or bccomp($seed, "9223372036854775807") > 0){
|
||||||
$seed = Utils::javaStringHash($seed);
|
$seed = Utils::javaStringHash($seed);
|
||||||
@ -1884,16 +1848,14 @@ class Server{
|
|||||||
* @param bool $immediate
|
* @param bool $immediate
|
||||||
*/
|
*/
|
||||||
public function batchPackets(array $players, array $packets, bool $forceSync = false, bool $immediate = false){
|
public function batchPackets(array $players, array $packets, bool $forceSync = false, bool $immediate = false){
|
||||||
|
if(empty($packets)){
|
||||||
|
throw new \InvalidArgumentException("Cannot send empty batch");
|
||||||
|
}
|
||||||
Timings::$playerNetworkTimer->startTiming();
|
Timings::$playerNetworkTimer->startTiming();
|
||||||
|
|
||||||
$targets = [];
|
$targets = array_filter($players, function(Player $player) : bool{ return $player->isConnected(); });
|
||||||
foreach($players as $p){
|
|
||||||
if($p->isConnected()){
|
|
||||||
$targets[] = $this->identifiers[spl_object_hash($p)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(count($targets) > 0){
|
if(!empty($targets)){
|
||||||
$pk = new BatchPacket();
|
$pk = new BatchPacket();
|
||||||
|
|
||||||
foreach($packets as $p){
|
foreach($packets as $p){
|
||||||
@ -1918,17 +1880,19 @@ class Server{
|
|||||||
Timings::$playerNetworkTimer->stopTiming();
|
Timings::$playerNetworkTimer->stopTiming();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function broadcastPacketsCallback(BatchPacket $pk, array $identifiers, bool $immediate = false){
|
/**
|
||||||
|
* @param BatchPacket $pk
|
||||||
|
* @param Player[] $players
|
||||||
|
* @param bool $immediate
|
||||||
|
*/
|
||||||
|
public function broadcastPacketsCallback(BatchPacket $pk, array $players, bool $immediate = false){
|
||||||
if(!$pk->isEncoded){
|
if(!$pk->isEncoded){
|
||||||
$pk->encode();
|
$pk->encode();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($identifiers as $i){
|
foreach($players as $i){
|
||||||
if(isset($this->players[$i])){
|
$i->sendDataPacket($pk, false, $immediate);
|
||||||
$this->players[$i]->sendDataPacket($pk, false, $immediate);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2004,7 +1968,7 @@ class Server{
|
|||||||
$this->properties->reload();
|
$this->properties->reload();
|
||||||
$this->maxPlayers = $this->getConfigInt("max-players", 20);
|
$this->maxPlayers = $this->getConfigInt("max-players", 20);
|
||||||
|
|
||||||
if($this->getConfigBool("hardcore", false) === true and $this->getDifficulty() < Level::DIFFICULTY_HARD){
|
if($this->getConfigBool("hardcore", false) and $this->getDifficulty() < Level::DIFFICULTY_HARD){
|
||||||
$this->setConfigInt("difficulty", Level::DIFFICULTY_HARD);
|
$this->setConfigInt("difficulty", Level::DIFFICULTY_HARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2049,7 +2013,7 @@ class Server{
|
|||||||
$this->rcon->stop();
|
$this->rcon->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->getProperty("network.upnp-forwarding", false) === true){
|
if($this->getProperty("network.upnp-forwarding", false)){
|
||||||
$this->logger->info("[UPnP] Removing port forward...");
|
$this->logger->info("[UPnP] Removing port forward...");
|
||||||
UPnP::RemovePortForward($this->getPort());
|
UPnP::RemovePortForward($this->getPort());
|
||||||
}
|
}
|
||||||
@ -2089,16 +2053,18 @@ class Server{
|
|||||||
if($this->network instanceof Network){
|
if($this->network instanceof Network){
|
||||||
$this->getLogger()->debug("Stopping network interfaces");
|
$this->getLogger()->debug("Stopping network interfaces");
|
||||||
foreach($this->network->getInterfaces() as $interface){
|
foreach($this->network->getInterfaces() as $interface){
|
||||||
|
$this->getLogger()->debug("Stopping network interface " . get_class($interface));
|
||||||
$interface->shutdown();
|
$interface->shutdown();
|
||||||
$this->network->unregisterInterface($interface);
|
$this->network->unregisterInterface($interface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->getLogger()->debug("Collecting cycles");
|
||||||
gc_collect_cycles();
|
gc_collect_cycles();
|
||||||
}catch(\Throwable $e){
|
}catch(\Throwable $e){
|
||||||
$this->logger->logException($e);
|
$this->logger->logException($e);
|
||||||
$this->logger->emergency("Crashed while crashing, killing process");
|
$this->logger->emergency("Crashed while crashing, killing process");
|
||||||
@kill(getmypid());
|
@Utils::kill(getmypid());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -2113,8 +2079,8 @@ class Server{
|
|||||||
/**
|
/**
|
||||||
* Starts the PocketMine-MP server and starts processing ticks and packets
|
* Starts the PocketMine-MP server and starts processing ticks and packets
|
||||||
*/
|
*/
|
||||||
public function start(){
|
private function start(){
|
||||||
if($this->getConfigBool("enable-query", true) === true){
|
if($this->getConfigBool("enable-query", true)){
|
||||||
$this->queryHandler = new QueryHandler();
|
$this->queryHandler = new QueryHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2130,7 +2096,11 @@ class Server{
|
|||||||
|
|
||||||
if($this->getProperty("network.upnp-forwarding", false)){
|
if($this->getProperty("network.upnp-forwarding", false)){
|
||||||
$this->logger->info("[UPnP] Trying to port forward...");
|
$this->logger->info("[UPnP] Trying to port forward...");
|
||||||
UPnP::PortForward($this->getPort());
|
try{
|
||||||
|
UPnP::PortForward($this->getPort());
|
||||||
|
}catch(\Throwable $e){
|
||||||
|
$this->logger->alert("UPnP portforward failed: " . $e->getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->tickCounter = 0;
|
$this->tickCounter = 0;
|
||||||
@ -2173,24 +2143,21 @@ class Server{
|
|||||||
|
|
||||||
$errstr = $e->getMessage();
|
$errstr = $e->getMessage();
|
||||||
$errfile = $e->getFile();
|
$errfile = $e->getFile();
|
||||||
$errno = $e->getCode();
|
|
||||||
$errline = $e->getLine();
|
$errline = $e->getLine();
|
||||||
|
|
||||||
$type = ($errno === E_ERROR or $errno === E_USER_ERROR) ? \LogLevel::ERROR : (($errno === E_USER_WARNING or $errno === E_WARNING) ? \LogLevel::WARNING : \LogLevel::NOTICE);
|
|
||||||
|
|
||||||
$errstr = preg_replace('/\s+/', ' ', trim($errstr));
|
$errstr = preg_replace('/\s+/', ' ', trim($errstr));
|
||||||
|
|
||||||
$errfile = cleanPath($errfile);
|
$errfile = Utils::cleanPath($errfile);
|
||||||
|
|
||||||
$this->logger->logException($e, $trace);
|
$this->logger->logException($e, $trace);
|
||||||
|
|
||||||
$lastError = [
|
$lastError = [
|
||||||
"type" => $type,
|
"type" => \get_class($e),
|
||||||
"message" => $errstr,
|
"message" => $errstr,
|
||||||
"fullFile" => $e->getFile(),
|
"fullFile" => $e->getFile(),
|
||||||
"file" => $errfile,
|
"file" => $errfile,
|
||||||
"line" => $errline,
|
"line" => $errline,
|
||||||
"trace" => getTrace(0, $trace)
|
"trace" => Utils::getTrace(0, $trace)
|
||||||
];
|
];
|
||||||
|
|
||||||
global $lastExceptionError, $lastError;
|
global $lastExceptionError, $lastError;
|
||||||
@ -2199,7 +2166,7 @@ class Server{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function crashDump(){
|
public function crashDump(){
|
||||||
if($this->isRunning === false){
|
if(!$this->isRunning){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if($this->sendUsageTicker > 0){
|
if($this->sendUsageTicker > 0){
|
||||||
@ -2209,8 +2176,8 @@ class Server{
|
|||||||
|
|
||||||
ini_set("error_reporting", '0');
|
ini_set("error_reporting", '0');
|
||||||
ini_set("memory_limit", '-1'); //Fix error dump not dumped on memory problems
|
ini_set("memory_limit", '-1'); //Fix error dump not dumped on memory problems
|
||||||
$this->logger->emergency($this->getLanguage()->translateString("pocketmine.crash.create"));
|
|
||||||
try{
|
try{
|
||||||
|
$this->logger->emergency($this->getLanguage()->translateString("pocketmine.crash.create"));
|
||||||
$dump = new CrashDump($this);
|
$dump = new CrashDump($this);
|
||||||
|
|
||||||
$this->logger->emergency($this->getLanguage()->translateString("pocketmine.crash.submit", [$dump->getPath()]));
|
$this->logger->emergency($this->getLanguage()->translateString("pocketmine.crash.submit", [$dump->getPath()]));
|
||||||
@ -2252,7 +2219,9 @@ class Server{
|
|||||||
}
|
}
|
||||||
}catch(\Throwable $e){
|
}catch(\Throwable $e){
|
||||||
$this->logger->logException($e);
|
$this->logger->logException($e);
|
||||||
$this->logger->critical($this->getLanguage()->translateString("pocketmine.crash.error", [$e->getMessage()]));
|
try{
|
||||||
|
$this->logger->critical($this->getLanguage()->translateString("pocketmine.crash.error", [$e->getMessage()]));
|
||||||
|
}catch(\Throwable $e){}
|
||||||
}
|
}
|
||||||
|
|
||||||
//$this->checkMemory();
|
//$this->checkMemory();
|
||||||
@ -2260,7 +2229,7 @@ class Server{
|
|||||||
|
|
||||||
$this->forceShutdown();
|
$this->forceShutdown();
|
||||||
$this->isRunning = false;
|
$this->isRunning = false;
|
||||||
@kill(getmypid());
|
@Utils::kill(getmypid());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2291,22 +2260,23 @@ class Server{
|
|||||||
$this->loggedInPlayers[$player->getRawUniqueId()] = $player;
|
$this->loggedInPlayers[$player->getRawUniqueId()] = $player;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onPlayerCompleteLoginSequence(Player $player){
|
|
||||||
$this->sendFullPlayerListData($player);
|
|
||||||
$player->dataPacket($this->craftingManager->getCraftingDataPacket());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onPlayerLogout(Player $player){
|
public function onPlayerLogout(Player $player){
|
||||||
unset($this->loggedInPlayers[$player->getRawUniqueId()]);
|
unset($this->loggedInPlayers[$player->getRawUniqueId()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addPlayer($identifier, Player $player){
|
public function addPlayer(Player $player){
|
||||||
$this->players[$identifier] = $player;
|
$this->players[spl_object_hash($player)] = $player;
|
||||||
$this->identifiers[spl_object_hash($player)] = $identifier;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Player $player
|
||||||
|
*/
|
||||||
|
public function removePlayer(Player $player){
|
||||||
|
unset($this->players[spl_object_hash($player)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addOnlinePlayer(Player $player){
|
public function addOnlinePlayer(Player $player){
|
||||||
$this->updatePlayerListData($player->getUniqueId(), $player->getId(), $player->getDisplayName(), $player->getSkin());
|
$this->updatePlayerListData($player->getUniqueId(), $player->getId(), $player->getDisplayName(), $player->getSkin(), $player->getXuid());
|
||||||
|
|
||||||
$this->playerList[$player->getRawUniqueId()] = $player;
|
$this->playerList[$player->getRawUniqueId()] = $player;
|
||||||
}
|
}
|
||||||
@ -2324,13 +2294,15 @@ class Server{
|
|||||||
* @param int $entityId
|
* @param int $entityId
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @param Skin $skin
|
* @param Skin $skin
|
||||||
|
* @param string $xboxUserId
|
||||||
* @param Player[]|null $players
|
* @param Player[]|null $players
|
||||||
*/
|
*/
|
||||||
public function updatePlayerListData(UUID $uuid, int $entityId, string $name, Skin $skin, array $players = null){
|
public function updatePlayerListData(UUID $uuid, int $entityId, string $name, Skin $skin, string $xboxUserId = "", array $players = null){
|
||||||
$pk = new PlayerListPacket();
|
$pk = new PlayerListPacket();
|
||||||
$pk->type = PlayerListPacket::TYPE_ADD;
|
$pk->type = PlayerListPacket::TYPE_ADD;
|
||||||
|
|
||||||
$pk->entries[] = PlayerListEntry::createAdditionEntry($uuid, $entityId, $name, $skin);
|
$pk->entries[] = PlayerListEntry::createAdditionEntry($uuid, $entityId, $name, "", 0, $skin, $xboxUserId);
|
||||||
|
|
||||||
$this->broadcastPacket($players ?? $this->playerList, $pk);
|
$this->broadcastPacket($players ?? $this->playerList, $pk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2352,7 +2324,7 @@ class Server{
|
|||||||
$pk = new PlayerListPacket();
|
$pk = new PlayerListPacket();
|
||||||
$pk->type = PlayerListPacket::TYPE_ADD;
|
$pk->type = PlayerListPacket::TYPE_ADD;
|
||||||
foreach($this->playerList as $player){
|
foreach($this->playerList as $player){
|
||||||
$pk->entries[] = PlayerListEntry::createAdditionEntry($player->getUniqueId(), $player->getId(), $player->getDisplayName(), $player->getSkin());
|
$pk->entries[] = PlayerListEntry::createAdditionEntry($player->getUniqueId(), $player->getId(), $player->getDisplayName(), "", 0, $player->getSkin(), $player->getXuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
$p->dataPacket($pk);
|
$p->dataPacket($pk);
|
||||||
@ -2481,16 +2453,17 @@ class Server{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $address
|
* @param AdvancedSourceInterface $interface
|
||||||
* @param int $port
|
* @param string $address
|
||||||
* @param string $payload
|
* @param int $port
|
||||||
|
* @param string $payload
|
||||||
*
|
*
|
||||||
* TODO: move this to Network
|
* TODO: move this to Network
|
||||||
*/
|
*/
|
||||||
public function handlePacket(string $address, int $port, string $payload){
|
public function handlePacket(AdvancedSourceInterface $interface, string $address, int $port, string $payload){
|
||||||
try{
|
try{
|
||||||
if(strlen($payload) > 2 and substr($payload, 0, 2) === "\xfe\xfd" and $this->queryHandler instanceof QueryHandler){
|
if(strlen($payload) > 2 and substr($payload, 0, 2) === "\xfe\xfd" and $this->queryHandler instanceof QueryHandler){
|
||||||
$this->queryHandler->handle($address, $port, $payload);
|
$this->queryHandler->handle($interface, $address, $port, $payload);
|
||||||
}
|
}
|
||||||
}catch(\Throwable $e){
|
}catch(\Throwable $e){
|
||||||
if(\pocketmine\DEBUG > 1){
|
if(\pocketmine\DEBUG > 1){
|
||||||
|
@ -30,6 +30,9 @@ abstract class Thread extends \Thread{
|
|||||||
|
|
||||||
/** @var \ClassLoader */
|
/** @var \ClassLoader */
|
||||||
protected $classLoader;
|
protected $classLoader;
|
||||||
|
/** @var string|null */
|
||||||
|
protected $composerAutoloaderPath;
|
||||||
|
|
||||||
protected $isKilled = false;
|
protected $isKilled = false;
|
||||||
|
|
||||||
public function getClassLoader(){
|
public function getClassLoader(){
|
||||||
@ -37,6 +40,8 @@ abstract class Thread extends \Thread{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function setClassLoader(\ClassLoader $loader = null){
|
public function setClassLoader(\ClassLoader $loader = null){
|
||||||
|
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
|
||||||
|
|
||||||
if($loader === null){
|
if($loader === null){
|
||||||
$loader = Server::getInstance()->getLoader();
|
$loader = Server::getInstance()->getLoader();
|
||||||
}
|
}
|
||||||
@ -51,10 +56,8 @@ abstract class Thread extends \Thread{
|
|||||||
* (unless you are using a custom autoloader).
|
* (unless you are using a custom autoloader).
|
||||||
*/
|
*/
|
||||||
public function registerClassLoader(){
|
public function registerClassLoader(){
|
||||||
require(\pocketmine\PATH . "vendor/autoload.php");
|
if($this->composerAutoloaderPath !== null){
|
||||||
if(!interface_exists("ClassLoader", false)){
|
require $this->composerAutoloaderPath;
|
||||||
require(\pocketmine\PATH . "src/spl/ClassLoader.php");
|
|
||||||
require(\pocketmine\PATH . "src/spl/BaseClassLoader.php");
|
|
||||||
}
|
}
|
||||||
if($this->classLoader !== null){
|
if($this->classLoader !== null){
|
||||||
$this->classLoader->register(false);
|
$this->classLoader->register(false);
|
||||||
|
@ -30,6 +30,8 @@ abstract class Worker extends \Worker{
|
|||||||
|
|
||||||
/** @var \ClassLoader */
|
/** @var \ClassLoader */
|
||||||
protected $classLoader;
|
protected $classLoader;
|
||||||
|
/** @var string|null */
|
||||||
|
protected $composerAutoloaderPath;
|
||||||
|
|
||||||
protected $isKilled = false;
|
protected $isKilled = false;
|
||||||
|
|
||||||
@ -38,6 +40,8 @@ abstract class Worker extends \Worker{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function setClassLoader(\ClassLoader $loader = null){
|
public function setClassLoader(\ClassLoader $loader = null){
|
||||||
|
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
|
||||||
|
|
||||||
if($loader === null){
|
if($loader === null){
|
||||||
$loader = Server::getInstance()->getLoader();
|
$loader = Server::getInstance()->getLoader();
|
||||||
}
|
}
|
||||||
@ -52,10 +56,8 @@ abstract class Worker extends \Worker{
|
|||||||
* (unless you are using a custom autoloader).
|
* (unless you are using a custom autoloader).
|
||||||
*/
|
*/
|
||||||
public function registerClassLoader(){
|
public function registerClassLoader(){
|
||||||
require(\pocketmine\PATH . "vendor/autoload.php");
|
if($this->composerAutoloaderPath !== null){
|
||||||
if(!interface_exists("ClassLoader", false)){
|
require $this->composerAutoloaderPath;
|
||||||
require(\pocketmine\PATH . "src/spl/ClassLoader.php");
|
|
||||||
require(\pocketmine\PATH . "src/spl/BaseClassLoader.php");
|
|
||||||
}
|
}
|
||||||
if($this->classLoader !== null){
|
if($this->classLoader !== null){
|
||||||
$this->classLoader->register(false);
|
$this->classLoader->register(false);
|
||||||
|
@ -26,7 +26,7 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\inventory\AnvilInventory;
|
use pocketmine\inventory\AnvilInventory;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
@ -65,7 +65,11 @@ class Anvil extends Fallable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function recalculateBoundingBox() : ?AxisAlignedBB{
|
public function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
@ -106,13 +110,9 @@ class Anvil extends Fallable{
|
|||||||
return $this->getLevel()->setBlock($blockReplace, $this, true, true);
|
return $this->getLevel()->setBlock($blockReplace, $this, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
return [
|
||||||
return [
|
ItemFactory::get($this->getItemId(), $this->getDamage() >> 2)
|
||||||
ItemFactory::get($this->getItemId(), $this->getDamage() & 0x0c, 1)
|
];
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -23,9 +23,9 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\event\TranslationContainer;
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
|
use pocketmine\lang\TranslationContainer;
|
||||||
use pocketmine\level\Level;
|
use pocketmine\level\Level;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
@ -176,7 +176,7 @@ class Bed extends Transparent{
|
|||||||
if(!$down->isTransparent()){
|
if(!$down->isTransparent()){
|
||||||
$meta = (($player instanceof Player ? $player->getDirection() : 0) - 1) & 0x03;
|
$meta = (($player instanceof Player ? $player->getDirection() : 0) - 1) & 0x03;
|
||||||
$next = $this->getSide(self::getOtherHalfSide($meta));
|
$next = $this->getSide(self::getOtherHalfSide($meta));
|
||||||
if($next->canBeReplaced() === true and !$next->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
if($next->canBeReplaced() and !$next->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||||
$this->getLevel()->setBlock($blockReplace, BlockFactory::get($this->id, $meta), true, true);
|
$this->getLevel()->setBlock($blockReplace, BlockFactory::get($this->id, $meta), true, true);
|
||||||
$this->getLevel()->setBlock($next, BlockFactory::get($this->id, $meta | self::BITFLAG_HEAD), true, true);
|
$this->getLevel()->setBlock($next, BlockFactory::get($this->id, $meta | self::BITFLAG_HEAD), true, true);
|
||||||
|
|
||||||
@ -190,25 +190,16 @@ class Bed extends Transparent{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onBreak(Item $item, Player $player = null) : bool{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
|
|
||||||
if(($other = $this->getOtherHalf()) !== null){
|
|
||||||
$this->getLevel()->useBreakOn($other, $item, null, $player !== null); //make sure tiles get removed
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
|
||||||
if($this->isHeadPart()){
|
if($this->isHeadPart()){
|
||||||
$tile = $this->getLevel()->getTile($this);
|
$tile = $this->getLevel()->getTile($this);
|
||||||
if($tile instanceof TileBed){
|
if($tile instanceof TileBed){
|
||||||
return [
|
return [
|
||||||
ItemFactory::get($this->getItemId(), $tile->getColor(), 1)
|
ItemFactory::get($this->getItemId(), $tile->getColor())
|
||||||
];
|
];
|
||||||
}else{
|
}else{
|
||||||
return [
|
return [
|
||||||
ItemFactory::get($this->getItemId(), 14, 1) //Red
|
ItemFactory::get($this->getItemId(), 14) //Red
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -216,4 +207,15 @@ class Bed extends Transparent{
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isAffectedBySilkTouch() : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAffectedBlocks() : array{
|
||||||
|
if(($other = $this->getOtherHalf()) !== null){
|
||||||
|
return [$this, $other];
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::getAffectedBlocks();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,16 +38,16 @@ class Beetroot extends Crops{
|
|||||||
return "Beetroot Block";
|
return "Beetroot Block";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
if($this->meta >= 0x07){
|
if($this->meta >= 0x07){
|
||||||
return [
|
return [
|
||||||
ItemFactory::get(Item::BEETROOT, 0, 1),
|
ItemFactory::get(Item::BEETROOT),
|
||||||
ItemFactory::get(Item::BEETROOT_SEEDS, 0, mt_rand(0, 3))
|
ItemFactory::get(Item::BEETROOT_SEEDS, 0, mt_rand(0, 3))
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
ItemFactory::get(Item::BEETROOT_SEEDS, 0, 1)
|
ItemFactory::get(Item::BEETROOT_SEEDS)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,13 +27,12 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
|
use pocketmine\item\enchantment\Enchantment;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\level\MovingObjectPosition;
|
|
||||||
use pocketmine\level\Position;
|
use pocketmine\level\Position;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
|
use pocketmine\math\RayTraceResult;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\metadata\Metadatable;
|
use pocketmine\metadata\Metadatable;
|
||||||
use pocketmine\metadata\MetadataValue;
|
use pocketmine\metadata\MetadataValue;
|
||||||
@ -195,8 +194,49 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function canBeBrokenWith(Item $item) : bool{
|
/**
|
||||||
return $this->getHardness() !== -1;
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getToolType() : int{
|
||||||
|
return BlockToolType::TYPE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the level of tool required to harvest this block (for normal blocks). When the tool type matches the
|
||||||
|
* block's required tool type, the tool must have a harvest level greater than or equal to this value to be able to
|
||||||
|
* successfully harvest the block.
|
||||||
|
*
|
||||||
|
* If the block requires a specific minimum tier of tiered tool, the minimum tier required should be returned.
|
||||||
|
* Otherwise, 1 should be returned if a tool is required, 0 if not.
|
||||||
|
*
|
||||||
|
* @see Item::getBlockToolHarvestLevel()
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the specified item is the proper tool to use for breaking this block. This checks tool type and
|
||||||
|
* harvest level requirement.
|
||||||
|
*
|
||||||
|
* In most cases this is also used to determine whether block drops should be created or not, except in some
|
||||||
|
* special cases such as vines.
|
||||||
|
*
|
||||||
|
* @param Item $tool
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isCompatibleWithTool(Item $tool) : bool{
|
||||||
|
if($this->getHardness() < 0){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$toolType = $this->getToolType();
|
||||||
|
$harvestLevel = $this->getToolHarvestLevel();
|
||||||
|
return $toolType === BlockToolType::TYPE_NONE or $harvestLevel === 0 or (
|
||||||
|
($toolType & $tool->getBlockToolType()) !== 0 and $tool->getBlockToolHarvestLevel() >= $harvestLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -220,44 +260,29 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
public function getBreakTime(Item $item) : float{
|
public function getBreakTime(Item $item) : float{
|
||||||
$base = $this->getHardness() * 1.5;
|
$base = $this->getHardness();
|
||||||
if($this->canBeBrokenWith($item)){
|
if($this->isCompatibleWithTool($item)){
|
||||||
if($this->getToolType() === Tool::TYPE_SHEARS and $item->isShears()){
|
$base *= 1.5;
|
||||||
$base /= 15;
|
|
||||||
}elseif(
|
|
||||||
($this->getToolType() === Tool::TYPE_PICKAXE and ($tier = $item->isPickaxe()) !== false) or
|
|
||||||
($this->getToolType() === Tool::TYPE_AXE and ($tier = $item->isAxe()) !== false) or
|
|
||||||
($this->getToolType() === Tool::TYPE_SHOVEL and ($tier = $item->isShovel()) !== false)
|
|
||||||
){
|
|
||||||
switch($tier){
|
|
||||||
case Tool::TIER_WOODEN:
|
|
||||||
$base /= 2;
|
|
||||||
break;
|
|
||||||
case Tool::TIER_STONE:
|
|
||||||
$base /= 4;
|
|
||||||
break;
|
|
||||||
case Tool::TIER_IRON:
|
|
||||||
$base /= 6;
|
|
||||||
break;
|
|
||||||
case Tool::TIER_DIAMOND:
|
|
||||||
$base /= 8;
|
|
||||||
break;
|
|
||||||
case Tool::TIER_GOLD:
|
|
||||||
$base /= 12;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else{
|
}else{
|
||||||
$base *= 3.33;
|
$base *= 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($item->isSword()){
|
$efficiency = $item->getMiningEfficiency($this);
|
||||||
$base /= 1.5;
|
if($efficiency <= 0){
|
||||||
|
throw new \RuntimeException("Item efficiency is invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$base /= $efficiency;
|
||||||
|
|
||||||
return $base;
|
return $base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when this block or a block immediately adjacent to it changes state.
|
||||||
|
*/
|
||||||
|
public function onNearbyBlockChange() : void{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether random block updates will be done on this block.
|
* Returns whether random block updates will be done on this block.
|
||||||
@ -269,14 +294,18 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fires a block update on the Block
|
* Called when this block is randomly updated due to chunk ticking.
|
||||||
*
|
* WARNING: This will not be called if ticksRandomly() does not return true!
|
||||||
* @param int $type
|
|
||||||
*
|
|
||||||
* @return bool|int
|
|
||||||
*/
|
*/
|
||||||
public function onUpdate(int $type){
|
public function onRandomTick() : void{
|
||||||
return false;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when this block is updated by the delayed blockupdate scheduler in the level.
|
||||||
|
*/
|
||||||
|
public function onScheduledUpdate() : void{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -299,14 +328,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
* @return float
|
|
||||||
*/
|
|
||||||
public function getResistance() : float{
|
|
||||||
return $this->getBlastResistance();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the block's resistance to explosions. Usually 5x hardness.
|
* Returns the block's resistance to explosions. Usually 5x hardness.
|
||||||
* @return float
|
* @return float
|
||||||
@ -315,13 +336,6 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
return $this->getHardness() * 5;
|
return $this->getHardness() * 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function getToolType() : int{
|
|
||||||
return Tool::TYPE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
@ -420,11 +434,53 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
* @return Item[]
|
* @return Item[]
|
||||||
*/
|
*/
|
||||||
public function getDrops(Item $item) : array{
|
public function getDrops(Item $item) : array{
|
||||||
|
if($this->isCompatibleWithTool($item)){
|
||||||
|
if($this->isAffectedBySilkTouch() and $item->hasEnchantment(Enchantment::SILK_TOUCH)){
|
||||||
|
return $this->getSilkTouchDrops($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->getDropsForCompatibleTool($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of Items to be dropped when the block is broken using the correct tool type.
|
||||||
|
*
|
||||||
|
* @param Item $item
|
||||||
|
*
|
||||||
|
* @return Item[]
|
||||||
|
*/
|
||||||
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [
|
return [
|
||||||
ItemFactory::get($this->getItemId(), $this->getVariant(), 1)
|
ItemFactory::get($this->getItemId(), $this->getVariant())
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of Items to be dropped when the block is broken using a compatible Silk Touch-enchanted tool.
|
||||||
|
*
|
||||||
|
* @param Item $item
|
||||||
|
*
|
||||||
|
* @return Item[]
|
||||||
|
*/
|
||||||
|
public function getSilkTouchDrops(Item $item) : array{
|
||||||
|
return [
|
||||||
|
ItemFactory::get($this->getItemId(), $this->getVariant())
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether Silk Touch enchanted tools will cause this block to drop as itself. Since most blocks drop
|
||||||
|
* themselves anyway, this is implicitly true.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isAffectedBySilkTouch() : bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the item that players will equip when middle-clicking on this block.
|
* Returns the item that players will equip when middle-clicking on this block.
|
||||||
* @return Item
|
* @return Item
|
||||||
@ -441,6 +497,50 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the chance that the block will catch fire from nearby fire sources. Higher values lead to faster catching
|
||||||
|
* fire.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getFlameEncouragement() : int{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the base flammability of this block. Higher values lead to the block burning away more quickly.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether fire lit on this block will burn indefinitely.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function burnsForever() : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this block can catch fire.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isFlammable() : bool{
|
||||||
|
return $this->getFlammability() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when this block is burned away by being on fire.
|
||||||
|
*/
|
||||||
|
public function onIncinerate() : void{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Block on the side $side, works like Vector3::getSide()
|
* Returns the Block on the side $side, works like Vector3::getSide()
|
||||||
*
|
*
|
||||||
@ -449,7 +549,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
*
|
*
|
||||||
* @return Block
|
* @return Block
|
||||||
*/
|
*/
|
||||||
public function getSide($side, $step = 1){
|
public function getSide(int $side, int $step = 1){
|
||||||
if($this->isValid()){
|
if($this->isValid()){
|
||||||
return $this->getLevel()->getBlock(Vector3::getSide($side, $step));
|
return $this->getLevel()->getBlock(Vector3::getSide($side, $step));
|
||||||
}
|
}
|
||||||
@ -486,6 +586,16 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of blocks that this block is part of. In most cases, only contains the block itself, but in cases
|
||||||
|
* such as double plants, beds and doors, will contain both halves.
|
||||||
|
*
|
||||||
|
* @return Block[]
|
||||||
|
*/
|
||||||
|
public function getAffectedBlocks() : array{
|
||||||
|
return [$this];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@ -501,9 +611,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function collidesWithBB(AxisAlignedBB $bb) : bool{
|
public function collidesWithBB(AxisAlignedBB $bb) : bool{
|
||||||
$bbs = $this->getCollisionBoxes();
|
foreach($this->getCollisionBoxes() as $bb2){
|
||||||
|
|
||||||
foreach($bbs as $bb2){
|
|
||||||
if($bb->intersectsWith($bb2)){
|
if($bb->intersectsWith($bb2)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -578,15 +686,15 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
* @param Vector3 $pos1
|
* @param Vector3 $pos1
|
||||||
* @param Vector3 $pos2
|
* @param Vector3 $pos2
|
||||||
*
|
*
|
||||||
* @return MovingObjectPosition|null
|
* @return RayTraceResult|null
|
||||||
*/
|
*/
|
||||||
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?MovingObjectPosition{
|
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{
|
||||||
$bbs = $this->getCollisionBoxes();
|
$bbs = $this->getCollisionBoxes();
|
||||||
if(empty($bbs)){
|
if(empty($bbs)){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var MovingObjectPosition|null $currentHit */
|
/** @var RayTraceResult|null $currentHit */
|
||||||
$currentHit = null;
|
$currentHit = null;
|
||||||
/** @var int|float $currentDistance */
|
/** @var int|float $currentDistance */
|
||||||
$currentDistance = PHP_INT_MAX;
|
$currentDistance = PHP_INT_MAX;
|
||||||
@ -604,40 +712,34 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($currentHit !== null){
|
|
||||||
$currentHit->blockX = $this->x;
|
|
||||||
$currentHit->blockY = $this->y;
|
|
||||||
$currentHit->blockZ = $this->z;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $currentHit;
|
return $currentHit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setMetadata(string $metadataKey, MetadataValue $newMetadataValue){
|
public function setMetadata(string $metadataKey, MetadataValue $newMetadataValue){
|
||||||
if($this->getLevel() instanceof Level){
|
if($this->isValid()){
|
||||||
$this->getLevel()->getBlockMetadata()->setMetadata($this, $metadataKey, $newMetadataValue);
|
$this->level->getBlockMetadata()->setMetadata($this, $metadataKey, $newMetadataValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMetadata(string $metadataKey){
|
public function getMetadata(string $metadataKey){
|
||||||
if($this->getLevel() instanceof Level){
|
if($this->isValid()){
|
||||||
return $this->getLevel()->getBlockMetadata()->getMetadata($this, $metadataKey);
|
return $this->level->getBlockMetadata()->getMetadata($this, $metadataKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasMetadata(string $metadataKey) : bool{
|
public function hasMetadata(string $metadataKey) : bool{
|
||||||
if($this->getLevel() instanceof Level){
|
if($this->isValid()){
|
||||||
return $this->getLevel()->getBlockMetadata()->hasMetadata($this, $metadataKey);
|
return $this->level->getBlockMetadata()->hasMetadata($this, $metadataKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function removeMetadata(string $metadataKey, Plugin $owningPlugin){
|
public function removeMetadata(string $metadataKey, Plugin $owningPlugin){
|
||||||
if($this->getLevel() instanceof Level){
|
if($this->isValid()){
|
||||||
$this->getLevel()->getBlockMetadata()->removeMetadata($this, $metadataKey, $owningPlugin);
|
$this->level->getBlockMetadata()->removeMetadata($this, $metadataKey, $owningPlugin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Position;
|
use pocketmine\level\Position;
|
||||||
|
use pocketmine\utils\MainLogger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages block registration and instance creation
|
* Manages block registration and instance creation
|
||||||
@ -50,282 +51,293 @@ class BlockFactory{
|
|||||||
/** @var \SplFixedArray<float> */
|
/** @var \SplFixedArray<float> */
|
||||||
public static $blastResistance = null;
|
public static $blastResistance = null;
|
||||||
|
|
||||||
|
/** @var int[] */
|
||||||
|
public static $staticRuntimeIdMap = [];
|
||||||
|
|
||||||
|
/** @var int[] */
|
||||||
|
public static $legacyIdMap = [];
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
private static $lastRuntimeId = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the block factory. By default this is called only once on server start, however you may wish to use
|
* Initializes the block factory. By default this is called only once on server start, however you may wish to use
|
||||||
* this if you need to reset the block factory back to its original defaults for whatever reason.
|
* this if you need to reset the block factory back to its original defaults for whatever reason.
|
||||||
*
|
|
||||||
* @param bool $force
|
|
||||||
*/
|
*/
|
||||||
public static function init(bool $force = false) : void{
|
public static function init() : void{
|
||||||
if(self::$list === null or $force){
|
self::$list = new \SplFixedArray(256);
|
||||||
self::$list = new \SplFixedArray(256);
|
self::$fullList = new \SplFixedArray(4096);
|
||||||
self::$fullList = new \SplFixedArray(4096);
|
|
||||||
|
|
||||||
self::$light = new \SplFixedArray(256);
|
self::$light = new \SplFixedArray(256);
|
||||||
self::$lightFilter = new \SplFixedArray(256);
|
self::$lightFilter = new \SplFixedArray(256);
|
||||||
self::$solid = new \SplFixedArray(256);
|
self::$solid = new \SplFixedArray(256);
|
||||||
self::$hardness = new \SplFixedArray(256);
|
self::$hardness = new \SplFixedArray(256);
|
||||||
self::$transparent = new \SplFixedArray(256);
|
self::$transparent = new \SplFixedArray(256);
|
||||||
self::$diffusesSkyLight = new \SplFixedArray(256);
|
self::$diffusesSkyLight = new \SplFixedArray(256);
|
||||||
self::$blastResistance = new \SplFixedArray(256);
|
self::$blastResistance = new \SplFixedArray(256);
|
||||||
|
|
||||||
self::registerBlock(new Air());
|
self::registerBlock(new Air());
|
||||||
self::registerBlock(new Stone());
|
self::registerBlock(new Stone());
|
||||||
self::registerBlock(new Grass());
|
self::registerBlock(new Grass());
|
||||||
self::registerBlock(new Dirt());
|
self::registerBlock(new Dirt());
|
||||||
self::registerBlock(new Cobblestone());
|
self::registerBlock(new Cobblestone());
|
||||||
self::registerBlock(new Planks());
|
self::registerBlock(new Planks());
|
||||||
self::registerBlock(new Sapling());
|
self::registerBlock(new Sapling());
|
||||||
self::registerBlock(new Bedrock());
|
self::registerBlock(new Bedrock());
|
||||||
self::registerBlock(new Water());
|
self::registerBlock(new Water());
|
||||||
self::registerBlock(new StillWater());
|
self::registerBlock(new StillWater());
|
||||||
self::registerBlock(new Lava());
|
self::registerBlock(new Lava());
|
||||||
self::registerBlock(new StillLava());
|
self::registerBlock(new StillLava());
|
||||||
self::registerBlock(new Sand());
|
self::registerBlock(new Sand());
|
||||||
self::registerBlock(new Gravel());
|
self::registerBlock(new Gravel());
|
||||||
self::registerBlock(new GoldOre());
|
self::registerBlock(new GoldOre());
|
||||||
self::registerBlock(new IronOre());
|
self::registerBlock(new IronOre());
|
||||||
self::registerBlock(new CoalOre());
|
self::registerBlock(new CoalOre());
|
||||||
self::registerBlock(new Wood());
|
self::registerBlock(new Wood());
|
||||||
self::registerBlock(new Leaves());
|
self::registerBlock(new Leaves());
|
||||||
self::registerBlock(new Sponge());
|
self::registerBlock(new Sponge());
|
||||||
self::registerBlock(new Glass());
|
self::registerBlock(new Glass());
|
||||||
self::registerBlock(new LapisOre());
|
self::registerBlock(new LapisOre());
|
||||||
self::registerBlock(new Lapis());
|
self::registerBlock(new Lapis());
|
||||||
//TODO: DISPENSER
|
//TODO: DISPENSER
|
||||||
self::registerBlock(new Sandstone());
|
self::registerBlock(new Sandstone());
|
||||||
self::registerBlock(new NoteBlock());
|
self::registerBlock(new NoteBlock());
|
||||||
self::registerBlock(new Bed());
|
self::registerBlock(new Bed());
|
||||||
self::registerBlock(new PoweredRail());
|
self::registerBlock(new PoweredRail());
|
||||||
self::registerBlock(new DetectorRail());
|
self::registerBlock(new DetectorRail());
|
||||||
//TODO: STICKY_PISTON
|
//TODO: STICKY_PISTON
|
||||||
self::registerBlock(new Cobweb());
|
self::registerBlock(new Cobweb());
|
||||||
self::registerBlock(new TallGrass());
|
self::registerBlock(new TallGrass());
|
||||||
self::registerBlock(new DeadBush());
|
self::registerBlock(new DeadBush());
|
||||||
//TODO: PISTON
|
//TODO: PISTON
|
||||||
//TODO: PISTONARMCOLLISION
|
//TODO: PISTONARMCOLLISION
|
||||||
self::registerBlock(new Wool());
|
self::registerBlock(new Wool());
|
||||||
|
|
||||||
self::registerBlock(new Dandelion());
|
self::registerBlock(new Dandelion());
|
||||||
self::registerBlock(new Flower());
|
self::registerBlock(new Flower());
|
||||||
self::registerBlock(new BrownMushroom());
|
self::registerBlock(new BrownMushroom());
|
||||||
self::registerBlock(new RedMushroom());
|
self::registerBlock(new RedMushroom());
|
||||||
self::registerBlock(new Gold());
|
self::registerBlock(new Gold());
|
||||||
self::registerBlock(new Iron());
|
self::registerBlock(new Iron());
|
||||||
self::registerBlock(new DoubleStoneSlab());
|
self::registerBlock(new DoubleStoneSlab());
|
||||||
self::registerBlock(new StoneSlab());
|
self::registerBlock(new StoneSlab());
|
||||||
self::registerBlock(new Bricks());
|
self::registerBlock(new Bricks());
|
||||||
self::registerBlock(new TNT());
|
self::registerBlock(new TNT());
|
||||||
self::registerBlock(new Bookshelf());
|
self::registerBlock(new Bookshelf());
|
||||||
self::registerBlock(new MossyCobblestone());
|
self::registerBlock(new MossyCobblestone());
|
||||||
self::registerBlock(new Obsidian());
|
self::registerBlock(new Obsidian());
|
||||||
self::registerBlock(new Torch());
|
self::registerBlock(new Torch());
|
||||||
self::registerBlock(new Fire());
|
self::registerBlock(new Fire());
|
||||||
self::registerBlock(new MonsterSpawner());
|
self::registerBlock(new MonsterSpawner());
|
||||||
self::registerBlock(new WoodenStairs(Block::OAK_STAIRS, 0, "Oak Stairs"));
|
self::registerBlock(new WoodenStairs(Block::OAK_STAIRS, 0, "Oak Stairs"));
|
||||||
self::registerBlock(new Chest());
|
self::registerBlock(new Chest());
|
||||||
//TODO: REDSTONE_WIRE
|
//TODO: REDSTONE_WIRE
|
||||||
self::registerBlock(new DiamondOre());
|
self::registerBlock(new DiamondOre());
|
||||||
self::registerBlock(new Diamond());
|
self::registerBlock(new Diamond());
|
||||||
self::registerBlock(new CraftingTable());
|
self::registerBlock(new CraftingTable());
|
||||||
self::registerBlock(new Wheat());
|
self::registerBlock(new Wheat());
|
||||||
self::registerBlock(new Farmland());
|
self::registerBlock(new Farmland());
|
||||||
self::registerBlock(new Furnace());
|
self::registerBlock(new Furnace());
|
||||||
self::registerBlock(new BurningFurnace());
|
self::registerBlock(new BurningFurnace());
|
||||||
self::registerBlock(new SignPost());
|
self::registerBlock(new SignPost());
|
||||||
self::registerBlock(new WoodenDoor(Block::OAK_DOOR_BLOCK, 0, "Oak Door", Item::OAK_DOOR));
|
self::registerBlock(new WoodenDoor(Block::OAK_DOOR_BLOCK, 0, "Oak Door", Item::OAK_DOOR));
|
||||||
self::registerBlock(new Ladder());
|
self::registerBlock(new Ladder());
|
||||||
self::registerBlock(new Rail());
|
self::registerBlock(new Rail());
|
||||||
self::registerBlock(new CobblestoneStairs());
|
self::registerBlock(new CobblestoneStairs());
|
||||||
self::registerBlock(new WallSign());
|
self::registerBlock(new WallSign());
|
||||||
self::registerBlock(new Lever());
|
self::registerBlock(new Lever());
|
||||||
self::registerBlock(new StonePressurePlate());
|
self::registerBlock(new StonePressurePlate());
|
||||||
self::registerBlock(new IronDoor());
|
self::registerBlock(new IronDoor());
|
||||||
self::registerBlock(new WoodenPressurePlate());
|
self::registerBlock(new WoodenPressurePlate());
|
||||||
self::registerBlock(new RedstoneOre());
|
self::registerBlock(new RedstoneOre());
|
||||||
self::registerBlock(new GlowingRedstoneOre());
|
self::registerBlock(new GlowingRedstoneOre());
|
||||||
self::registerBlock(new RedstoneTorchUnlit());
|
self::registerBlock(new RedstoneTorchUnlit());
|
||||||
self::registerBlock(new RedstoneTorch());
|
self::registerBlock(new RedstoneTorch());
|
||||||
self::registerBlock(new StoneButton());
|
self::registerBlock(new StoneButton());
|
||||||
self::registerBlock(new SnowLayer());
|
self::registerBlock(new SnowLayer());
|
||||||
self::registerBlock(new Ice());
|
self::registerBlock(new Ice());
|
||||||
self::registerBlock(new Snow());
|
self::registerBlock(new Snow());
|
||||||
self::registerBlock(new Cactus());
|
self::registerBlock(new Cactus());
|
||||||
self::registerBlock(new Clay());
|
self::registerBlock(new Clay());
|
||||||
self::registerBlock(new Sugarcane());
|
self::registerBlock(new Sugarcane());
|
||||||
//TODO: JUKEBOX
|
//TODO: JUKEBOX
|
||||||
self::registerBlock(new WoodenFence());
|
self::registerBlock(new WoodenFence());
|
||||||
self::registerBlock(new Pumpkin());
|
self::registerBlock(new Pumpkin());
|
||||||
self::registerBlock(new Netherrack());
|
self::registerBlock(new Netherrack());
|
||||||
self::registerBlock(new SoulSand());
|
self::registerBlock(new SoulSand());
|
||||||
self::registerBlock(new Glowstone());
|
self::registerBlock(new Glowstone());
|
||||||
//TODO: PORTAL
|
//TODO: PORTAL
|
||||||
self::registerBlock(new LitPumpkin());
|
self::registerBlock(new LitPumpkin());
|
||||||
self::registerBlock(new Cake());
|
self::registerBlock(new Cake());
|
||||||
//TODO: REPEATER_BLOCK
|
//TODO: REPEATER_BLOCK
|
||||||
//TODO: POWERED_REPEATER
|
//TODO: POWERED_REPEATER
|
||||||
//TODO: INVISIBLEBEDROCK
|
//TODO: INVISIBLEBEDROCK
|
||||||
self::registerBlock(new Trapdoor());
|
self::registerBlock(new Trapdoor());
|
||||||
//TODO: MONSTER_EGG
|
//TODO: MONSTER_EGG
|
||||||
self::registerBlock(new StoneBricks());
|
self::registerBlock(new StoneBricks());
|
||||||
self::registerBlock(new BrownMushroomBlock());
|
self::registerBlock(new BrownMushroomBlock());
|
||||||
self::registerBlock(new RedMushroomBlock());
|
self::registerBlock(new RedMushroomBlock());
|
||||||
self::registerBlock(new IronBars());
|
self::registerBlock(new IronBars());
|
||||||
self::registerBlock(new GlassPane());
|
self::registerBlock(new GlassPane());
|
||||||
self::registerBlock(new Melon());
|
self::registerBlock(new Melon());
|
||||||
self::registerBlock(new PumpkinStem());
|
self::registerBlock(new PumpkinStem());
|
||||||
self::registerBlock(new MelonStem());
|
self::registerBlock(new MelonStem());
|
||||||
self::registerBlock(new Vine());
|
self::registerBlock(new Vine());
|
||||||
self::registerBlock(new FenceGate(Block::OAK_FENCE_GATE, 0, "Oak Fence Gate"));
|
self::registerBlock(new FenceGate(Block::OAK_FENCE_GATE, 0, "Oak Fence Gate"));
|
||||||
self::registerBlock(new BrickStairs());
|
self::registerBlock(new BrickStairs());
|
||||||
self::registerBlock(new StoneBrickStairs());
|
self::registerBlock(new StoneBrickStairs());
|
||||||
self::registerBlock(new Mycelium());
|
self::registerBlock(new Mycelium());
|
||||||
self::registerBlock(new WaterLily());
|
self::registerBlock(new WaterLily());
|
||||||
self::registerBlock(new NetherBrick(Block::NETHER_BRICK_BLOCK, 0, "Nether Bricks"));
|
self::registerBlock(new NetherBrick(Block::NETHER_BRICK_BLOCK, 0, "Nether Bricks"));
|
||||||
self::registerBlock(new NetherBrickFence());
|
self::registerBlock(new NetherBrickFence());
|
||||||
self::registerBlock(new NetherBrickStairs());
|
self::registerBlock(new NetherBrickStairs());
|
||||||
self::registerBlock(new NetherWartPlant());
|
self::registerBlock(new NetherWartPlant());
|
||||||
self::registerBlock(new EnchantingTable());
|
self::registerBlock(new EnchantingTable());
|
||||||
self::registerBlock(new BrewingStand());
|
self::registerBlock(new BrewingStand());
|
||||||
//TODO: CAULDRON_BLOCK
|
//TODO: CAULDRON_BLOCK
|
||||||
//TODO: END_PORTAL
|
//TODO: END_PORTAL
|
||||||
self::registerBlock(new EndPortalFrame());
|
self::registerBlock(new EndPortalFrame());
|
||||||
self::registerBlock(new EndStone());
|
self::registerBlock(new EndStone());
|
||||||
//TODO: DRAGON_EGG
|
//TODO: DRAGON_EGG
|
||||||
self::registerBlock(new RedstoneLamp());
|
self::registerBlock(new RedstoneLamp());
|
||||||
self::registerBlock(new LitRedstoneLamp());
|
self::registerBlock(new LitRedstoneLamp());
|
||||||
//TODO: DROPPER
|
//TODO: DROPPER
|
||||||
self::registerBlock(new ActivatorRail());
|
self::registerBlock(new ActivatorRail());
|
||||||
self::registerBlock(new CocoaBlock());
|
self::registerBlock(new CocoaBlock());
|
||||||
self::registerBlock(new SandstoneStairs());
|
self::registerBlock(new SandstoneStairs());
|
||||||
self::registerBlock(new EmeraldOre());
|
self::registerBlock(new EmeraldOre());
|
||||||
self::registerBlock(new EnderChest());
|
self::registerBlock(new EnderChest());
|
||||||
self::registerBlock(new TripwireHook());
|
self::registerBlock(new TripwireHook());
|
||||||
self::registerBlock(new Tripwire());
|
self::registerBlock(new Tripwire());
|
||||||
self::registerBlock(new Emerald());
|
self::registerBlock(new Emerald());
|
||||||
self::registerBlock(new WoodenStairs(Block::SPRUCE_STAIRS, 0, "Spruce Stairs"));
|
self::registerBlock(new WoodenStairs(Block::SPRUCE_STAIRS, 0, "Spruce Stairs"));
|
||||||
self::registerBlock(new WoodenStairs(Block::BIRCH_STAIRS, 0, "Birch Stairs"));
|
self::registerBlock(new WoodenStairs(Block::BIRCH_STAIRS, 0, "Birch Stairs"));
|
||||||
self::registerBlock(new WoodenStairs(Block::JUNGLE_STAIRS, 0, "Jungle Stairs"));
|
self::registerBlock(new WoodenStairs(Block::JUNGLE_STAIRS, 0, "Jungle Stairs"));
|
||||||
//TODO: COMMAND_BLOCK
|
//TODO: COMMAND_BLOCK
|
||||||
//TODO: BEACON
|
//TODO: BEACON
|
||||||
self::registerBlock(new CobblestoneWall());
|
self::registerBlock(new CobblestoneWall());
|
||||||
self::registerBlock(new FlowerPot());
|
self::registerBlock(new FlowerPot());
|
||||||
self::registerBlock(new Carrot());
|
self::registerBlock(new Carrot());
|
||||||
self::registerBlock(new Potato());
|
self::registerBlock(new Potato());
|
||||||
self::registerBlock(new WoodenButton());
|
self::registerBlock(new WoodenButton());
|
||||||
self::registerBlock(new Skull());
|
self::registerBlock(new Skull());
|
||||||
self::registerBlock(new Anvil());
|
self::registerBlock(new Anvil());
|
||||||
self::registerBlock(new TrappedChest());
|
self::registerBlock(new TrappedChest());
|
||||||
self::registerBlock(new WeightedPressurePlateLight());
|
self::registerBlock(new WeightedPressurePlateLight());
|
||||||
self::registerBlock(new WeightedPressurePlateHeavy());
|
self::registerBlock(new WeightedPressurePlateHeavy());
|
||||||
//TODO: COMPARATOR_BLOCK
|
//TODO: COMPARATOR_BLOCK
|
||||||
//TODO: POWERED_COMPARATOR
|
//TODO: POWERED_COMPARATOR
|
||||||
self::registerBlock(new DaylightSensor());
|
self::registerBlock(new DaylightSensor());
|
||||||
self::registerBlock(new Redstone());
|
self::registerBlock(new Redstone());
|
||||||
self::registerBlock(new NetherQuartzOre());
|
self::registerBlock(new NetherQuartzOre());
|
||||||
//TODO: HOPPER_BLOCK
|
//TODO: HOPPER_BLOCK
|
||||||
self::registerBlock(new Quartz());
|
self::registerBlock(new Quartz());
|
||||||
self::registerBlock(new QuartzStairs());
|
self::registerBlock(new QuartzStairs());
|
||||||
self::registerBlock(new DoubleWoodenSlab());
|
self::registerBlock(new DoubleWoodenSlab());
|
||||||
self::registerBlock(new WoodenSlab());
|
self::registerBlock(new WoodenSlab());
|
||||||
self::registerBlock(new StainedClay());
|
self::registerBlock(new StainedClay());
|
||||||
self::registerBlock(new StainedGlassPane());
|
self::registerBlock(new StainedGlassPane());
|
||||||
self::registerBlock(new Leaves2());
|
self::registerBlock(new Leaves2());
|
||||||
self::registerBlock(new Wood2());
|
self::registerBlock(new Wood2());
|
||||||
self::registerBlock(new WoodenStairs(Block::ACACIA_STAIRS, 0, "Acacia Stairs"));
|
self::registerBlock(new WoodenStairs(Block::ACACIA_STAIRS, 0, "Acacia Stairs"));
|
||||||
self::registerBlock(new WoodenStairs(Block::DARK_OAK_STAIRS, 0, "Dark Oak Stairs"));
|
self::registerBlock(new WoodenStairs(Block::DARK_OAK_STAIRS, 0, "Dark Oak Stairs"));
|
||||||
//TODO: SLIME
|
//TODO: SLIME
|
||||||
|
|
||||||
self::registerBlock(new IronTrapdoor());
|
self::registerBlock(new IronTrapdoor());
|
||||||
self::registerBlock(new Prismarine());
|
self::registerBlock(new Prismarine());
|
||||||
self::registerBlock(new SeaLantern());
|
self::registerBlock(new SeaLantern());
|
||||||
self::registerBlock(new HayBale());
|
self::registerBlock(new HayBale());
|
||||||
self::registerBlock(new Carpet());
|
self::registerBlock(new Carpet());
|
||||||
self::registerBlock(new HardenedClay());
|
self::registerBlock(new HardenedClay());
|
||||||
self::registerBlock(new Coal());
|
self::registerBlock(new Coal());
|
||||||
self::registerBlock(new PackedIce());
|
self::registerBlock(new PackedIce());
|
||||||
self::registerBlock(new DoublePlant());
|
self::registerBlock(new DoublePlant());
|
||||||
self::registerBlock(new StandingBanner());
|
self::registerBlock(new StandingBanner());
|
||||||
self::registerBlock(new WallBanner());
|
self::registerBlock(new WallBanner());
|
||||||
//TODO: DAYLIGHT_DETECTOR_INVERTED
|
//TODO: DAYLIGHT_DETECTOR_INVERTED
|
||||||
self::registerBlock(new RedSandstone());
|
self::registerBlock(new RedSandstone());
|
||||||
self::registerBlock(new RedSandstoneStairs());
|
self::registerBlock(new RedSandstoneStairs());
|
||||||
self::registerBlock(new DoubleStoneSlab2());
|
self::registerBlock(new DoubleStoneSlab2());
|
||||||
self::registerBlock(new StoneSlab2());
|
self::registerBlock(new StoneSlab2());
|
||||||
self::registerBlock(new FenceGate(Block::SPRUCE_FENCE_GATE, 0, "Spruce Fence Gate"));
|
self::registerBlock(new FenceGate(Block::SPRUCE_FENCE_GATE, 0, "Spruce Fence Gate"));
|
||||||
self::registerBlock(new FenceGate(Block::BIRCH_FENCE_GATE, 0, "Birch Fence Gate"));
|
self::registerBlock(new FenceGate(Block::BIRCH_FENCE_GATE, 0, "Birch Fence Gate"));
|
||||||
self::registerBlock(new FenceGate(Block::JUNGLE_FENCE_GATE, 0, "Jungle Fence Gate"));
|
self::registerBlock(new FenceGate(Block::JUNGLE_FENCE_GATE, 0, "Jungle Fence Gate"));
|
||||||
self::registerBlock(new FenceGate(Block::DARK_OAK_FENCE_GATE, 0, "Dark Oak Fence Gate"));
|
self::registerBlock(new FenceGate(Block::DARK_OAK_FENCE_GATE, 0, "Dark Oak Fence Gate"));
|
||||||
self::registerBlock(new FenceGate(Block::ACACIA_FENCE_GATE, 0, "Acacia Fence Gate"));
|
self::registerBlock(new FenceGate(Block::ACACIA_FENCE_GATE, 0, "Acacia Fence Gate"));
|
||||||
//TODO: REPEATING_COMMAND_BLOCK
|
//TODO: REPEATING_COMMAND_BLOCK
|
||||||
//TODO: CHAIN_COMMAND_BLOCK
|
//TODO: CHAIN_COMMAND_BLOCK
|
||||||
|
|
||||||
self::registerBlock(new WoodenDoor(Block::SPRUCE_DOOR_BLOCK, 0, "Spruce Door", Item::SPRUCE_DOOR));
|
self::registerBlock(new WoodenDoor(Block::SPRUCE_DOOR_BLOCK, 0, "Spruce Door", Item::SPRUCE_DOOR));
|
||||||
self::registerBlock(new WoodenDoor(Block::BIRCH_DOOR_BLOCK, 0, "Birch Door", Item::BIRCH_DOOR));
|
self::registerBlock(new WoodenDoor(Block::BIRCH_DOOR_BLOCK, 0, "Birch Door", Item::BIRCH_DOOR));
|
||||||
self::registerBlock(new WoodenDoor(Block::JUNGLE_DOOR_BLOCK, 0, "Jungle Door", Item::JUNGLE_DOOR));
|
self::registerBlock(new WoodenDoor(Block::JUNGLE_DOOR_BLOCK, 0, "Jungle Door", Item::JUNGLE_DOOR));
|
||||||
self::registerBlock(new WoodenDoor(Block::ACACIA_DOOR_BLOCK, 0, "Acacia Door", Item::ACACIA_DOOR));
|
self::registerBlock(new WoodenDoor(Block::ACACIA_DOOR_BLOCK, 0, "Acacia Door", Item::ACACIA_DOOR));
|
||||||
self::registerBlock(new WoodenDoor(Block::DARK_OAK_DOOR_BLOCK, 0, "Dark Oak Door", Item::DARK_OAK_DOOR));
|
self::registerBlock(new WoodenDoor(Block::DARK_OAK_DOOR_BLOCK, 0, "Dark Oak Door", Item::DARK_OAK_DOOR));
|
||||||
self::registerBlock(new GrassPath());
|
self::registerBlock(new GrassPath());
|
||||||
self::registerBlock(new ItemFrame());
|
self::registerBlock(new ItemFrame());
|
||||||
//TODO: CHORUS_FLOWER
|
//TODO: CHORUS_FLOWER
|
||||||
self::registerBlock(new Purpur());
|
self::registerBlock(new Purpur());
|
||||||
|
|
||||||
self::registerBlock(new PurpurStairs());
|
self::registerBlock(new PurpurStairs());
|
||||||
|
|
||||||
//TODO: UNDYED_SHULKER_BOX
|
//TODO: UNDYED_SHULKER_BOX
|
||||||
self::registerBlock(new EndStoneBricks());
|
self::registerBlock(new EndStoneBricks());
|
||||||
//TODO: FROSTED_ICE
|
//TODO: FROSTED_ICE
|
||||||
self::registerBlock(new EndRod());
|
self::registerBlock(new EndRod());
|
||||||
//TODO: END_GATEWAY
|
//TODO: END_GATEWAY
|
||||||
|
|
||||||
self::registerBlock(new Magma());
|
self::registerBlock(new Magma());
|
||||||
self::registerBlock(new NetherWartBlock());
|
self::registerBlock(new NetherWartBlock());
|
||||||
self::registerBlock(new NetherBrick(Block::RED_NETHER_BRICK, 0, "Red Nether Bricks"));
|
self::registerBlock(new NetherBrick(Block::RED_NETHER_BRICK, 0, "Red Nether Bricks"));
|
||||||
self::registerBlock(new BoneBlock());
|
self::registerBlock(new BoneBlock());
|
||||||
|
|
||||||
//TODO: SHULKER_BOX
|
//TODO: SHULKER_BOX
|
||||||
self::registerBlock(new GlazedTerracotta(Block::PURPLE_GLAZED_TERRACOTTA, 0, "Purple Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::PURPLE_GLAZED_TERRACOTTA, 0, "Purple Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::WHITE_GLAZED_TERRACOTTA, 0, "White Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::WHITE_GLAZED_TERRACOTTA, 0, "White Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::ORANGE_GLAZED_TERRACOTTA, 0, "Orange Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::ORANGE_GLAZED_TERRACOTTA, 0, "Orange Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::MAGENTA_GLAZED_TERRACOTTA, 0, "Magenta Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::MAGENTA_GLAZED_TERRACOTTA, 0, "Magenta Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::LIGHT_BLUE_GLAZED_TERRACOTTA, 0, "Light Blue Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::LIGHT_BLUE_GLAZED_TERRACOTTA, 0, "Light Blue Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::YELLOW_GLAZED_TERRACOTTA, 0, "Yellow Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::YELLOW_GLAZED_TERRACOTTA, 0, "Yellow Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::LIME_GLAZED_TERRACOTTA, 0, "Lime Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::LIME_GLAZED_TERRACOTTA, 0, "Lime Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::PINK_GLAZED_TERRACOTTA, 0, "Pink Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::PINK_GLAZED_TERRACOTTA, 0, "Pink Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::GRAY_GLAZED_TERRACOTTA, 0, "Grey Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::GRAY_GLAZED_TERRACOTTA, 0, "Grey Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::SILVER_GLAZED_TERRACOTTA, 0, "Light Grey Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::SILVER_GLAZED_TERRACOTTA, 0, "Light Grey Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::CYAN_GLAZED_TERRACOTTA, 0, "Cyan Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::CYAN_GLAZED_TERRACOTTA, 0, "Cyan Glazed Terracotta"));
|
||||||
|
|
||||||
self::registerBlock(new GlazedTerracotta(Block::BLUE_GLAZED_TERRACOTTA, 0, "Blue Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::BLUE_GLAZED_TERRACOTTA, 0, "Blue Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::BROWN_GLAZED_TERRACOTTA, 0, "Brown Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::BROWN_GLAZED_TERRACOTTA, 0, "Brown Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::GREEN_GLAZED_TERRACOTTA, 0, "Green Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::GREEN_GLAZED_TERRACOTTA, 0, "Green Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::RED_GLAZED_TERRACOTTA, 0, "Red Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::RED_GLAZED_TERRACOTTA, 0, "Red Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::BLACK_GLAZED_TERRACOTTA, 0, "Black Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::BLACK_GLAZED_TERRACOTTA, 0, "Black Glazed Terracotta"));
|
||||||
self::registerBlock(new Concrete());
|
self::registerBlock(new Concrete());
|
||||||
self::registerBlock(new ConcretePowder());
|
self::registerBlock(new ConcretePowder());
|
||||||
|
|
||||||
//TODO: CHORUS_PLANT
|
//TODO: CHORUS_PLANT
|
||||||
self::registerBlock(new StainedGlass());
|
self::registerBlock(new StainedGlass());
|
||||||
|
|
||||||
self::registerBlock(new Podzol());
|
self::registerBlock(new Podzol());
|
||||||
self::registerBlock(new Beetroot());
|
self::registerBlock(new Beetroot());
|
||||||
self::registerBlock(new Stonecutter());
|
self::registerBlock(new Stonecutter());
|
||||||
self::registerBlock(new GlowingObsidian());
|
self::registerBlock(new GlowingObsidian());
|
||||||
self::registerBlock(new NetherReactor());
|
self::registerBlock(new NetherReactor());
|
||||||
//TODO: INFO_UPDATE
|
//TODO: INFO_UPDATE
|
||||||
//TODO: INFO_UPDATE2
|
//TODO: INFO_UPDATE2
|
||||||
//TODO: MOVINGBLOCK
|
//TODO: MOVINGBLOCK
|
||||||
//TODO: OBSERVER
|
//TODO: OBSERVER
|
||||||
//TODO: STRUCTURE_BLOCK
|
//TODO: STRUCTURE_BLOCK
|
||||||
|
|
||||||
//TODO: RESERVED6
|
//TODO: RESERVED6
|
||||||
|
|
||||||
foreach(self::$list as $id => $block){
|
foreach(self::$list as $id => $block){
|
||||||
if($block === null){
|
if($block === null){
|
||||||
self::registerBlock(new UnknownBlock($id));
|
self::registerBlock(new UnknownBlock($id));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var mixed[] $runtimeIdMap */
|
||||||
|
$runtimeIdMap = json_decode(file_get_contents(\pocketmine\RESOURCE_PATH . "runtimeid_table.json"), true);
|
||||||
|
foreach($runtimeIdMap as $obj){
|
||||||
|
self::registerMapping($obj["runtimeID"], $obj["id"], $obj["data"]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -390,9 +402,9 @@ class BlockFactory{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($pos !== null){
|
if($pos !== null){
|
||||||
$block->x = $pos->x;
|
$block->x = $pos->getFloorX();
|
||||||
$block->y = $pos->y;
|
$block->y = $pos->getFloorY();
|
||||||
$block->z = $pos->z;
|
$block->z = $pos->getFloorZ();
|
||||||
$block->level = $pos->level;
|
$block->level = $pos->level;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,4 +429,46 @@ class BlockFactory{
|
|||||||
$b = self::$list[$id];
|
$b = self::$list[$id];
|
||||||
return $b !== null and !($b instanceof UnknownBlock);
|
return $b !== null and !($b instanceof UnknownBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @param int $meta
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public static function toStaticRuntimeId(int $id, int $meta = 0) : int{
|
||||||
|
if($id === Block::AIR){
|
||||||
|
//TODO: HACK! (weird air blocks with non-zero damage values shouldn't turn into update! blocks)
|
||||||
|
$meta = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$index = ($id << 4) | $meta;
|
||||||
|
if(!isset(self::$staticRuntimeIdMap[$index])){
|
||||||
|
self::registerMapping($rtId = ++self::$lastRuntimeId, $id, $meta);
|
||||||
|
MainLogger::getLogger()->error("ID $id meta $meta does not have a corresponding block static runtime ID, added a new unknown runtime ID ($rtId)");
|
||||||
|
return $rtId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$staticRuntimeIdMap[$index];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @param int $runtimeId
|
||||||
|
*
|
||||||
|
* @return int[] [id, meta]
|
||||||
|
*/
|
||||||
|
public static function fromStaticRuntimeId(int $runtimeId) : array{
|
||||||
|
$v = self::$legacyIdMap[$runtimeId];
|
||||||
|
return [$v >> 4, $v & 0xf];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function registerMapping(int $staticRuntimeId, int $legacyId, int $legacyMeta) : void{
|
||||||
|
self::$staticRuntimeIdMap[($legacyId << 4) | $legacyMeta] = $staticRuntimeId;
|
||||||
|
self::$legacyIdMap[$staticRuntimeId] = ($legacyId << 4) | $legacyMeta;
|
||||||
|
self::$lastRuntimeId = max(self::$lastRuntimeId, $staticRuntimeId);
|
||||||
|
}
|
||||||
}
|
}
|
@ -21,21 +21,19 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\block;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Math related classes, like matrices, bounding boxes and vector
|
* Types of tools that can be used to break blocks
|
||||||
|
* Blocks may allow multiple tool types by combining these bitflags
|
||||||
*/
|
*/
|
||||||
namespace pocketmine\math;
|
interface BlockToolType{
|
||||||
|
|
||||||
|
public const TYPE_NONE = 0;
|
||||||
|
public const TYPE_SWORD = 1 << 0;
|
||||||
|
public const TYPE_SHOVEL = 1 << 1;
|
||||||
|
public const TYPE_PICKAXE = 1 << 2;
|
||||||
|
public const TYPE_AXE = 1 << 3;
|
||||||
|
public const TYPE_SHEARS = 1 << 4;
|
||||||
|
|
||||||
abstract class Math{
|
|
||||||
|
|
||||||
public static function floorFloat($n) : int{
|
|
||||||
$i = (int) $n;
|
|
||||||
return $n >= $i ? $i : $i - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function ceilFloat($n) : int{
|
|
||||||
$i = (int) ($n + 1);
|
|
||||||
return $n >= $i ? $i : $i - 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -25,7 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\block\utils\PillarRotationHelper;
|
use pocketmine\block\utils\PillarRotationHelper;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
@ -46,7 +46,11 @@ class BoneBlock extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
@ -57,13 +61,4 @@ class BoneBlock extends Solid{
|
|||||||
public function getVariantBitmask() : int{
|
public function getVariantBitmask() : int{
|
||||||
return 0x03;
|
return 0x03;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
|
||||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -25,7 +25,6 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class Bookshelf extends Solid{
|
class Bookshelf extends Solid{
|
||||||
|
|
||||||
@ -44,10 +43,10 @@ class Bookshelf extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_AXE;
|
return BlockToolType::TYPE_AXE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [
|
return [
|
||||||
ItemFactory::get(Item::BOOK, 0, 3)
|
ItemFactory::get(Item::BOOK, 0, 3)
|
||||||
];
|
];
|
||||||
@ -57,4 +56,11 @@ class Bookshelf extends Solid{
|
|||||||
return 300;
|
return 300;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFlameEncouragement() : int{
|
||||||
|
return 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
}
|
}
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
|
|
||||||
class BrewingStand extends Transparent{
|
class BrewingStand extends Transparent{
|
||||||
|
|
||||||
@ -42,7 +42,11 @@ class BrewingStand extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
public function getVariantBitmask() : int{
|
||||||
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
|
|
||||||
class BrickStairs extends Stair{
|
class BrickStairs extends Stair{
|
||||||
|
|
||||||
@ -42,7 +42,11 @@ class BrickStairs extends Stair{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class Bricks extends Solid{
|
class Bricks extends Solid{
|
||||||
|
|
||||||
@ -43,18 +42,14 @@ class Bricks extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return "Bricks";
|
return "Bricks";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
|
||||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -33,7 +33,7 @@ class BrownMushroomBlock extends RedMushroomBlock{
|
|||||||
return "Brown Mushroom Block";
|
return "Brown Mushroom Block";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [
|
return [
|
||||||
Item::get(Item::BROWN_MUSHROOM, 0, mt_rand(0, 2))
|
Item::get(Item::BROWN_MUSHROOM, 0, mt_rand(0, 2))
|
||||||
];
|
];
|
||||||
|
@ -24,7 +24,7 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\nbt\tag\StringTag;
|
use pocketmine\nbt\tag\StringTag;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
@ -35,6 +35,8 @@ class BurningFurnace extends Solid{
|
|||||||
|
|
||||||
protected $id = self::BURNING_FURNACE;
|
protected $id = self::BURNING_FURNACE;
|
||||||
|
|
||||||
|
protected $itemId = self::FURNACE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(int $meta = 0){
|
||||||
$this->meta = $meta;
|
$this->meta = $meta;
|
||||||
}
|
}
|
||||||
@ -48,7 +50,11 @@ class BurningFurnace extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLightLevel() : int{
|
public function getLightLevel() : int{
|
||||||
@ -90,12 +96,4 @@ class BurningFurnace extends Solid{
|
|||||||
public function getVariantBitmask() : int{
|
public function getVariantBitmask() : int{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
|
||||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -28,7 +28,6 @@ use pocketmine\event\block\BlockGrowEvent;
|
|||||||
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||||
use pocketmine\event\entity\EntityDamageEvent;
|
use pocketmine\event\entity\EntityDamageEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
@ -66,50 +65,49 @@ class Cactus extends Transparent{
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ticksRandomly() : bool{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onEntityCollide(Entity $entity) : void{
|
public function onEntityCollide(Entity $entity) : void{
|
||||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_CONTACT, 1);
|
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_CONTACT, 1);
|
||||||
$entity->attack($ev);
|
$entity->attack($ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
if($down->getId() !== self::SAND and $down->getId() !== self::CACTUS){
|
||||||
if($down->getId() !== self::SAND and $down->getId() !== self::CACTUS){
|
$this->getLevel()->useBreakOn($this);
|
||||||
$this->getLevel()->useBreakOn($this);
|
}else{
|
||||||
}else{
|
for($side = 2; $side <= 5; ++$side){
|
||||||
for($side = 2; $side <= 5; ++$side){
|
$b = $this->getSide($side);
|
||||||
$b = $this->getSide($side);
|
if(!$b->canBeFlowedInto()){
|
||||||
if(!$b->canBeFlowedInto()){
|
$this->getLevel()->useBreakOn($this);
|
||||||
$this->getLevel()->useBreakOn($this);
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::CACTUS){
|
|
||||||
if($this->meta === 0x0f){
|
|
||||||
for($y = 1; $y < 3; ++$y){
|
|
||||||
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z);
|
|
||||||
if($b->getId() === self::AIR){
|
|
||||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS)));
|
|
||||||
if(!$ev->isCancelled()){
|
|
||||||
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->meta = 0;
|
|
||||||
$this->getLevel()->setBlock($this, $this);
|
|
||||||
}else{
|
|
||||||
++$this->meta;
|
|
||||||
$this->getLevel()->setBlock($this, $this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
public function ticksRandomly() : bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onRandomTick() : void{
|
||||||
|
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::CACTUS){
|
||||||
|
if($this->meta === 0x0f){
|
||||||
|
for($y = 1; $y < 3; ++$y){
|
||||||
|
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z);
|
||||||
|
if($b->getId() === self::AIR){
|
||||||
|
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS)));
|
||||||
|
if(!$ev->isCancelled()){
|
||||||
|
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->meta = 0;
|
||||||
|
$this->getLevel()->setBlock($this, $this);
|
||||||
|
}else{
|
||||||
|
++$this->meta;
|
||||||
|
$this->getLevel()->setBlock($this, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
@ -119,7 +117,7 @@ class Cactus extends Transparent{
|
|||||||
$block1 = $this->getSide(Vector3::SIDE_SOUTH);
|
$block1 = $this->getSide(Vector3::SIDE_SOUTH);
|
||||||
$block2 = $this->getSide(Vector3::SIDE_WEST);
|
$block2 = $this->getSide(Vector3::SIDE_WEST);
|
||||||
$block3 = $this->getSide(Vector3::SIDE_EAST);
|
$block3 = $this->getSide(Vector3::SIDE_EAST);
|
||||||
if($block0->isTransparent() === true and $block1->isTransparent() === true and $block2->isTransparent() === true and $block3->isTransparent() === true){
|
if($block0->isTransparent() and $block1->isTransparent() and $block2->isTransparent() and $block3->isTransparent()){
|
||||||
$this->getLevel()->setBlock($this, $this, true);
|
$this->getLevel()->setBlock($this, $this, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -23,11 +23,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\entity\Effect;
|
use pocketmine\entity\EffectInstance;
|
||||||
use pocketmine\event\entity\EntityEatBlockEvent;
|
use pocketmine\entity\Living;
|
||||||
use pocketmine\item\FoodSource;
|
use pocketmine\item\FoodSource;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
@ -45,7 +44,7 @@ class Cake extends Transparent implements FoodSource{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return "Cake Block";
|
return "Cake";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
@ -73,37 +72,24 @@ class Cake extends Transparent implements FoodSource{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isAffectedBySilkTouch() : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
//TODO: refactor this into generic food handling
|
if($player !== null){
|
||||||
if($player instanceof Player and $player->getFood() < $player->getMaxFood()){
|
$player->consumeObject($this);
|
||||||
$player->getServer()->getPluginManager()->callEvent($ev = new EntityEatBlockEvent($player, $this));
|
return true;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -117,6 +103,13 @@ class Cake extends Transparent implements FoodSource{
|
|||||||
return 0.4;
|
return 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function requiresHunger() : bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Block
|
||||||
|
*/
|
||||||
public function getResidue(){
|
public function getResidue(){
|
||||||
$clone = clone $this;
|
$clone = clone $this;
|
||||||
$clone->meta++;
|
$clone->meta++;
|
||||||
@ -127,9 +120,13 @@ class Cake extends Transparent implements FoodSource{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Effect[]
|
* @return EffectInstance[]
|
||||||
*/
|
*/
|
||||||
public function getAdditionalEffects() : array{
|
public function getAdditionalEffects() : array{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function onConsume(Living $consumer) : void{
|
||||||
|
$this->level->setBlock($this, $this->getResidue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
use pocketmine\block\utils\ColorBlockMetaHelper;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
@ -73,16 +72,17 @@ class Carpet extends Flowable{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){
|
$this->getLevel()->useBreakOn($this);
|
||||||
$this->getLevel()->useBreakOn($this);
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFlameEncouragement() : int{
|
||||||
|
return 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
}
|
}
|
@ -38,7 +38,7 @@ class Carrot extends Crops{
|
|||||||
return "Carrot Block";
|
return "Carrot Block";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [
|
return [
|
||||||
ItemFactory::get(Item::CARROT, 0, $this->meta >= 0x07 ? mt_rand(1, 4) : 1)
|
ItemFactory::get(Item::CARROT, 0, $this->meta >= 0x07 ? mt_rand(1, 4) : 1)
|
||||||
];
|
];
|
||||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\nbt\tag\StringTag;
|
use pocketmine\nbt\tag\StringTag;
|
||||||
@ -49,7 +48,7 @@ class Chest extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_AXE;
|
return BlockToolType::TYPE_AXE;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
@ -102,16 +101,6 @@ class Chest extends Transparent{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onBreak(Item $item, Player $player = null) : bool{
|
|
||||||
$t = $this->getLevel()->getTile($this);
|
|
||||||
if($t instanceof TileChest){
|
|
||||||
$t->unpair();
|
|
||||||
}
|
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
if($player instanceof Player){
|
if($player instanceof Player){
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class Clay extends Solid{
|
class Clay extends Solid{
|
||||||
|
|
||||||
@ -40,14 +39,14 @@ class Clay extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_SHOVEL;
|
return BlockToolType::TYPE_SHOVEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return "Clay Block";
|
return "Clay Block";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [
|
return [
|
||||||
ItemFactory::get(Item::CLAY_BALL, 0, 4)
|
ItemFactory::get(Item::CLAY_BALL, 0, 4)
|
||||||
];
|
];
|
||||||
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class Coal extends Solid{
|
class Coal extends Solid{
|
||||||
|
|
||||||
@ -39,22 +38,26 @@ class Coal extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return "Coal Block";
|
return "Coal Block";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
|
||||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFuelTime() : int{
|
public function getFuelTime() : int{
|
||||||
return 16000;
|
return 16000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFlameEncouragement() : int{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
}
|
}
|
@ -25,7 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
|
|
||||||
class CoalOre extends Solid{
|
class CoalOre extends Solid{
|
||||||
|
|
||||||
@ -40,21 +40,21 @@ class CoalOre extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return "Coal Ore";
|
return "Coal Ore";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
return [
|
||||||
return [
|
ItemFactory::get(Item::COAL)
|
||||||
ItemFactory::get(Item::COAL, 0, 1)
|
];
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class Cobblestone extends Solid{
|
class Cobblestone extends Solid{
|
||||||
|
|
||||||
@ -35,7 +34,11 @@ class Cobblestone extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
@ -45,12 +48,4 @@ class Cobblestone extends Solid{
|
|||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
|
||||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
|
|
||||||
class CobblestoneStairs extends Stair{
|
class CobblestoneStairs extends Stair{
|
||||||
|
|
||||||
@ -38,7 +38,11 @@ class CobblestoneStairs extends Stair{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
|
|
||||||
@ -38,7 +38,11 @@ class CobblestoneWall extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
|
@ -25,7 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\ItemFactory;
|
||||||
|
|
||||||
class Cobweb extends Flowable{
|
class Cobweb extends Flowable{
|
||||||
|
|
||||||
@ -48,16 +48,21 @@ class Cobweb extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_SWORD;
|
return BlockToolType::TYPE_SWORD | BlockToolType::TYPE_SHEARS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onEntityCollide(Entity $entity) : void{
|
public function onEntityCollide(Entity $entity) : void{
|
||||||
$entity->resetFallDistance();
|
$entity->resetFallDistance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
//TODO: correct drops
|
return [
|
||||||
return [];
|
ItemFactory::get(Item::STRING)
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function diffusesSkyLight() : bool{
|
public function diffusesSkyLight() : bool{
|
||||||
|
@ -35,5 +35,17 @@ class CocoaBlock extends Transparent{
|
|||||||
return "Cocoa Block";
|
return "Cocoa Block";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getHardness() : float{
|
||||||
|
return 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolType() : int{
|
||||||
|
return BlockToolType::TYPE_AXE;
|
||||||
|
}
|
||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
|
|
||||||
|
public function isAffectedBySilkTouch() : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,7 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
use pocketmine\block\utils\ColorBlockMetaHelper;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class Concrete extends Solid{
|
class Concrete extends Solid{
|
||||||
|
|
||||||
@ -44,15 +43,10 @@ class Concrete extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getToolHarvestLevel() : int{
|
||||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
return TieredTool::TIER_WOODEN;
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -24,8 +24,6 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
use pocketmine\block\utils\ColorBlockMetaHelper;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
use pocketmine\level\Level;
|
|
||||||
|
|
||||||
class ConcretePowder extends Fallable{
|
class ConcretePowder extends Fallable{
|
||||||
|
|
||||||
@ -44,16 +42,15 @@ class ConcretePowder extends Fallable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_SHOVEL;
|
return BlockToolType::TYPE_SHOVEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL and ($block = $this->checkAdjacentWater()) !== null){
|
if(($block = $this->checkAdjacentWater()) !== null){
|
||||||
$this->level->setBlock($this, $block);
|
$this->level->setBlock($this, $block);
|
||||||
return $type;
|
}else{
|
||||||
|
parent::onNearbyBlockChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::onUpdate($type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,9 +23,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\inventory\BigCraftingGrid;
|
use pocketmine\inventory\CraftingGrid;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
class CraftingTable extends Solid{
|
class CraftingTable extends Solid{
|
||||||
@ -45,12 +44,12 @@ class CraftingTable extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_AXE;
|
return BlockToolType::TYPE_AXE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
if($player instanceof Player){
|
if($player instanceof Player){
|
||||||
$player->setCraftingGrid(new BigCraftingGrid($player));
|
$player->setCraftingGrid(new CraftingGrid($player, CraftingGrid::SIZE_BIG));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -25,7 +25,6 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\event\block\BlockGrowEvent;
|
use pocketmine\event\block\BlockGrowEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\Server;
|
use pocketmine\Server;
|
||||||
@ -65,34 +64,31 @@ abstract class Crops extends Flowable{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function onNearbyBlockChange() : void{
|
||||||
|
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
|
||||||
|
$this->getLevel()->useBreakOn($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function ticksRandomly() : bool{
|
public function ticksRandomly() : bool{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onRandomTick() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if(mt_rand(0, 2) === 1){
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
|
if($this->meta < 0x07){
|
||||||
$this->getLevel()->useBreakOn($this);
|
$block = clone $this;
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
++$block->meta;
|
||||||
}
|
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
||||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
|
||||||
if(mt_rand(0, 2) === 1){
|
|
||||||
if($this->meta < 0x07){
|
|
||||||
$block = clone $this;
|
|
||||||
++$block->meta;
|
|
||||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
|
||||||
|
|
||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
|
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
|
||||||
}else{
|
|
||||||
return Level::BLOCK_UPDATE_RANDOM;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}else{
|
|
||||||
return Level::BLOCK_UPDATE_RANDOM;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isAffectedBySilkTouch() : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
@ -52,15 +51,17 @@ class Dandelion extends Flowable{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
|
$this->getLevel()->useBreakOn($this);
|
||||||
$this->getLevel()->useBreakOn($this);
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
public function getFlameEncouragement() : int{
|
||||||
|
return 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -43,5 +43,9 @@ class DaylightSensor extends Transparent{
|
|||||||
return 300;
|
return 300;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getToolType() : int{
|
||||||
|
return BlockToolType::TYPE_AXE;
|
||||||
|
}
|
||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,8 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
|
use pocketmine\Player;
|
||||||
|
|
||||||
class DeadBush extends Flowable{
|
class DeadBush extends Flowable{
|
||||||
|
|
||||||
@ -41,29 +40,43 @@ class DeadBush extends Flowable{
|
|||||||
return "Dead Bush";
|
return "Dead Bush";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if(!$this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
|
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
$this->getLevel()->useBreakOn($this);
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function onNearbyBlockChange() : void{
|
||||||
|
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||||
|
$this->getLevel()->useBreakOn($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_SHEARS;
|
return BlockToolType::TYPE_SHEARS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDrops(Item $item) : array{
|
||||||
if($item->isShears()){
|
if(!$this->isCompatibleWithTool($item)){
|
||||||
return parent::getDrops($item);
|
return [
|
||||||
|
ItemFactory::get(Item::STICK, 0, mt_rand(0, 2))
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return parent::getDrops($item);
|
||||||
ItemFactory::get(Item::STICK, 0, mt_rand(0, 2))
|
}
|
||||||
];
|
|
||||||
|
public function getFlameEncouragement() : int{
|
||||||
|
return 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class Diamond extends Solid{
|
class Diamond extends Solid{
|
||||||
|
|
||||||
@ -43,14 +42,10 @@ class Diamond extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getToolHarvestLevel() : int{
|
||||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
return TieredTool::TIER_IRON;
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,7 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
|
|
||||||
class DiamondOre extends Solid{
|
class DiamondOre extends Solid{
|
||||||
|
|
||||||
@ -44,16 +44,16 @@ class DiamondOre extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getToolHarvestLevel() : int{
|
||||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
return TieredTool::TIER_IRON;
|
||||||
return [
|
}
|
||||||
ItemFactory::get(Item::DIAMOND, 0, 1)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
|
return [
|
||||||
|
ItemFactory::get(Item::DIAMOND)
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
class Dirt extends Solid{
|
class Dirt extends Solid{
|
||||||
@ -40,7 +39,7 @@ class Dirt extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_SHOVEL;
|
return BlockToolType::TYPE_SHOVEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\level\sound\DoorSound;
|
use pocketmine\level\sound\DoorSound;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
@ -201,26 +200,20 @@ abstract class Door extends Transparent{
|
|||||||
return $bb;
|
return $bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() === self::AIR){ //Replace with common break method
|
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false);
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), false);
|
if($this->getSide(Vector3::SIDE_UP) instanceof Door){
|
||||||
if($this->getSide(Vector3::SIDE_UP) instanceof Door){
|
$this->getLevel()->setBlock($this->getSide(Vector3::SIDE_UP), BlockFactory::get(Block::AIR), false);
|
||||||
$this->getLevel()->setBlock($this->getSide(Vector3::SIDE_UP), BlockFactory::get(Block::AIR), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
if($face === Vector3::SIDE_UP){
|
if($face === Vector3::SIDE_UP){
|
||||||
$blockUp = $this->getSide(Vector3::SIDE_UP);
|
$blockUp = $this->getSide(Vector3::SIDE_UP);
|
||||||
$blockDown = $this->getSide(Vector3::SIDE_DOWN);
|
$blockDown = $this->getSide(Vector3::SIDE_DOWN);
|
||||||
if($blockUp->canBeReplaced() === false or $blockDown->isTransparent() === true){
|
if(!$blockUp->canBeReplaced() or $blockDown->isTransparent()){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$direction = $player instanceof Player ? $player->getDirection() : 0;
|
$direction = $player instanceof Player ? $player->getDirection() : 0;
|
||||||
@ -233,36 +226,19 @@ abstract class Door extends Transparent{
|
|||||||
$next = $this->getSide($faces[($direction + 2) % 4]);
|
$next = $this->getSide($faces[($direction + 2) % 4]);
|
||||||
$next2 = $this->getSide($faces[$direction]);
|
$next2 = $this->getSide($faces[$direction]);
|
||||||
$metaUp = 0x08;
|
$metaUp = 0x08;
|
||||||
if($next->getId() === $this->getId() or ($next2->isTransparent() === false and $next->isTransparent() === true)){ //Door hinge
|
if($next->getId() === $this->getId() or (!$next2->isTransparent() and $next->isTransparent())){ //Door hinge
|
||||||
$metaUp |= 0x01;
|
$metaUp |= 0x01;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->setDamage($player->getDirection() & 0x03);
|
$this->setDamage($player->getDirection() & 0x03);
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, true, true); //Bottom
|
$this->getLevel()->setBlock($blockReplace, $this, true, true); //Bottom
|
||||||
$this->getLevel()->setBlock($blockUp, $b = BlockFactory::get($this->getId(), $metaUp), true); //Top
|
$this->getLevel()->setBlock($blockUp, BlockFactory::get($this->getId(), $metaUp), true); //Top
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onBreak(Item $item, Player $player = null) : bool{
|
|
||||||
if(($this->getDamage() & 0x08) === 0x08){
|
|
||||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
|
||||||
if($down->getId() === $this->getId()){
|
|
||||||
$this->getLevel()->setBlock($down, BlockFactory::get(Block::AIR), true);
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
$up = $this->getSide(Vector3::SIDE_UP);
|
|
||||||
if($up->getId() === $this->getId()){
|
|
||||||
$this->getLevel()->setBlock($up, BlockFactory::get(Block::AIR), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
if(($this->getDamage() & 0x08) === 0x08){ //Top
|
if(($this->getDamage() & 0x08) === 0x08){ //Top
|
||||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||||
@ -286,4 +262,32 @@ abstract class Door extends Transparent{
|
|||||||
public function getVariantBitmask() : int{
|
public function getVariantBitmask() : int{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
|
if(($this->meta & 0x08) === 0){ //bottom half only
|
||||||
|
return parent::getDropsForCompatibleTool($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isAffectedBySilkTouch() : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAffectedBlocks() : array{
|
||||||
|
if(($this->getDamage() & 0x08) === 0x08){
|
||||||
|
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||||
|
if($down->getId() === $this->getId()){
|
||||||
|
return [$this, $down];
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
$up = $this->getSide(Vector3::SIDE_UP);
|
||||||
|
if($up->getId() === $this->getId()){
|
||||||
|
return [$this, $up];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::getAffectedBlocks();
|
||||||
|
}
|
||||||
}
|
}
|
@ -25,7 +25,6 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
@ -84,46 +83,45 @@ class DoublePlant extends Flowable{
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if(!$this->isValidHalfPlant() or (($this->meta & self::BITFLAG_TOP) === 0 and $this->getSide(Vector3::SIDE_DOWN)->isTransparent())){
|
||||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
$this->getLevel()->useBreakOn($this);
|
||||||
if(!$this->isValidHalfPlant() or (($this->meta & self::BITFLAG_TOP) === 0 and $down->isTransparent())){
|
|
||||||
$this->getLevel()->useBreakOn($this);
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function 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{
|
public function getVariantBitmask() : int{
|
||||||
return 0x07;
|
return 0x07;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getToolType() : int{
|
||||||
|
return ($this->meta === 2 or $this->meta === 3) ? BlockToolType::TYPE_SHEARS : BlockToolType::TYPE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return ($this->meta === 2 or $this->meta === 3) ? 1 : 0; //only grass or fern require shears
|
||||||
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDrops(Item $item) : array{
|
||||||
if($this->meta & self::BITFLAG_TOP){
|
if($this->meta & self::BITFLAG_TOP){
|
||||||
if(!$item->isShears() and ($this->meta === 2 or $this->meta === 3)){ //grass or fern
|
if($this->isCompatibleWithTool($item)){
|
||||||
if(mt_rand(0, 24) === 0){
|
return parent::getDrops($item);
|
||||||
return [
|
|
||||||
ItemFactory::get(Item::SEEDS, 0, 1)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::getDrops($item);
|
if(mt_rand(0, 24) === 0){
|
||||||
|
return [
|
||||||
|
ItemFactory::get(Item::SEEDS)
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getAffectedBlocks() : array{
|
||||||
|
if($this->isValidHalfPlant()){
|
||||||
|
return [$this, $this->getSide(($this->meta & self::BITFLAG_TOP) !== 0 ? Vector3::SIDE_DOWN : Vector3::SIDE_UP)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::getAffectedBlocks();
|
||||||
|
}
|
||||||
}
|
}
|
@ -38,10 +38,13 @@ abstract class DoubleSlab extends Solid{
|
|||||||
return "Double " . BlockFactory::get($this->getSlabId(), $this->getVariant())->getName() . " Slab";
|
return "Double " . BlockFactory::get($this->getSlabId(), $this->getVariant())->getName() . " Slab";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [
|
return [
|
||||||
ItemFactory::get($this->getSlabId(), $this->getVariant(), 2)
|
ItemFactory::get($this->getSlabId(), $this->getVariant(), 2)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isAffectedBySilkTouch() : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class DoubleStoneSlab extends DoubleSlab{
|
class DoubleStoneSlab extends DoubleSlab{
|
||||||
|
|
||||||
@ -39,15 +38,10 @@ class DoubleStoneSlab extends DoubleSlab{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getToolHarvestLevel() : int{
|
||||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
return TieredTool::TIER_WOODEN;
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -23,8 +23,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class DoubleWoodenSlab extends DoubleSlab{
|
class DoubleWoodenSlab extends DoubleSlab{
|
||||||
|
|
||||||
protected $id = self::DOUBLE_WOODEN_SLAB;
|
protected $id = self::DOUBLE_WOODEN_SLAB;
|
||||||
@ -38,6 +36,14 @@ class DoubleWoodenSlab extends DoubleSlab{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_AXE;
|
return BlockToolType::TYPE_AXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlameEncouragement() : int{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return 20;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class Emerald extends Solid{
|
class Emerald extends Solid{
|
||||||
|
|
||||||
@ -39,18 +38,14 @@ class Emerald extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_IRON;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return "Emerald Block";
|
return "Emerald Block";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
|
||||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -25,7 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
|
|
||||||
class EmeraldOre extends Solid{
|
class EmeraldOre extends Solid{
|
||||||
|
|
||||||
@ -40,20 +40,20 @@ class EmeraldOre extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_IRON;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
return [
|
||||||
return [
|
ItemFactory::get(Item::EMERALD)
|
||||||
ItemFactory::get(Item::EMERALD, 0, 1)
|
];
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,7 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\inventory\EnchantInventory;
|
use pocketmine\inventory\EnchantInventory;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\tile\EnchantTable as TileEnchantTable;
|
use pocketmine\tile\EnchantTable as TileEnchantTable;
|
||||||
@ -60,7 +60,11 @@ class EnchantingTable extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
@ -72,12 +76,4 @@ class EnchantingTable extends Transparent{
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
|
||||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
|
|
||||||
class EndStone extends Solid{
|
class EndStone extends Solid{
|
||||||
|
|
||||||
@ -38,7 +38,11 @@ class EndStone extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class EndStoneBricks extends Solid{
|
class EndStoneBricks extends Solid{
|
||||||
|
|
||||||
@ -43,15 +42,10 @@ class EndStoneBricks extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getToolHarvestLevel() : int{
|
||||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
return TieredTool::TIER_WOODEN;
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -25,7 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\tile\EnderChest as TileEnderChest;
|
use pocketmine\tile\EnderChest as TileEnderChest;
|
||||||
@ -52,7 +52,11 @@ class EnderChest extends Chest{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
@ -71,10 +75,6 @@ class EnderChest extends Chest{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onBreak(Item $item, Player $player = null) : bool{
|
|
||||||
return Block::onBreak($item, $player);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
if($player instanceof Player){
|
if($player instanceof Player){
|
||||||
|
|
||||||
@ -97,12 +97,10 @@ class EnderChest extends Chest{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
return [
|
||||||
return [ItemFactory::get(Item::OBSIDIAN, 0, 8)];
|
ItemFactory::get(Item::OBSIDIAN, 0, 8)
|
||||||
}
|
];
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFuelTime() : int{
|
public function getFuelTime() : int{
|
||||||
|
@ -24,26 +24,23 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
|
|
||||||
abstract class Fallable extends Solid{
|
abstract class Fallable extends Solid{
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
if($down->getId() === self::AIR or $down instanceof Liquid or $down instanceof Fire){
|
||||||
if($down->getId() === self::AIR or $down instanceof Liquid or $down instanceof Fire){
|
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||||
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true);
|
|
||||||
|
|
||||||
$nbt = Entity::createBaseNBT($this->add(0.5, 0, 0.5));
|
$nbt = Entity::createBaseNBT($this->add(0.5, 0, 0.5));
|
||||||
$nbt->setInt("TileID", $this->getId());
|
$nbt->setInt("TileID", $this->getId());
|
||||||
$nbt->setByte("Data", $this->getDamage());
|
$nbt->setByte("Data", $this->getDamage());
|
||||||
|
|
||||||
$fall = Entity::createEntity("FallingSand", $this->getLevel(), $nbt);
|
$fall = Entity::createEntity("FallingSand", $this->getLevel(), $nbt);
|
||||||
|
|
||||||
if($fall !== null){
|
if($fall !== null){
|
||||||
$fall->spawnToAll();
|
$fall->spawnToAll();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,6 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
|
|
||||||
@ -47,12 +45,9 @@ class Farmland extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_SHOVEL;
|
return BlockToolType::TYPE_SHOVEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ticksRandomly() : bool{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
return new AxisAlignedBB(
|
return new AxisAlignedBB(
|
||||||
@ -65,29 +60,28 @@ class Farmland extends Transparent{
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL and $this->getSide(Vector3::SIDE_UP)->isSolid()){
|
if($this->getSide(Vector3::SIDE_UP)->isSolid()){
|
||||||
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
||||||
return $type;
|
|
||||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
|
||||||
if(!$this->canHydrate()){
|
|
||||||
if($this->meta > 0){
|
|
||||||
$this->meta--;
|
|
||||||
$this->level->setBlock($this, $this, false, false);
|
|
||||||
}else{
|
|
||||||
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $type;
|
|
||||||
}elseif($this->meta < 7){
|
|
||||||
$this->meta = 7;
|
|
||||||
$this->level->setBlock($this, $this, false, false);
|
|
||||||
|
|
||||||
return $type;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
public function ticksRandomly() : bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onRandomTick() : void{
|
||||||
|
if(!$this->canHydrate()){
|
||||||
|
if($this->meta > 0){
|
||||||
|
$this->meta--;
|
||||||
|
$this->level->setBlock($this, $this, false, false);
|
||||||
|
}else{
|
||||||
|
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), false, true);
|
||||||
|
}
|
||||||
|
}elseif($this->meta < 7){
|
||||||
|
$this->meta = 7;
|
||||||
|
$this->level->setBlock($this, $this, false, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function canHydrate() : bool{
|
protected function canHydrate() : bool{
|
||||||
@ -108,9 +102,13 @@ class Farmland extends Transparent{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [
|
return [
|
||||||
ItemFactory::get(Item::DIRT, 0, 1)
|
ItemFactory::get(Item::DIRT)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isAffectedBySilkTouch() : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
use pocketmine\level\sound\DoorSound;
|
use pocketmine\level\sound\DoorSound;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
@ -37,7 +36,7 @@ class FenceGate extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_AXE;
|
return BlockToolType::TYPE_AXE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -95,4 +94,12 @@ class FenceGate extends Transparent{
|
|||||||
public function getFuelTime() : int{
|
public function getFuelTime() : int{
|
||||||
return 300;
|
return 300;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFlameEncouragement() : int{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,11 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
use pocketmine\entity\projectile\Arrow;
|
use pocketmine\entity\projectile\Arrow;
|
||||||
|
use pocketmine\event\block\BlockBurnEvent;
|
||||||
use pocketmine\event\entity\EntityCombustByBlockEvent;
|
use pocketmine\event\entity\EntityCombustByBlockEvent;
|
||||||
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||||
use pocketmine\event\entity\EntityDamageEvent;
|
use pocketmine\event\entity\EntityDamageEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Server;
|
use pocketmine\Server;
|
||||||
|
|
||||||
@ -61,10 +61,6 @@ class Fire extends Flowable{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ticksRandomly() : bool{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onEntityCollide(Entity $entity) : void{
|
public function onEntityCollide(Entity $entity) : void{
|
||||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, 1);
|
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, 1);
|
||||||
$entity->attack($ev);
|
$entity->attack($ev);
|
||||||
@ -79,39 +75,94 @@ class Fire extends Flowable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if(!$this->getSide(Vector3::SIDE_DOWN)->isSolid() and !$this->hasAdjacentFlammableBlocks()){
|
||||||
for($s = 0; $s <= 5; ++$s){
|
|
||||||
$side = $this->getSide($s);
|
|
||||||
if($side->getId() !== self::AIR and !($side instanceof Liquid)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
|
||||||
|
}else{
|
||||||
|
$this->level->scheduleDelayedBlockUpdate($this, mt_rand(30, 40));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
public function ticksRandomly() : bool{
|
||||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
return true;
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::NETHERRACK){
|
}
|
||||||
if(mt_rand(0, 2) === 0){
|
|
||||||
if($this->meta === 0x0F){
|
|
||||||
$this->level->setBlock($this, BlockFactory::get(Block::AIR));
|
|
||||||
}else{
|
|
||||||
$this->meta++;
|
|
||||||
$this->level->setBlock($this, $this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
public function onRandomTick() : void{
|
||||||
|
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||||
|
|
||||||
|
$result = null;
|
||||||
|
if($this->meta < 15 and mt_rand(0, 2) === 0){
|
||||||
|
$this->meta++;
|
||||||
|
$result = $this;
|
||||||
|
}
|
||||||
|
$canSpread = true;
|
||||||
|
|
||||||
|
if(!$down->burnsForever()){
|
||||||
|
//TODO: check rain
|
||||||
|
if($this->meta === 15){
|
||||||
|
if(!$down->isFlammable() and mt_rand(0, 3) === 3){ //1/4 chance to extinguish
|
||||||
|
$canSpread = false;
|
||||||
|
$result = BlockFactory::get(Block::AIR);
|
||||||
|
}
|
||||||
|
}elseif(!$this->hasAdjacentFlammableBlocks()){
|
||||||
|
$canSpread = false;
|
||||||
|
if(!$down->isSolid() or $this->meta > 3){ //fire older than 3, or without a solid block below
|
||||||
|
$result = BlockFactory::get(Block::AIR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($result !== null){
|
||||||
|
$this->level->setBlock($this, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->level->scheduleDelayedBlockUpdate($this, mt_rand(30, 40));
|
||||||
|
|
||||||
|
if($canSpread){
|
||||||
|
//TODO: raise upper bound for chance in humid biomes
|
||||||
|
|
||||||
|
foreach($this->getHorizontalSides() as $side){
|
||||||
|
$this->burnBlock($side, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
//vanilla uses a 250 upper bound here, but I don't think they intended to increase the chance of incineration
|
||||||
|
$this->burnBlock($this->getSide(Vector3::SIDE_UP), 350);
|
||||||
|
$this->burnBlock($this->getSide(Vector3::SIDE_DOWN), 350);
|
||||||
|
|
||||||
//TODO: fire spread
|
//TODO: fire spread
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onScheduledUpdate() : void{
|
||||||
|
$this->onRandomTick();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function hasAdjacentFlammableBlocks() : bool{
|
||||||
|
for($i = 0; $i <= 5; ++$i){
|
||||||
|
if($this->getSide($i)->isFlammable()){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function burnBlock(Block $block, int $chanceBound) : void{
|
||||||
|
if(mt_rand(0, $chanceBound) < $block->getFlammability()){
|
||||||
|
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockBurnEvent($block, $this));
|
||||||
|
if(!$ev->isCancelled()){
|
||||||
|
$block->onIncinerate();
|
||||||
|
|
||||||
|
if(mt_rand(0, $this->meta + 9) < 5){ //TODO: check rain
|
||||||
|
$this->level->setBlock($block, BlockFactory::get(Block::FIRE, min(15, $this->meta + (mt_rand(0, 4) >> 2))));
|
||||||
|
}else{
|
||||||
|
$this->level->setBlock($block, BlockFactory::get(Block::AIR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
@ -71,15 +70,17 @@ class Flower extends Flowable{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
$this->getLevel()->useBreakOn($this);
|
||||||
$this->getLevel()->useBreakOn($this);
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
public function getFlameEncouragement() : int{
|
||||||
|
return 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
@ -68,16 +67,10 @@ class FlowerPot extends Flowable{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
|
||||||
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
|
$this->getLevel()->useBreakOn($this);
|
||||||
$this->getLevel()->useBreakOn($this);
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
@ -96,8 +89,12 @@ class FlowerPot extends Flowable{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getVariantBitmask() : int{
|
||||||
$items = parent::getDrops($item);
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
|
$items = parent::getDropsForCompatibleTool($item);
|
||||||
|
|
||||||
$tile = $this->getLevel()->getTile($this);
|
$tile = $this->getLevel()->getTile($this);
|
||||||
if($tile instanceof TileFlowerPot){
|
if($tile instanceof TileFlowerPot){
|
||||||
@ -110,4 +107,7 @@ class FlowerPot extends Flowable{
|
|||||||
return $items;
|
return $items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isAffectedBySilkTouch() : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
@ -41,7 +41,7 @@ class Glass extends Transparent{
|
|||||||
return 0.3;
|
return 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -41,7 +41,7 @@ class GlassPane extends Thin{
|
|||||||
return 0.3;
|
return 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,7 +25,7 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
@ -36,7 +36,11 @@ class GlazedTerracotta extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
@ -56,12 +60,4 @@ class GlazedTerracotta extends Solid{
|
|||||||
public function getVariantBitmask() : int{
|
public function getVariantBitmask() : int{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
|
||||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -24,6 +24,8 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
|
|
||||||
|
use pocketmine\item\TieredTool;
|
||||||
|
|
||||||
class GlowingObsidian extends Solid{
|
class GlowingObsidian extends Solid{
|
||||||
|
|
||||||
protected $id = self::GLOWING_OBSIDIAN;
|
protected $id = self::GLOWING_OBSIDIAN;
|
||||||
@ -47,4 +49,12 @@ class GlowingObsidian extends Solid{
|
|||||||
public function getBlastResistance() : float{
|
public function getBlastResistance() : float{
|
||||||
return 50;
|
return 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getToolType() : int{
|
||||||
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_DIAMOND;
|
||||||
|
}
|
||||||
}
|
}
|
@ -23,12 +23,15 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\level\Level;
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\Player;
|
||||||
|
|
||||||
class GlowingRedstoneOre extends RedstoneOre{
|
class GlowingRedstoneOre extends RedstoneOre{
|
||||||
|
|
||||||
protected $id = self::GLOWING_REDSTONE_ORE;
|
protected $id = self::GLOWING_REDSTONE_ORE;
|
||||||
|
|
||||||
|
protected $itemId = self::REDSTONE_ORE;
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return "Glowing Redstone Ore";
|
return "Glowing Redstone Ore";
|
||||||
}
|
}
|
||||||
@ -37,13 +40,19 @@ class GlowingRedstoneOre extends RedstoneOre{
|
|||||||
return 9;
|
return 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
if($type === Level::BLOCK_UPDATE_SCHEDULED or $type === Level::BLOCK_UPDATE_RANDOM){
|
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::REDSTONE_ORE, $this->meta), false, false);
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_WEAK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function onNearbyBlockChange() : void{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ticksRandomly() : bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onRandomTick() : void{
|
||||||
|
$this->getLevel()->setBlock($this, BlockFactory::get(Block::REDSTONE_ORE, $this->meta), false, false);
|
||||||
|
}
|
||||||
}
|
}
|
@ -25,7 +25,6 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class Glowstone extends Transparent{
|
class Glowstone extends Transparent{
|
||||||
|
|
||||||
@ -44,14 +43,14 @@ class Glowstone extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLightLevel() : int{
|
public function getLightLevel() : int{
|
||||||
return 15;
|
return 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [
|
return [
|
||||||
ItemFactory::get(Item::GLOWSTONE_DUST, 0, mt_rand(2, 4))
|
ItemFactory::get(Item::GLOWSTONE_DUST, 0, mt_rand(2, 4))
|
||||||
];
|
];
|
||||||
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class Gold extends Solid{
|
class Gold extends Solid{
|
||||||
|
|
||||||
@ -43,14 +42,10 @@ class Gold extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getToolHarvestLevel() : int{
|
||||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
return TieredTool::TIER_IRON;
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class GoldOre extends Solid{
|
class GoldOre extends Solid{
|
||||||
|
|
||||||
@ -43,14 +42,10 @@ class GoldOre extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getToolHarvestLevel() : int{
|
||||||
if($item->isPickaxe() >= Tool::TIER_IRON){
|
return TieredTool::TIER_IRON;
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,9 +26,7 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\event\block\BlockSpreadEvent;
|
use pocketmine\event\block\BlockSpreadEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
use pocketmine\level\generator\object\TallGrass as TallGrassObject;
|
use pocketmine\level\generator\object\TallGrass as TallGrassObject;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\utils\Random;
|
use pocketmine\utils\Random;
|
||||||
@ -50,12 +48,12 @@ class Grass extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_SHOVEL;
|
return BlockToolType::TYPE_SHOVEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [
|
return [
|
||||||
ItemFactory::get(Item::DIRT, 0, 1)
|
ItemFactory::get(Item::DIRT)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,43 +61,35 @@ class Grass extends Solid{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onRandomTick() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_RANDOM){
|
$lightAbove = $this->level->getFullLightAt($this->x, $this->y + 1, $this->z);
|
||||||
$lightAbove = $this->level->getFullLightAt($this->x, $this->y + 1, $this->z);
|
if($lightAbove < 4 and BlockFactory::$lightFilter[$this->level->getBlockIdAt($this->x, $this->y + 1, $this->z)] >= 3){ //2 plus 1 standard filter amount
|
||||||
if($lightAbove < 4 and BlockFactory::$lightFilter[$this->level->getBlockIdAt($this->x, $this->y + 1, $this->z)] >= 3){ //2 plus 1 standard filter amount
|
//grass dies
|
||||||
//grass dies
|
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($this, $this, BlockFactory::get(Block::DIRT)));
|
||||||
$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);
|
||||||
|
}
|
||||||
|
}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()){
|
if(!$ev->isCancelled()){
|
||||||
$this->level->setBlock($this, $ev->getNewState(), false, false);
|
$this->level->setBlock($b, $ev->getNewState(), false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_RANDOM;
|
|
||||||
}elseif($lightAbove >= 9){
|
|
||||||
//try grass spread
|
|
||||||
for($i = 0; $i < 4; ++$i){
|
|
||||||
$x = mt_rand($this->x - 1, $this->x + 1);
|
|
||||||
$y = mt_rand($this->y - 3, $this->y + 1);
|
|
||||||
$z = mt_rand($this->z - 1, $this->z + 1);
|
|
||||||
if(
|
|
||||||
$this->level->getBlockIdAt($x, $y, $z) !== Block::DIRT or
|
|
||||||
$this->level->getBlockDataAt($x, $y, $z) === 1 or
|
|
||||||
$this->level->getFullLightAt($x, $y + 1, $z) < 4 or
|
|
||||||
BlockFactory::$lightFilter[$this->level->getBlockIdAt($x, $y + 1, $z)] >= 3
|
|
||||||
){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($b = $this->level->getBlockAt($x, $y, $z), $this, BlockFactory::get(Block::GRASS)));
|
|
||||||
if(!$ev->isCancelled()){
|
|
||||||
$this->level->setBlock($b, $ev->getNewState(), false, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_RANDOM;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
|
@ -25,8 +25,6 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
|
|
||||||
@ -43,7 +41,7 @@ class GrassPath extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_SHOVEL;
|
return BlockToolType::TYPE_SHOVEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
@ -61,18 +59,15 @@ class GrassPath extends Transparent{
|
|||||||
return 0.6;
|
return 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL and $this->getSide(Vector3::SIDE_UP)->isSolid()){
|
if($this->getSide(Vector3::SIDE_UP)->isSolid()){
|
||||||
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
||||||
return $type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [
|
return [
|
||||||
ItemFactory::get(Item::DIRT, 0, 1)
|
ItemFactory::get(Item::DIRT)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,7 +25,6 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class Gravel extends Fallable{
|
class Gravel extends Fallable{
|
||||||
|
|
||||||
@ -44,17 +43,17 @@ class Gravel extends Fallable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_SHOVEL;
|
return BlockToolType::TYPE_SHOVEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
if(mt_rand(1, 10) === 1){
|
if(mt_rand(1, 10) === 1){
|
||||||
return [
|
return [
|
||||||
ItemFactory::get(Item::FLINT, 0, 1)
|
ItemFactory::get(Item::FLINT)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::getDrops($item);
|
return parent::getDropsForCompatibleTool($item);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
|
|
||||||
class HardenedClay extends Solid{
|
class HardenedClay extends Solid{
|
||||||
|
|
||||||
@ -38,7 +38,11 @@ class HardenedClay extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
|
@ -54,4 +54,12 @@ class HayBale extends Solid{
|
|||||||
public function getVariantBitmask() : int{
|
public function getVariantBitmask() : int{
|
||||||
return 0x03;
|
return 0x03;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFlameEncouragement() : int{
|
||||||
|
return 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
}
|
}
|
@ -23,9 +23,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
|
use pocketmine\item\enchantment\Enchantment;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
class Ice extends Transparent{
|
class Ice extends Transparent{
|
||||||
@ -53,29 +52,27 @@ class Ice extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onBreak(Item $item, Player $player = null) : bool{
|
public function onBreak(Item $item, Player $player = null) : bool{
|
||||||
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::WATER), true);
|
if(!$item->hasEnchantment(Enchantment::SILK_TOUCH)){
|
||||||
|
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::WATER), true);
|
||||||
|
}
|
||||||
|
return parent::onBreak($item, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ticksRandomly() : bool{
|
public function ticksRandomly() : bool{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onRandomTick() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_RANDOM){
|
if($this->level->getHighestAdjacentBlockLight($this->x, $this->y, $this->z) >= 12){
|
||||||
if($this->level->getHighestAdjacentBlockLight($this->x, $this->y, $this->z) >= 12){
|
$this->level->useBreakOn($this);
|
||||||
$this->level->useBreakOn($this);
|
|
||||||
|
|
||||||
return $type;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class Iron extends Solid{
|
class Iron extends Solid{
|
||||||
|
|
||||||
@ -39,18 +38,14 @@ class Iron extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_STONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
|
||||||
if($item->isPickaxe() >= Tool::TIER_STONE){
|
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class IronBars extends Thin{
|
class IronBars extends Thin{
|
||||||
|
|
||||||
@ -43,20 +42,14 @@ class IronBars extends Thin{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
public function getVariantBitmask() : int{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
|
||||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
|
|
||||||
class IronDoor extends Door{
|
class IronDoor extends Door{
|
||||||
|
|
||||||
@ -41,18 +41,14 @@ class IronDoor extends Door{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
|
||||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class IronOre extends Solid{
|
class IronOre extends Solid{
|
||||||
|
|
||||||
@ -39,18 +38,14 @@ class IronOre extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_STONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
|
||||||
if($item->isPickaxe() >= Tool::TIER_STONE){
|
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
|
|
||||||
class IronTrapdoor extends Trapdoor{
|
class IronTrapdoor extends Trapdoor{
|
||||||
|
|
||||||
@ -38,6 +38,10 @@ class IronTrapdoor extends Trapdoor{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\tile\ItemFrame as TileItemFrame;
|
use pocketmine\tile\ItemFrame as TileItemFrame;
|
||||||
@ -58,20 +57,16 @@ class ItemFrame extends Flowable{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
$sides = [
|
||||||
$sides = [
|
0 => Vector3::SIDE_WEST,
|
||||||
0 => Vector3::SIDE_WEST,
|
1 => Vector3::SIDE_EAST,
|
||||||
1 => Vector3::SIDE_EAST,
|
2 => Vector3::SIDE_NORTH,
|
||||||
2 => Vector3::SIDE_NORTH,
|
3 => Vector3::SIDE_SOUTH
|
||||||
3 => Vector3::SIDE_SOUTH
|
];
|
||||||
];
|
if(!$this->getSide($sides[$this->meta])->isSolid()){
|
||||||
if(!$this->getSide($sides[$this->meta])->isSolid()){
|
$this->level->useBreakOn($this);
|
||||||
$this->level->useBreakOn($this);
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
@ -99,8 +94,8 @@ class ItemFrame extends Flowable{
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
$drops = parent::getDrops($item);
|
$drops = parent::getDropsForCompatibleTool($item);
|
||||||
|
|
||||||
$tile = $this->level->getTile($this);
|
$tile = $this->level->getTile($this);
|
||||||
if($tile instanceof TileItemFrame){
|
if($tile instanceof TileItemFrame){
|
||||||
@ -112,4 +107,8 @@ class ItemFrame extends Flowable{
|
|||||||
|
|
||||||
return $drops;
|
return $drops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isAffectedBySilkTouch() : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
@ -25,8 +25,6 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
@ -92,7 +90,7 @@ class Ladder extends Transparent{
|
|||||||
|
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
if($blockClicked->isTransparent() === false){
|
if(!$blockClicked->isTransparent()){
|
||||||
$faces = [
|
$faces = [
|
||||||
2 => 2,
|
2 => 2,
|
||||||
3 => 3,
|
3 => 3,
|
||||||
@ -110,19 +108,14 @@ class Ladder extends Transparent{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if(!$this->getSide($this->meta ^ 0x01)->isSolid()){ //Replace with common break method
|
||||||
if(!$this->getSide($this->meta ^ 0x01)->isSolid()){ //Replace with common break method
|
$this->level->useBreakOn($this);
|
||||||
$this->level->useBreakOn($this);
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_AXE;
|
return BlockToolType::TYPE_AXE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
public function getVariantBitmask() : int{
|
||||||
|
@ -23,8 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class Lapis extends Solid{
|
class Lapis extends Solid{
|
||||||
|
|
||||||
@ -39,19 +38,14 @@ class Lapis extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_STONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
|
||||||
if($item->isPickaxe() >= Tool::TIER_STONE){
|
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -25,7 +25,7 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\Tool;
|
use pocketmine\item\TieredTool;
|
||||||
|
|
||||||
class LapisOre extends Solid{
|
class LapisOre extends Solid{
|
||||||
|
|
||||||
@ -40,21 +40,21 @@ class LapisOre extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_STONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return "Lapis Lazuli Ore";
|
return "Lapis Lazuli Ore";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
if($item->isPickaxe() >= Tool::TIER_STONE){
|
return [
|
||||||
return [
|
ItemFactory::get(Item::DYE, 4, mt_rand(4, 8))
|
||||||
ItemFactory::get(Item::DYE, 4, mt_rand(4, 8))
|
];
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -29,6 +29,7 @@ use pocketmine\event\entity\EntityDamageByBlockEvent;
|
|||||||
use pocketmine\event\entity\EntityDamageEvent;
|
use pocketmine\event\entity\EntityDamageEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
|
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\Server;
|
use pocketmine\Server;
|
||||||
|
|
||||||
@ -48,6 +49,22 @@ class Lava extends Liquid{
|
|||||||
return "Lava";
|
return "Lava";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getStillForm() : Block{
|
||||||
|
return BlockFactory::get(Block::STILL_LAVA, $this->meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlowingForm() : Block{
|
||||||
|
return BlockFactory::get(Block::FLOWING_LAVA, $this->meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBucketFillSound() : int{
|
||||||
|
return LevelSoundEventPacket::SOUND_BUCKET_FILL_LAVA;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBucketEmptySound() : int{
|
||||||
|
return LevelSoundEventPacket::SOUND_BUCKET_EMPTY_LAVA;
|
||||||
|
}
|
||||||
|
|
||||||
public function tickRate() : int{
|
public function tickRate() : int{
|
||||||
return 30;
|
return 30;
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,6 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\event\block\LeavesDecayEvent;
|
use pocketmine\event\block\LeavesDecayEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
use pocketmine\level\Level;
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
@ -51,7 +49,7 @@ class Leaves extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_SHEARS;
|
return BlockToolType::TYPE_SHEARS;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
@ -68,11 +66,8 @@ class Leaves extends Transparent{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ticksRandomly() : bool{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function findLog(Block $pos, array $visited, $distance, &$check, $fromSide = null){
|
protected function findLog(Block $pos, array $visited, $distance, &$check, $fromSide = null) : bool{
|
||||||
++$check;
|
++$check;
|
||||||
$index = $pos->x . "." . $pos->y . "." . $pos->z;
|
$index = $pos->x . "." . $pos->y . "." . $pos->z;
|
||||||
if(isset($visited[$index])){
|
if(isset($visited[$index])){
|
||||||
@ -88,45 +83,45 @@ class Leaves extends Transparent{
|
|||||||
}
|
}
|
||||||
if($fromSide === null){
|
if($fromSide === null){
|
||||||
for($side = 2; $side <= 5; ++$side){
|
for($side = 2; $side <= 5; ++$side){
|
||||||
if($this->findLog($pos->getSide($side), $visited, $distance + 1, $check, $side) === true){
|
if($this->findLog($pos->getSide($side), $visited, $distance + 1, $check, $side)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{ //No more loops
|
}else{ //No more loops
|
||||||
switch($fromSide){
|
switch($fromSide){
|
||||||
case 2:
|
case 2:
|
||||||
if($this->findLog($pos->getSide(Vector3::SIDE_NORTH), $visited, $distance + 1, $check, $fromSide) === true){
|
if($this->findLog($pos->getSide(Vector3::SIDE_NORTH), $visited, $distance + 1, $check, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}elseif($this->findLog($pos->getSide(Vector3::SIDE_WEST), $visited, $distance + 1, $check, $fromSide) === true){
|
}elseif($this->findLog($pos->getSide(Vector3::SIDE_WEST), $visited, $distance + 1, $check, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}elseif($this->findLog($pos->getSide(Vector3::SIDE_EAST), $visited, $distance + 1, $check, $fromSide) === true){
|
}elseif($this->findLog($pos->getSide(Vector3::SIDE_EAST), $visited, $distance + 1, $check, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if($this->findLog($pos->getSide(Vector3::SIDE_SOUTH), $visited, $distance + 1, $check, $fromSide) === true){
|
if($this->findLog($pos->getSide(Vector3::SIDE_SOUTH), $visited, $distance + 1, $check, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}elseif($this->findLog($pos->getSide(Vector3::SIDE_WEST), $visited, $distance + 1, $check, $fromSide) === true){
|
}elseif($this->findLog($pos->getSide(Vector3::SIDE_WEST), $visited, $distance + 1, $check, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}elseif($this->findLog($pos->getSide(Vector3::SIDE_EAST), $visited, $distance + 1, $check, $fromSide) === true){
|
}elseif($this->findLog($pos->getSide(Vector3::SIDE_EAST), $visited, $distance + 1, $check, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if($this->findLog($pos->getSide(Vector3::SIDE_NORTH), $visited, $distance + 1, $check, $fromSide) === true){
|
if($this->findLog($pos->getSide(Vector3::SIDE_NORTH), $visited, $distance + 1, $check, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}elseif($this->findLog($pos->getSide(Vector3::SIDE_SOUTH), $visited, $distance + 1, $check, $fromSide) === true){
|
}elseif($this->findLog($pos->getSide(Vector3::SIDE_SOUTH), $visited, $distance + 1, $check, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}elseif($this->findLog($pos->getSide(Vector3::SIDE_WEST), $visited, $distance + 1, $check, $fromSide) === true){
|
}elseif($this->findLog($pos->getSide(Vector3::SIDE_WEST), $visited, $distance + 1, $check, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
if($this->findLog($pos->getSide(Vector3::SIDE_NORTH), $visited, $distance + 1, $check, $fromSide) === true){
|
if($this->findLog($pos->getSide(Vector3::SIDE_NORTH), $visited, $distance + 1, $check, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}elseif($this->findLog($pos->getSide(Vector3::SIDE_SOUTH), $visited, $distance + 1, $check, $fromSide) === true){
|
}elseif($this->findLog($pos->getSide(Vector3::SIDE_SOUTH), $visited, $distance + 1, $check, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}elseif($this->findLog($pos->getSide(Vector3::SIDE_EAST), $visited, $distance + 1, $check, $fromSide) === true){
|
}elseif($this->findLog($pos->getSide(Vector3::SIDE_EAST), $visited, $distance + 1, $check, $fromSide)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -137,31 +132,31 @@ class Leaves extends Transparent{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onUpdate(int $type){
|
public function onNearbyBlockChange() : void{
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
if(($this->meta & 0b00001100) === 0){
|
||||||
if(($this->meta & 0b00001100) === 0){
|
$this->meta |= 0x08;
|
||||||
$this->meta |= 0x08;
|
$this->getLevel()->setBlock($this, $this, true, false);
|
||||||
$this->getLevel()->setBlock($this, $this, true, false);
|
}
|
||||||
}
|
}
|
||||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
|
||||||
if(($this->meta & 0b00001100) === 0x08){
|
|
||||||
$this->meta &= 0x03;
|
|
||||||
$visited = [];
|
|
||||||
$check = 0;
|
|
||||||
|
|
||||||
$this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new LeavesDecayEvent($this));
|
public function ticksRandomly() : bool{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if($ev->isCancelled() or $this->findLog($this, $visited, 0, $check) === true){
|
public function onRandomTick() : void{
|
||||||
$this->getLevel()->setBlock($this, $this, false, false);
|
if(($this->meta & 0b00001100) === 0x08){
|
||||||
}else{
|
$this->meta &= 0x03;
|
||||||
$this->getLevel()->useBreakOn($this);
|
$visited = [];
|
||||||
|
$check = 0;
|
||||||
|
|
||||||
return Level::BLOCK_UPDATE_NORMAL;
|
$this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new LeavesDecayEvent($this));
|
||||||
}
|
|
||||||
|
if($ev->isCancelled() or $this->findLog($this, $visited, 0, $check)){
|
||||||
|
$this->getLevel()->setBlock($this, $this, false, false);
|
||||||
|
}else{
|
||||||
|
$this->getLevel()->useBreakOn($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
@ -174,8 +169,8 @@ class Leaves extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDrops(Item $item) : array{
|
||||||
if($item->isShears()){
|
if($item->getBlockToolType() & BlockToolType::TYPE_SHEARS){
|
||||||
return parent::getDrops($item);
|
return $this->getDropsForCompatibleTool($item);
|
||||||
}
|
}
|
||||||
|
|
||||||
$drops = [];
|
$drops = [];
|
||||||
@ -183,7 +178,7 @@ class Leaves extends Transparent{
|
|||||||
$drops[] = $this->getSaplingItem();
|
$drops[] = $this->getSaplingItem();
|
||||||
}
|
}
|
||||||
if($this->canDropApples() and mt_rand(1, 200) === 1){ //Apples
|
if($this->canDropApples() and mt_rand(1, 200) === 1){ //Apples
|
||||||
$drops[] = ItemFactory::get(Item::APPLE, 0, 1);
|
$drops[] = ItemFactory::get(Item::APPLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $drops;
|
return $drops;
|
||||||
@ -196,4 +191,12 @@ class Leaves extends Transparent{
|
|||||||
public function canDropApples() : bool{
|
public function canDropApples() : bool{
|
||||||
return $this->meta === self::OAK;
|
return $this->meta === self::OAK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFlameEncouragement() : int{
|
||||||
|
return 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return 60;
|
||||||
|
}
|
||||||
}
|
}
|
@ -23,6 +23,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\math\Vector3;
|
||||||
|
use pocketmine\Player;
|
||||||
|
|
||||||
class Lever extends Flowable{
|
class Lever extends Flowable{
|
||||||
|
|
||||||
protected $id = self::LEVER;
|
protected $id = self::LEVER;
|
||||||
@ -34,4 +38,56 @@ class Lever extends Flowable{
|
|||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return "Lever";
|
return "Lever";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getHardness() : float{
|
||||||
|
return 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVariantBitmask() : int{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
|
if(!$blockClicked->isSolid()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($face === Vector3::SIDE_DOWN){
|
||||||
|
$this->meta = 0;
|
||||||
|
}else{
|
||||||
|
$this->meta = 6 - $face;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($player !== null){
|
||||||
|
if(($player->getDirection() & 0x01) === 0){
|
||||||
|
if($face === Vector3::SIDE_UP){
|
||||||
|
$this->meta = 6;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if($face === Vector3::SIDE_DOWN){
|
||||||
|
$this->meta = 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->level->setBlock($blockReplace, $this, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onNearbyBlockChange() : void{
|
||||||
|
$faces = [
|
||||||
|
0 => Vector3::SIDE_UP,
|
||||||
|
1 => Vector3::SIDE_WEST,
|
||||||
|
2 => Vector3::SIDE_EAST,
|
||||||
|
3 => Vector3::SIDE_NORTH,
|
||||||
|
4 => Vector3::SIDE_SOUTH,
|
||||||
|
5 => Vector3::SIDE_DOWN,
|
||||||
|
6 => Vector3::SIDE_DOWN,
|
||||||
|
7 => Vector3::SIDE_UP
|
||||||
|
];
|
||||||
|
if(!$this->getSide($faces[$this->meta & 0x07])->isSolid()){
|
||||||
|
$this->level->useBreakOn($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO
|
||||||
}
|
}
|
||||||
|
@ -72,10 +72,18 @@ abstract class Liquid extends Transparent{
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract public function getStillForm() : Block;
|
||||||
|
|
||||||
|
abstract public function getFlowingForm() : Block;
|
||||||
|
|
||||||
|
abstract public function getBucketFillSound() : int;
|
||||||
|
|
||||||
|
abstract public function getBucketEmptySound() : int;
|
||||||
|
|
||||||
public function getFluidHeightPercent(){
|
public function getFluidHeightPercent(){
|
||||||
$d = $this->meta;
|
$d = $this->meta;
|
||||||
if($d >= 8){
|
if($d >= 8){
|
||||||
@ -181,10 +189,12 @@ abstract class Liquid extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function addVelocityToEntity(Entity $entity, Vector3 $vector) : void{
|
public function addVelocityToEntity(Entity $entity, Vector3 $vector) : void{
|
||||||
$flow = $this->getFlowVector();
|
if($entity->canBeMovedByCurrents()){
|
||||||
$vector->x += $flow->x;
|
$flow = $this->getFlowVector();
|
||||||
$vector->y += $flow->y;
|
$vector->x += $flow->x;
|
||||||
$vector->z += $flow->z;
|
$vector->y += $flow->y;
|
||||||
|
$vector->z += $flow->z;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract public function tickRate() : int;
|
abstract public function tickRate() : int;
|
||||||
@ -198,101 +208,88 @@ abstract class Liquid extends Transparent{
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function onNearbyBlockChange() : void{
|
||||||
* {@inheritdoc}
|
$this->checkForHarden();
|
||||||
*
|
$this->level->scheduleDelayedBlockUpdate($this, $this->tickRate());
|
||||||
* @param int $type
|
}
|
||||||
*
|
|
||||||
* @return bool|int
|
|
||||||
*/
|
|
||||||
public function onUpdate(int $type){
|
|
||||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
|
||||||
$this->checkForHarden();
|
|
||||||
$this->level->scheduleDelayedBlockUpdate($this, $this->tickRate());
|
|
||||||
|
|
||||||
return $type;
|
public function onScheduledUpdate() : void{
|
||||||
}elseif($type === Level::BLOCK_UPDATE_SCHEDULED){
|
$decay = $this->getFlowDecay($this);
|
||||||
$decay = $this->getFlowDecay($this);
|
$multiplier = $this->getFlowDecayPerBlock();
|
||||||
$multiplier = $this->getFlowDecayPerBlock();
|
|
||||||
|
|
||||||
if($decay > 0){
|
if($decay > 0){
|
||||||
$smallestFlowDecay = -100;
|
$smallestFlowDecay = -100;
|
||||||
$this->adjacentSources = 0;
|
$this->adjacentSources = 0;
|
||||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $smallestFlowDecay);
|
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $smallestFlowDecay);
|
||||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x, $this->y, $this->z + 1), $smallestFlowDecay);
|
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x, $this->y, $this->z + 1), $smallestFlowDecay);
|
||||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x - 1, $this->y, $this->z), $smallestFlowDecay);
|
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x - 1, $this->y, $this->z), $smallestFlowDecay);
|
||||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $smallestFlowDecay);
|
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $smallestFlowDecay);
|
||||||
|
|
||||||
$newDecay = $smallestFlowDecay + $multiplier;
|
$newDecay = $smallestFlowDecay + $multiplier;
|
||||||
|
|
||||||
if($newDecay >= 8 or $smallestFlowDecay < 0){
|
if($newDecay >= 8 or $smallestFlowDecay < 0){
|
||||||
$newDecay = -1;
|
$newDecay = -1;
|
||||||
}
|
|
||||||
|
|
||||||
if(($topFlowDecay = $this->getFlowDecay($this->level->getBlockAt($this->x, $this->y + 1, $this->z))) >= 0){
|
|
||||||
$newDecay = $topFlowDecay | 0x08;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($this->adjacentSources >= 2 and $this instanceof Water){
|
|
||||||
$bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z);
|
|
||||||
if($bottomBlock->isSolid()){
|
|
||||||
$newDecay = 0;
|
|
||||||
}elseif($bottomBlock instanceof Water and $bottomBlock->getDamage() === 0){
|
|
||||||
$newDecay = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if($newDecay !== $decay){
|
|
||||||
$decay = $newDecay;
|
|
||||||
if($decay < 0){
|
|
||||||
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true, true);
|
|
||||||
}else{
|
|
||||||
$this->level->setBlock($this, BlockFactory::get($this->id, $decay), true, true);
|
|
||||||
$this->level->scheduleDelayedBlockUpdate($this, $this->tickRate());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($decay >= 0){
|
if(($topFlowDecay = $this->getFlowDecay($this->level->getBlockAt($this->x, $this->y + 1, $this->z))) >= 0){
|
||||||
|
$newDecay = $topFlowDecay | 0x08;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->adjacentSources >= 2 and $this instanceof Water){
|
||||||
$bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z);
|
$bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z);
|
||||||
|
if($bottomBlock->isSolid()){
|
||||||
$this->flowIntoBlock($bottomBlock, $decay | 0x08);
|
$newDecay = 0;
|
||||||
|
}elseif($bottomBlock instanceof Water and $bottomBlock->getDamage() === 0){
|
||||||
if($decay === 0 or !$bottomBlock->canBeFlowedInto()){
|
$newDecay = 0;
|
||||||
if($decay >= 8){
|
|
||||||
$adjacentDecay = 1;
|
|
||||||
}else{
|
|
||||||
$adjacentDecay = $decay + $multiplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($adjacentDecay < 8){
|
|
||||||
$flags = $this->getOptimalFlowDirections();
|
|
||||||
|
|
||||||
if($flags[0]){
|
|
||||||
$this->flowIntoBlock($this->level->getBlockAt($this->x - 1, $this->y, $this->z), $adjacentDecay);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($flags[1]){
|
|
||||||
$this->flowIntoBlock($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $adjacentDecay);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($flags[2]){
|
|
||||||
$this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $adjacentDecay);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($flags[3]){
|
|
||||||
$this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z + 1), $adjacentDecay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->checkForHarden();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $type;
|
if($newDecay !== $decay){
|
||||||
|
$decay = $newDecay;
|
||||||
|
if($decay < 0){
|
||||||
|
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true, true);
|
||||||
|
}else{
|
||||||
|
$this->level->setBlock($this, BlockFactory::get($this->id, $decay), true, true);
|
||||||
|
$this->level->scheduleDelayedBlockUpdate($this, $this->tickRate());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
if($decay >= 0){
|
||||||
|
$bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z);
|
||||||
|
|
||||||
|
$this->flowIntoBlock($bottomBlock, $decay | 0x08);
|
||||||
|
|
||||||
|
if($decay === 0 or !$bottomBlock->canBeFlowedInto()){
|
||||||
|
if($decay >= 8){
|
||||||
|
$adjacentDecay = 1;
|
||||||
|
}else{
|
||||||
|
$adjacentDecay = $decay + $multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($adjacentDecay < 8){
|
||||||
|
$flags = $this->getOptimalFlowDirections();
|
||||||
|
|
||||||
|
if($flags[0]){
|
||||||
|
$this->flowIntoBlock($this->level->getBlockAt($this->x - 1, $this->y, $this->z), $adjacentDecay);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($flags[1]){
|
||||||
|
$this->flowIntoBlock($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $adjacentDecay);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($flags[2]){
|
||||||
|
$this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $adjacentDecay);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($flags[3]){
|
||||||
|
$this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z + 1), $adjacentDecay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->checkForHarden();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function flowIntoBlock(Block $block, int $newFlowDecay) : void{
|
protected function flowIntoBlock(Block $block, int $newFlowDecay) : void{
|
||||||
|
@ -26,8 +26,7 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\entity\Entity;
|
use pocketmine\entity\Entity;
|
||||||
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||||
use pocketmine\event\entity\EntityDamageEvent;
|
use pocketmine\event\entity\EntityDamageEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\item\Tool;
|
|
||||||
|
|
||||||
class Magma extends Solid{
|
class Magma extends Solid{
|
||||||
|
|
||||||
@ -46,7 +45,11 @@ class Magma extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return Tool::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLightLevel() : int{
|
public function getLightLevel() : int{
|
||||||
@ -64,12 +67,7 @@ class Magma extends Solid{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function burnsForever() : bool{
|
||||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
return true;
|
||||||
return parent::getDrops($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user