mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-08 19:02:59 +00:00
Compare commits
586 Commits
4.0.0-BETA
...
4.0.2
Author | SHA1 | Date | |
---|---|---|---|
178dcb71a9 | |||
0a58fd5472 | |||
e06eefeab0 | |||
ede07c4314 | |||
cba00bf1e2 | |||
e81bee3866 | |||
e6b85988b2 | |||
b50591303b | |||
448f26cefc | |||
fa48100da5 | |||
bcf8a3424c | |||
69d5bfa0d4 | |||
549fb923bf | |||
6d5c463bdd | |||
911ad344c9 | |||
3b77462935 | |||
6b40ed7bf8 | |||
1ed9302f5a | |||
b3dab0beef | |||
6ddaed97fa | |||
036b90d247 | |||
d909cd8a91 | |||
06eaf9f273 | |||
1e56ed2ea3 | |||
dccb8a3595 | |||
0ace807756 | |||
40895a86e5 | |||
b081394125 | |||
f48cf68cac | |||
264cff70ec | |||
3aabfa4ab0 | |||
0793e7e094 | |||
3d9e19546f | |||
e0eeb87ea0 | |||
78ffad5ffc | |||
5a351d3b17 | |||
0c012ca5d9 | |||
0530cb72df | |||
ee060f3e02 | |||
e7deffa9af | |||
6e4b73c183 | |||
62f150586f | |||
8ed9551ac9 | |||
4d2d0f1d35 | |||
cac9db9bcc | |||
300d194185 | |||
13340a21d3 | |||
27f599793a | |||
527e975fa9 | |||
8e37f86480 | |||
8e8cee45b8 | |||
1a046c6cd5 | |||
e61aaaccca | |||
1b86355c40 | |||
1669d33f7e | |||
2da65c5a6e | |||
468faa464b | |||
59de045ecb | |||
bd8308cc6f | |||
edc3bae172 | |||
06e7030817 | |||
cb0af44ccb | |||
d535f02096 | |||
7665f4f443 | |||
20d6b69813 | |||
6b7d0307af | |||
baeac2eb07 | |||
2850ea1e89 | |||
d560cf17fc | |||
3f6efd0018 | |||
aea124af74 | |||
8620e67d88 | |||
d5f81fe261 | |||
0aeac3af7d | |||
9931c1d50a | |||
d21a3d8750 | |||
6d62b06ce6 | |||
8be92d16fe | |||
8079ae341a | |||
ba295dc7dc | |||
38325c8573 | |||
f239b077b9 | |||
6f8f460a6c | |||
882df94bcb | |||
4a8ca603a1 | |||
52f0c4f3ed | |||
e2815eed60 | |||
932a88764c | |||
9540193766 | |||
cc23e0b7a1 | |||
1f9400f901 | |||
e5149756a8 | |||
bc18969a09 | |||
c19174a174 | |||
f95142f6b6 | |||
7ace24caab | |||
32f619ac49 | |||
1bb6ac4fb6 | |||
533d3aae8b | |||
52a891ba73 | |||
71b813d4f9 | |||
f2540a72ad | |||
03f13495b7 | |||
7e0f6c02a1 | |||
1bc7869f6e | |||
5556861000 | |||
7dd5d0b593 | |||
9338d42742 | |||
9346ecdc39 | |||
c023c02b6c | |||
bb7683158f | |||
fad96b77ce | |||
40575a6dcf | |||
40f8f042da | |||
0fe6038c41 | |||
adff561483 | |||
ad56392d95 | |||
472ffb28ff | |||
726c5652f7 | |||
b784a04e08 | |||
5c7125f190 | |||
eb0cf52d81 | |||
d8f0fd0a7e | |||
fb0eebc0dc | |||
020cd7b966 | |||
c37c261c0f | |||
2bb97d8904 | |||
d3878b2d57 | |||
cbe0f44c4f | |||
37622e02b8 | |||
ed8b4950a3 | |||
fc7d297f60 | |||
7b4ef293bd | |||
c72d66f370 | |||
3683884b9c | |||
37e8b1ee8c | |||
046dafc34f | |||
db135788b9 | |||
b34e6f53eb | |||
b4b954cc5f | |||
7210db25b0 | |||
4599913034 | |||
c48aa274e7 | |||
269231c228 | |||
4cad552909 | |||
f2d5455c5e | |||
65247b7248 | |||
2f408708f0 | |||
3dd03075cb | |||
82b5bca83e | |||
639867a640 | |||
d4a382d568 | |||
399824c31c | |||
ada469bc45 | |||
dc8243f88b | |||
7668171c56 | |||
e4754ab029 | |||
3276047497 | |||
49a8eff11e | |||
73592349cd | |||
635a9143de | |||
c3ec9c0948 | |||
09a2e006a8 | |||
fed59d3ebe | |||
c7beb0a702 | |||
5be429a8c4 | |||
ab002ca06d | |||
6efb1db107 | |||
6fdcfb01c8 | |||
1beec348f9 | |||
7306a2d939 | |||
4bf338f783 | |||
255ff63fda | |||
d72f6a3ac6 | |||
93a1e84ad9 | |||
c33f97ae41 | |||
cc4bb91fcb | |||
eb9012401b | |||
3b34268ed6 | |||
4c07078586 | |||
19a3efe893 | |||
a1ecdc27e5 | |||
f93b5be789 | |||
1fb60b5b3a | |||
08420c2556 | |||
18f5fb66bb | |||
a6f6b60bed | |||
c6c992a1f0 | |||
df39a1ca07 | |||
be6d1843de | |||
2b0b9bd8ed | |||
76dad46e13 | |||
eb3530b6e6 | |||
4131bcef08 | |||
b84f7c18ec | |||
45edb94607 | |||
6b316dc29a | |||
d9d37f7fa6 | |||
4cb6c7dc1e | |||
b392651354 | |||
f81c55ce6c | |||
002feacf8e | |||
b8523f7a18 | |||
640e88009b | |||
6cd272c9e1 | |||
566c57bcd3 | |||
3c754b079c | |||
dbf9a33160 | |||
07b1cff306 | |||
0989c77037 | |||
5107d0df4e | |||
579ef63663 | |||
8abc952c74 | |||
4c3a5fdd73 | |||
54f287feb6 | |||
84f8b3eb2d | |||
15fca84f3b | |||
c60144210f | |||
8ac999cbd4 | |||
4f8501ff34 | |||
2405e45b35 | |||
e0b07ff308 | |||
729f831b8f | |||
0356716e8e | |||
5c81b04813 | |||
1ebb206762 | |||
29e2d92098 | |||
ef82a2cd79 | |||
87031627bf | |||
f066199971 | |||
a0e9eec652 | |||
fa6a432d58 | |||
102277c636 | |||
f50f26d52e | |||
4ca7c29cde | |||
9f64bc8180 | |||
f75a05d7fa | |||
3dae873731 | |||
aa0dc60c32 | |||
d184838ba0 | |||
ead8ccf08d | |||
38f97bed52 | |||
275f145418 | |||
6b07f7a5ec | |||
e131c2cefa | |||
e34364412b | |||
4eef458d29 | |||
8b3565b75d | |||
facfd7c04a | |||
65ef9f786a | |||
4dc13ab3da | |||
ede4157814 | |||
34ea199fb0 | |||
1775699f05 | |||
32a857b8b4 | |||
7e4be29fc4 | |||
c17587d436 | |||
0f6b7e48cb | |||
f2912fcdd8 | |||
f6cb4f9597 | |||
54442f7e4b | |||
5257755dc5 | |||
8c16ecaa5b | |||
3214da8642 | |||
f827a555d5 | |||
61145baded | |||
4d54d6c552 | |||
485bc2c565 | |||
07b4f844a9 | |||
19e5775f6b | |||
804fb3f603 | |||
6175b03433 | |||
a78248a19c | |||
414ccb9f10 | |||
794142fe49 | |||
ff27c5f7db | |||
4d4362801f | |||
0babe0a1ab | |||
d696ebcda3 | |||
c3768b997a | |||
f6480017ce | |||
9f5c16bc46 | |||
8865bb73ba | |||
2dee1dbc28 | |||
0f0b6f0efa | |||
d5f13d8be2 | |||
27ae959e89 | |||
f8f39687e2 | |||
94737934de | |||
debb469de1 | |||
616eb0050d | |||
9d30bc8b95 | |||
46b7d35cd3 | |||
c781efcf90 | |||
e4a54f5b6a | |||
afb54f1ae4 | |||
8f803df511 | |||
f4a3c40b5c | |||
9dec82cdbc | |||
74031d2fbe | |||
bd60e41268 | |||
96cfdc79b8 | |||
2fa0a914ff | |||
08636d079d | |||
3265d3f6b4 | |||
0f78a2b5ef | |||
f1a791ef75 | |||
866020dfdb | |||
c580bb2434 | |||
4fe3f69702 | |||
018006541e | |||
fbb91d123d | |||
3dc75644d9 | |||
1cabe4baf3 | |||
73dc0598e4 | |||
faad2365e2 | |||
4f816d03a7 | |||
1d22761d27 | |||
5b8ce7e3e2 | |||
08f3c18de9 | |||
141fbde660 | |||
465a509858 | |||
69952ae2af | |||
71f2a34616 | |||
63dfcc60c3 | |||
428bd5ae91 | |||
d17cd65803 | |||
a8d5e8c5f6 | |||
19f448d074 | |||
1c18c731ef | |||
8a2ecfe1d4 | |||
089e62b44e | |||
32a34d2494 | |||
ee9f5e0044 | |||
88b7389080 | |||
f1cc168d26 | |||
fb5543a2ad | |||
a4eda9a8f5 | |||
eb75df6f8e | |||
c66790b6a6 | |||
d78801b9d5 | |||
d410db4302 | |||
a62ce64fdd | |||
5db3915aad | |||
eb40b741ae | |||
b3720b3f17 | |||
7effa03ba4 | |||
d0474ccd92 | |||
2b0768f720 | |||
dba148cfaa | |||
48f77abe7e | |||
bb05af103d | |||
0ef5c67b9b | |||
6d89265510 | |||
a7d8a598e1 | |||
51fbff204b | |||
1873457840 | |||
fca70efbb1 | |||
8f88393184 | |||
b9d9b69bbe | |||
1d99cd329a | |||
bd8cba1a7f | |||
24d4daec90 | |||
4178c81209 | |||
94f4ef5862 | |||
2e2515354c | |||
359d0835f3 | |||
d4cbde6f10 | |||
a5418a019d | |||
baba25953f | |||
d53347454b | |||
401e8d117b | |||
9835d75f65 | |||
b8519d1af4 | |||
f6e53f826b | |||
42ede30e77 | |||
04aedc6494 | |||
701a71a4ee | |||
e50072dc27 | |||
c77829f4ad | |||
c773e43eda | |||
c262c2e726 | |||
a4b65d6a3f | |||
986b4e0651 | |||
2971bf30a5 | |||
4f2bcb61d6 | |||
e2275cc8ec | |||
620874d902 | |||
44508a138f | |||
aa408c9a97 | |||
6d78a0b435 | |||
76b4b23d98 | |||
03fcd844eb | |||
fecc13f362 | |||
9646128d01 | |||
a788954551 | |||
dc07ac33d3 | |||
ec3986827c | |||
09c840b66a | |||
80b402e529 | |||
a3f8546ac4 | |||
46920818b5 | |||
69cb575789 | |||
fee6478cbe | |||
9c5cec77b1 | |||
f48b703533 | |||
70636f6eb4 | |||
c70b80c273 | |||
a794d24c81 | |||
8db5732b44 | |||
48f809d3fa | |||
0348236860 | |||
8c07748100 | |||
06e7338ff9 | |||
bdbfa70558 | |||
7a4af7a0bc | |||
34b1392598 | |||
321345fcc8 | |||
0ac9f4fe61 | |||
2db53775e0 | |||
8523f0fb0b | |||
b570324288 | |||
6284cd14c7 | |||
ce8af4e3bc | |||
b65e89b605 | |||
d3f74d6ce1 | |||
bbd925abc4 | |||
4bf6205a6c | |||
b5699679ef | |||
824a89edfe | |||
ead9aae23c | |||
aefa0afd7c | |||
ec2699ffee | |||
49c1e4c06e | |||
9b94a4661b | |||
62f11360ee | |||
a5833327f0 | |||
d73ea8efe4 | |||
835e18ce6e | |||
01c0602043 | |||
8fd475f87b | |||
34f54750c8 | |||
092aabeb97 | |||
89d7b7198f | |||
70deea0ef9 | |||
859cdfa5d2 | |||
fa93a8d78f | |||
7b6632941d | |||
e62794e4cf | |||
500c298aaf | |||
8ac16345a3 | |||
19a66a8d03 | |||
6d728e8d98 | |||
e1ee320c8d | |||
965a16d19d | |||
5bae458a91 | |||
2696698926 | |||
912e612743 | |||
fd2df637b6 | |||
aa53dc6709 | |||
c1f843a42c | |||
09715906c8 | |||
13068ba3a7 | |||
b54854529f | |||
974d08efd6 | |||
289553fa46 | |||
e38866c4ba | |||
58a95f8836 | |||
ccc881ee58 | |||
308d7c126a | |||
4910250a81 | |||
e0d2e24698 | |||
d5f02a0bf8 | |||
2a3a57c519 | |||
5115387feb | |||
dd0aaf59b5 | |||
a555f21b18 | |||
1be9b2f037 | |||
32fd9879e5 | |||
dc2e8e7e8f | |||
847e24fc41 | |||
9e6d740570 | |||
8e3772ceef | |||
e032b8fe20 | |||
90800a4124 | |||
4b00465e24 | |||
10b3596eef | |||
258c38f9cd | |||
d07517fe8b | |||
31a176286d | |||
1fafce6d6f | |||
5061bbbc25 | |||
a101d1cdf9 | |||
fec48003d9 | |||
e25c03eec1 | |||
7245d15abe | |||
13178a47a5 | |||
817ab88c70 | |||
fef8297907 | |||
dbeaf27cb7 | |||
2db79cf58d | |||
7d06b76aaf | |||
0ad663ff50 | |||
a27c14c00c | |||
5b26abcb0e | |||
f2d6059613 | |||
bb6ea8cbdc | |||
356a49d225 | |||
6332af3e59 | |||
fb570970a8 | |||
30e10c38b6 | |||
05dc675d5b | |||
d63b9d1648 | |||
f9e6fd44bc | |||
0108888450 | |||
dd0c2fed82 | |||
2566123e49 | |||
54174eefa0 | |||
f5266ec816 | |||
c6b2c63a9b | |||
f26f063164 | |||
81d5598e96 | |||
c7e9138994 | |||
88f799da2c | |||
8de30e8162 | |||
e6f6a036ef | |||
32f8b8163e | |||
5b818827db | |||
42bf9578ce | |||
aee4a00a50 | |||
2fdd8d039e | |||
349f37b15f | |||
afa3349c04 | |||
6a8280b1ba | |||
003c002208 | |||
d417b1e2f5 | |||
65e468e3c2 | |||
a11cf8c296 | |||
c931c52617 | |||
b3e8314b9f | |||
f138004913 | |||
8e2d06a880 | |||
eb80515e99 | |||
1cb540387c | |||
9bc07a9cc0 | |||
5f1e66478b | |||
36b8217e68 | |||
d455188d03 | |||
14fba36636 | |||
43ac3fbf3e | |||
352162a6e6 | |||
b3601c9390 | |||
817fec9e3d | |||
3813caf5ec | |||
e472c117e0 | |||
ceeef7c729 | |||
7f1b2a0ee5 | |||
27324a3aeb | |||
133398c69a | |||
52b6952771 | |||
1ce388ca0b | |||
971cbe3929 | |||
18de35ffc7 | |||
576c33ee8f | |||
6b2ab15ea1 | |||
027f7e249b | |||
a9c4238c59 | |||
34e1b244fa | |||
b047100719 | |||
1b5071e074 | |||
3836a57ba6 | |||
87dc763d92 | |||
43b2e1a0e8 | |||
05e2bef5ce | |||
6cf181b579 | |||
9490b78640 | |||
59f3622f69 | |||
a1c82da2f2 | |||
84170ad3e1 | |||
ace8841d5d | |||
5ddd94b7e8 | |||
f0fa561c2f | |||
33a7c05425 | |||
273aa8ab42 | |||
3b7580688c | |||
b65e3c69b1 |
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -4,6 +4,7 @@
|
||||
*.sh text eol=lf
|
||||
*.txt text eol=lf
|
||||
*.properties text eol=lf
|
||||
*.neon text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.cmd text eol=crlf
|
||||
*.ps1 text eol=crlf
|
||||
|
13
.github/workflows/draft-release.yml
vendored
13
.github/workflows/draft-release.yml
vendored
@ -35,17 +35,18 @@ jobs:
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --no-dev --prefer-dist --no-interaction --ignore-platform-reqs
|
||||
|
||||
- name: Patch VersionInfo
|
||||
- name: Calculate build number
|
||||
id: build-number
|
||||
run: |
|
||||
BUILD_NUMBER=2000+$GITHUB_RUN_NUMBER #to stay above jenkins
|
||||
BUILD_NUMBER=$((2000+$GITHUB_RUN_NUMBER)) #to stay above jenkins
|
||||
echo "Build number: $BUILD_NUMBER"
|
||||
sed -i "s/const BUILD_NUMBER = 0/const BUILD_NUMBER = ${BUILD_NUMBER}/" src/VersionInfo.php
|
||||
echo ::set-output name=BUILD_NUMBER::$BUILD_NUMBER
|
||||
|
||||
- name: Minify BedrockData JSON files
|
||||
run: php resources/vanilla/.minify_json.php
|
||||
run: php vendor/pocketmine/bedrock-data/.minify_json.php
|
||||
|
||||
- name: Build PocketMine-MP.phar
|
||||
run: php -dphar.readonly=0 build/server-phar.php --git ${{ github.sha }}
|
||||
run: php -dphar.readonly=0 build/server-phar.php --git ${{ github.sha }} --build ${{ steps.build-number.outputs.BUILD_NUMBER }}
|
||||
|
||||
- name: Get PocketMine-MP release version
|
||||
id: get-pm-version
|
||||
@ -56,7 +57,7 @@ jobs:
|
||||
echo ::set-output name=PM_VERSION_MD::$(php -r 'require "vendor/autoload.php"; echo str_replace(".", "", \pocketmine\VersionInfo::BASE_VERSION);')
|
||||
|
||||
- name: Generate build info
|
||||
run: php build/generate-build-info-json.php ${{ github.sha }} ${{ steps.get-pm-version.outputs.PM_VERSION }} ${{ github.repository }} > build_info.json
|
||||
run: php build/generate-build-info-json.php ${{ github.sha }} ${{ steps.get-pm-version.outputs.PM_VERSION }} ${{ github.repository }} ${{ steps.build-number.outputs.BUILD_NUMBER }} > build_info.json
|
||||
|
||||
- name: Upload release artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
|
136
.github/workflows/main.yml
vendored
136
.github/workflows/main.yml
vendored
@ -13,20 +13,14 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.0.9]
|
||||
php: [8.0.11]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2 #needed for build.sh
|
||||
- name: Check for PHP build cache
|
||||
id: php-build-cache
|
||||
uses: actions/cache@v2
|
||||
- name: Build and prepare PHP cache
|
||||
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
||||
with:
|
||||
path: "./bin"
|
||||
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
|
||||
|
||||
- name: Compile PHP
|
||||
if: steps.php-build-cache.outputs.cache-hit != 'true'
|
||||
run: ./tests/gh-actions/build.sh "${{ matrix.php }}"
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
|
||||
phpstan:
|
||||
name: PHPStan analysis
|
||||
@ -37,28 +31,16 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.0.9]
|
||||
php: [8.0.11]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Restore PHP build cache
|
||||
id: php-build-cache
|
||||
uses: actions/cache@v2
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
||||
with:
|
||||
path: "./bin"
|
||||
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
|
||||
|
||||
- name: Kill build on PHP build cache miss (should never happen)
|
||||
if: steps.php-build-cache.outputs.cache-hit != 'true'
|
||||
run: exit 1
|
||||
|
||||
- name: Install cached PHP's dependencies
|
||||
if: steps.php-build-cache.outputs.cache-hit == 'true'
|
||||
run: ./tests/gh-actions/install-dependencies.sh
|
||||
|
||||
- name: Prefix PHP to PATH
|
||||
run: echo "$(pwd)/bin/php7/bin" >> $GITHUB_PATH
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
|
||||
- name: Install Composer
|
||||
run: curl -sS https://getcomposer.org/installer | php
|
||||
@ -87,30 +69,16 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.0.9]
|
||||
php: [8.0.11]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Restore PHP build cache
|
||||
id: php-build-cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "./bin"
|
||||
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
|
||||
|
||||
- name: Kill build on PHP build cache miss (should never happen)
|
||||
if: steps.php-build-cache.outputs.cache-hit != 'true'
|
||||
run: exit 1
|
||||
|
||||
- name: Install cached PHP's dependencies
|
||||
if: steps.php-build-cache.outputs.cache-hit == 'true'
|
||||
run: ./tests/gh-actions/install-dependencies.sh
|
||||
|
||||
- name: Prefix PHP to PATH
|
||||
run: echo "$(pwd)/bin/php7/bin" >> $GITHUB_PATH
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
|
||||
- name: Install Composer
|
||||
run: curl -sS https://getcomposer.org/installer | php
|
||||
@ -139,30 +107,18 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.0.9]
|
||||
php: [8.0.11]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Restore PHP build cache
|
||||
id: php-build-cache
|
||||
uses: actions/cache@v2
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
||||
with:
|
||||
path: "./bin"
|
||||
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
|
||||
|
||||
- name: Kill build on PHP build cache miss (should never happen)
|
||||
if: steps.php-build-cache.outputs.cache-hit != 'true'
|
||||
run: exit 1
|
||||
|
||||
- name: Install cached PHP's dependencies
|
||||
if: steps.php-build-cache.outputs.cache-hit == 'true'
|
||||
run: ./tests/gh-actions/install-dependencies.sh
|
||||
|
||||
- name: Prefix PHP to PATH
|
||||
run: echo "$(pwd)/bin/php7/bin" >> $GITHUB_PATH
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
|
||||
- name: Install Composer
|
||||
run: curl -sS https://getcomposer.org/installer | php
|
||||
@ -183,6 +139,52 @@ jobs:
|
||||
- name: Run integration tests
|
||||
run: ./tests/travis.sh -t4
|
||||
|
||||
codegen:
|
||||
name: Generated Code consistency checks
|
||||
needs: build-php
|
||||
runs-on: ${{ matrix.image }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.0.11]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
|
||||
- name: Install Composer
|
||||
run: curl -sS https://getcomposer.org/installer | php
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cache/composer/files
|
||||
~/.cache/composer/vcs
|
||||
key: "composer-v2-cache-${{ matrix.php }}-${{ hashFiles('./composer.lock') }}"
|
||||
restore-keys: |
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: php composer.phar install --no-dev --prefer-dist --no-interaction
|
||||
|
||||
- name: Regenerate registry annotations
|
||||
run: php build/generate-registry-annotations.php src
|
||||
|
||||
- name: Regenerate KnownTranslation APIs
|
||||
run: php build/generate-known-translation-apis.php
|
||||
|
||||
- name: Verify code is unchanged
|
||||
run: |
|
||||
git diff
|
||||
git diff --quiet
|
||||
|
||||
codestyle:
|
||||
name: Code Style checks
|
||||
runs-on: ubuntu-20.04
|
||||
@ -193,10 +195,10 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup PHP and tools
|
||||
uses: shivammathur/setup-php@2.9.0
|
||||
uses: shivammathur/setup-php@2.15.0
|
||||
with:
|
||||
php-version: 8.0
|
||||
tools: php-cs-fixer
|
||||
tools: php-cs-fixer:3.2
|
||||
|
||||
- name: Run PHP-CS-Fixer
|
||||
run: php-cs-fixer fix --dry-run --diff
|
||||
|
2
.github/workflows/update-php-versions.php
vendored
2
.github/workflows/update-php-versions.php
vendored
@ -22,8 +22,6 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
const VERSIONS = [
|
||||
"7.3",
|
||||
"7.4",
|
||||
"8.0"
|
||||
];
|
||||
|
||||
|
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -1,12 +1,6 @@
|
||||
[submodule "resources/locale"]
|
||||
path = resources/locale
|
||||
url = https://github.com/pmmp/Language.git
|
||||
[submodule "tests/plugins/DevTools"]
|
||||
path = tests/plugins/DevTools
|
||||
url = https://github.com/pmmp/DevTools.git
|
||||
[submodule "build/php"]
|
||||
path = build/php
|
||||
url = https://github.com/pmmp/php-build-scripts.git
|
||||
[submodule "resources/vanilla"]
|
||||
path = resources/vanilla
|
||||
url = https://github.com/pmmp/BedrockData.git
|
||||
|
@ -61,6 +61,11 @@ return (new PhpCsFixer\Config)
|
||||
],
|
||||
'sort_algorithm' => 'alpha'
|
||||
],
|
||||
'phpdoc_line_span' => [
|
||||
'property' => 'single',
|
||||
'method' => null,
|
||||
'const' => null
|
||||
],
|
||||
'phpdoc_trim' => true,
|
||||
'phpdoc_trim_consecutive_blank_line_separation' => true,
|
||||
'single_import_per_statement' => true,
|
||||
|
11
BUILDING.md
11
BUILDING.md
@ -2,25 +2,24 @@
|
||||
## Pre-requisites
|
||||
- A bash shell (git bash is sufficient for Windows)
|
||||
- [`git`](https://git-scm.com) available in your shell
|
||||
- PHP 7.4 or newer available in your shell
|
||||
- PHP 8.0 or newer available in your shell
|
||||
- [`composer`](https://getcomposer.org) available in your shell
|
||||
|
||||
## Custom PHP binaries
|
||||
Because PocketMine-MP requires several non-standard PHP extensions and configuration, PMMP provides scripts to build custom binaries for running PocketMine-MP, as well as prebuilt binaries.
|
||||
|
||||
- [Prebuilt binaries](https://jenkins.pmmp.io/job/PHP-7.4-Aggregate)
|
||||
- [Prebuilt binaries](https://jenkins.pmmp.io/job/PHP-8.0-Aggregate)
|
||||
- [Compile scripts](https://github.com/pmmp/php-build-scripts) are provided as a submodule in the path `build/php`
|
||||
|
||||
If you use a custom binary, you'll need to replace `composer` usages in this guide with `path/to/your/php path/to/your/composer.phar`.
|
||||
|
||||
## Setting up environment
|
||||
1. `git clone --recursive https://github.com/pmmp/PocketMine-MP.git`
|
||||
1. `git clone https://github.com/pmmp/PocketMine-MP.git`
|
||||
2. `composer install`
|
||||
|
||||
## Checking out a different branch to build
|
||||
1. `git checkout <branch to checkout>`
|
||||
2. `git submodule update --init`
|
||||
3. Re-run `composer install` to synchronize dependencies.
|
||||
2. Re-run `composer install` to synchronize dependencies.
|
||||
|
||||
## Optimizing for release builds
|
||||
1. Add the flags `--no-dev --classmap-authoritative` to your `composer install` command. This will reduce build size and improve autoloading speed.
|
||||
@ -34,7 +33,7 @@ There is a bug in PHP that might cause an error which looks like this:
|
||||
```
|
||||
Fatal error: Uncaught BadMethodCallException: unable to create temporary file in PocketMine-MP/build/server-phar.php:119
|
||||
```
|
||||
You can work around it by setting `ulimit -n` to some bigger number, e.g. `8192`, or by updating your PHP version to at least 7.4.16 or 8.0.3.
|
||||
You can work around it by setting `ulimit -n` to some bigger number, e.g. `8192`, or by updating your PHP version to at least 8.0.3.
|
||||
|
||||
## Running PocketMine-MP from source code
|
||||
Run `src/PocketMine.php` using your preferred PHP binary.
|
||||
|
@ -5,9 +5,12 @@
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/pmmp/PocketMine-MP/workflows/CI/badge.svg" alt="CI" />
|
||||
<a href="https://github.com/pmmp/PocketMine-MP/releases"><img src="https://img.shields.io/github/v/tag/pmmp/PocketMine-MP?label=release&logo=github" alt="GitHub tag (latest semver)" /></a>
|
||||
<img alt="GitHub release (latest SemVer)" src="https://img.shields.io/github/v/release/pmmp/PocketMine-MP?label=release&sort=semver">
|
||||
<a href="https://hub.docker.com/r/pmmp/pocketmine-mp"><img src="https://img.shields.io/docker/v/pmmp/pocketmine-mp?logo=docker&label=image" alt="Docker image version (latest semver)" /></a>
|
||||
<a href="https://discord.gg/bmSAZBG"><img src="https://img.shields.io/discord/373199722573201408?label=discord&color=7289DA&logo=discord" alt="Discord" /></a>
|
||||
<br>
|
||||
<img alt="GitHub all releases" src="https://img.shields.io/github/downloads/pmmp/PocketMine-MP/total?label=downloads%40total">
|
||||
<img alt="GitHub release (latest by SemVer)" src="https://img.shields.io/github/downloads/pmmp/PocketMine-MP/latest/total?sort=semver">
|
||||
</p>
|
||||
|
||||
## Getting started
|
||||
|
@ -23,15 +23,15 @@ declare(strict_types=1);
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
if(count($argv) !== 4){
|
||||
fwrite(STDERR, "required args: <git hash> <tag name> <github repo (owner/name)>");
|
||||
if(count($argv) !== 5){
|
||||
fwrite(STDERR, "required args: <git hash> <tag name> <github repo (owner/name)> <build number>");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
"php_version" => sprintf("%d.%d", PHP_MAJOR_VERSION, PHP_MINOR_VERSION),
|
||||
"base_version" => \pocketmine\VersionInfo::BASE_VERSION,
|
||||
"build" => \pocketmine\VersionInfo::BUILD_NUMBER,
|
||||
"build" => (int) $argv[4],
|
||||
"is_dev" => \pocketmine\VersionInfo::IS_DEVELOPMENT_BUILD,
|
||||
"channel" => \pocketmine\VersionInfo::BUILD_CHANNEL,
|
||||
"git_commit" => $argv[1],
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\build\generate_known_translation_apis;
|
||||
|
||||
use pocketmine\lang\Translatable;
|
||||
use pocketmine\utils\Utils;
|
||||
use Webmozart\PathUtil\Path;
|
||||
use function array_map;
|
||||
use function count;
|
||||
@ -40,6 +41,7 @@ use function preg_match_all;
|
||||
use function str_replace;
|
||||
use function strtoupper;
|
||||
use const INI_SCANNER_RAW;
|
||||
use const SORT_NUMERIC;
|
||||
use const SORT_STRING;
|
||||
use const STDERR;
|
||||
|
||||
@ -94,13 +96,15 @@ function generate_known_translation_keys(array $languageDefinitions) : void{
|
||||
/**
|
||||
* This class contains constants for all the translations known to PocketMine-MP as per the used version of pmmp/Language.
|
||||
* This class is generated automatically, do NOT modify it by hand.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class KnownTranslationKeys{
|
||||
|
||||
HEADER;
|
||||
|
||||
ksort($languageDefinitions, SORT_STRING);
|
||||
foreach($languageDefinitions as $k => $_){
|
||||
foreach(Utils::stringifyKeys($languageDefinitions) as $k => $_){
|
||||
echo "\tpublic const ";
|
||||
echo constantify($k);
|
||||
echo " = \"" . $k . "\";\n";
|
||||
@ -126,6 +130,8 @@ function generate_known_translation_factory(array $languageDefinitions) : void{
|
||||
* This class contains factory methods for all the translations known to PocketMine-MP as per the used version of
|
||||
* pmmp/Language.
|
||||
* This class is generated automatically, do NOT modify it by hand.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class KnownTranslationFactory{
|
||||
|
||||
@ -135,17 +141,22 @@ HEADER;
|
||||
$parameterRegex = '/{%(.+?)}/';
|
||||
|
||||
$translationContainerClass = (new \ReflectionClass(Translatable::class))->getShortName();
|
||||
foreach($languageDefinitions as $key => $value){
|
||||
foreach(Utils::stringifyKeys($languageDefinitions) as $key => $value){
|
||||
$parameters = [];
|
||||
$allParametersPositional = true;
|
||||
if(preg_match_all($parameterRegex, $value, $matches) > 0){
|
||||
foreach($matches[1] as $parameterName){
|
||||
if(is_numeric($parameterName)){
|
||||
$parameters[$parameterName] = "param$parameterName";
|
||||
}else{
|
||||
$parameters[$parameterName] = $parameterName;
|
||||
$allParametersPositional = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if($allParametersPositional){
|
||||
ksort($parameters, SORT_NUMERIC);
|
||||
}
|
||||
echo "\tpublic static function " .
|
||||
functionify($key) .
|
||||
"(" . implode(", ", array_map(fn(string $paramName) => "$translationContainerClass|string \$$paramName", $parameters)) . ") : $translationContainerClass{\n";
|
||||
@ -172,7 +183,7 @@ HEADER;
|
||||
echo "Done generating KnownTranslationFactory.\n";
|
||||
}
|
||||
|
||||
$lang = parse_ini_file(Path::join(\pocketmine\RESOURCE_PATH, "locale", "eng.ini"), false, INI_SCANNER_RAW);
|
||||
$lang = parse_ini_file(Path::join(\pocketmine\LOCALE_DATA_PATH, "eng.ini"), false, INI_SCANNER_RAW);
|
||||
if($lang === false){
|
||||
fwrite(STDERR, "Missing language files!\n");
|
||||
exit(1);
|
||||
|
@ -91,7 +91,7 @@ foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($argv[1],
|
||||
throw new \RuntimeException("Failed to get contents of $file");
|
||||
}
|
||||
|
||||
if(preg_match("/^namespace (.+);$/m", $contents, $matches) !== 1 || preg_match('/^((final|abstract)\s+)?class /m', $contents) !== 1){
|
||||
if(preg_match("/(*ANYCRLF)^namespace (.+);$/m", $contents, $matches) !== 1 || preg_match('/(*ANYCRLF)^((final|abstract)\s+)?class /m', $contents) !== 1){
|
||||
continue;
|
||||
}
|
||||
$shortClassName = basename($file, ".php");
|
||||
@ -101,7 +101,7 @@ foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($argv[1],
|
||||
}
|
||||
$reflect = new \ReflectionClass($className);
|
||||
$docComment = $reflect->getDocComment();
|
||||
if($docComment === false || preg_match("/^\s*\*\s*@generate-registry-docblock$/m", $docComment) !== 1){
|
||||
if($docComment === false || preg_match("/(*ANYCRLF)^\s*\*\s*@generate-registry-docblock$/m", $docComment) !== 1){
|
||||
continue;
|
||||
}
|
||||
echo "Found registry in $file\n";
|
||||
|
@ -23,20 +23,29 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\build\make_release;
|
||||
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\VersionString;
|
||||
use pocketmine\VersionInfo;
|
||||
use function count;
|
||||
use function array_keys;
|
||||
use function array_map;
|
||||
use function dirname;
|
||||
use function fgets;
|
||||
use function file_get_contents;
|
||||
use function file_put_contents;
|
||||
use function fwrite;
|
||||
use function getopt;
|
||||
use function is_string;
|
||||
use function max;
|
||||
use function preg_replace;
|
||||
use function sleep;
|
||||
use function sprintf;
|
||||
use function str_pad;
|
||||
use function strlen;
|
||||
use function system;
|
||||
use const STDERR;
|
||||
use const STDIN;
|
||||
use const STDOUT;
|
||||
use const STR_PAD_LEFT;
|
||||
|
||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
@ -60,22 +69,38 @@ function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev
|
||||
file_put_contents($versionInfoPath, $versionInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $argv
|
||||
* @phpstan-param list<string> $argv
|
||||
*/
|
||||
function main(array $argv) : void{
|
||||
if(count($argv) < 2){
|
||||
fwrite(STDERR, "Arguments: <channel> [release version] [next version]\n");
|
||||
exit(1);
|
||||
const ACCEPTED_OPTS = [
|
||||
"current" => "Version to insert and tag",
|
||||
"next" => "Version to put in the file after tagging",
|
||||
"channel" => "Release channel to post this build into"
|
||||
];
|
||||
|
||||
function main() : void{
|
||||
$filteredOpts = [];
|
||||
foreach(Utils::stringifyKeys(getopt("", ["current:", "next:", "channel:", "help"])) as $optName => $optValue){
|
||||
if($optName === "help"){
|
||||
fwrite(STDOUT, "Options:\n");
|
||||
|
||||
$maxLength = max(array_map(fn(string $str) => strlen($str), array_keys(ACCEPTED_OPTS)));
|
||||
foreach(ACCEPTED_OPTS as $acceptedName => $description){
|
||||
fwrite(STDOUT, str_pad("--$acceptedName", $maxLength + 4, " ", STR_PAD_LEFT) . ": $description\n");
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
if(!is_string($optValue)){
|
||||
fwrite(STDERR, "--$optName expects exactly 1 value\n");
|
||||
exit(1);
|
||||
}
|
||||
$filteredOpts[$optName] = $optValue;
|
||||
}
|
||||
if(isset($argv[2])){
|
||||
$currentVer = new VersionString($argv[2]);
|
||||
|
||||
if(isset($filteredOpts["current"])){
|
||||
$currentVer = new VersionString($filteredOpts["current"]);
|
||||
}else{
|
||||
$currentVer = VersionInfo::VERSION();
|
||||
$currentVer = new VersionString(VersionInfo::BASE_VERSION);
|
||||
}
|
||||
if(isset($argv[3])){
|
||||
$nextVer = new VersionString($argv[3]);
|
||||
if(isset($filteredOpts["next"])){
|
||||
$nextVer = new VersionString($filteredOpts["next"]);
|
||||
}else{
|
||||
$nextVer = new VersionString(sprintf(
|
||||
"%u.%u.%u",
|
||||
@ -84,8 +109,10 @@ function main(array $argv) : void{
|
||||
$currentVer->getPatch() + 1
|
||||
));
|
||||
}
|
||||
$channel = $filteredOpts["channel"] ?? VersionInfo::BUILD_CHANNEL;
|
||||
|
||||
echo "About to tag version $currentVer. Next version will be $nextVer.\n";
|
||||
echo "$currentVer will be published on release channel \"$channel\".\n";
|
||||
echo "please add appropriate notes to the changelog and press enter...";
|
||||
fgets(STDIN);
|
||||
system('git add "' . dirname(__DIR__) . '/changelogs"');
|
||||
@ -95,10 +122,10 @@ function main(array $argv) : void{
|
||||
exit(1);
|
||||
}
|
||||
$versionInfoPath = dirname(__DIR__) . '/src/VersionInfo.php';
|
||||
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false, $argv[1]);
|
||||
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false, $channel);
|
||||
system('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"');
|
||||
system('git tag ' . $currentVer->getBaseVersion());
|
||||
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true, "");
|
||||
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true, $channel);
|
||||
system('git add "' . $versionInfoPath . '"');
|
||||
system('git commit -m "' . $nextVer->getBaseVersion() . ' is next" --include "' . $versionInfoPath . '"');
|
||||
echo "pushing changes in 5 seconds\n";
|
||||
@ -106,4 +133,4 @@ function main(array $argv) : void{
|
||||
system('git push origin HEAD ' . $currentVer->getBaseVersion());
|
||||
}
|
||||
|
||||
main($argv);
|
||||
main();
|
||||
|
Submodule build/php updated: ad9cd1fdb4...bd329dba08
@ -134,13 +134,18 @@ function main() : void{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$opts = getopt("", ["out:", "git:"]);
|
||||
$opts = getopt("", ["out:", "git:", "build:"]);
|
||||
if(isset($opts["git"])){
|
||||
$gitHash = $opts["git"];
|
||||
}else{
|
||||
$gitHash = Git::getRepositoryStatePretty(dirname(__DIR__));
|
||||
echo "Git hash detected as $gitHash" . PHP_EOL;
|
||||
}
|
||||
if(isset($opts["build"])){
|
||||
$build = (int) $opts["build"];
|
||||
}else{
|
||||
$build = 0;
|
||||
}
|
||||
foreach(buildPhar(
|
||||
$opts["out"] ?? getcwd() . DIRECTORY_SEPARATOR . "PocketMine-MP.phar",
|
||||
dirname(__DIR__) . DIRECTORY_SEPARATOR,
|
||||
@ -150,7 +155,8 @@ function main() : void{
|
||||
'vendor'
|
||||
],
|
||||
[
|
||||
'git' => $gitHash
|
||||
'git' => $gitHash,
|
||||
'build' => $build
|
||||
],
|
||||
<<<'STUB'
|
||||
<?php
|
||||
|
14
changelogs/3.23.md
Normal file
14
changelogs/3.23.md
Normal file
@ -0,0 +1,14 @@
|
||||
**For Minecraft: Bedrock Edition 1.17.30**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 3.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 3.23.0
|
||||
- Added support for Minecraft: Bedrock Edition 1.17.30.
|
||||
- Removed compatibility with earlier versions.
|
||||
|
||||
# 3.23.1
|
||||
- Fixed broken build of 3.23.0.
|
12
changelogs/3.24.md
Normal file
12
changelogs/3.24.md
Normal file
@ -0,0 +1,12 @@
|
||||
**For Minecraft: Bedrock Edition 1.17.30**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 3.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 3.24.0
|
||||
- PHP 8.0 is now required as a minimum.
|
||||
- Fixed stats reporting checking the wrong `pocketmine.yml` property.
|
||||
- Fixed `Projectile->move()` not respecting the given `dx`/`dy`/`dz` and using its own motion instead.
|
38
changelogs/3.25.md
Normal file
38
changelogs/3.25.md
Normal file
@ -0,0 +1,38 @@
|
||||
**For Minecraft: Bedrock Edition 1.17.40**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 3.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 3.25.0
|
||||
- Added support for Minecraft: Bedrock Edition 1.17.40.
|
||||
- Removed compatibility with earlier versions.
|
||||
|
||||
# 3.25.1
|
||||
- Fixed autosave bug that caused unmodified chunks to be saved at least once (during the first autosave after they were loaded).
|
||||
- `Entity->spawnTo()` now has an additional sanity check for matching worlds (might expose a few new errors in plugins).
|
||||
- Fixed a missing field in `CraftRecipeAuto` item stack request type.
|
||||
|
||||
# 3.25.2
|
||||
- Now analysed using level 9 on PHPStan 1.0.0.
|
||||
- `ext-pthreads` v4.0.0 or newer is now required.
|
||||
- Fixed crash in `Player->showPlayer()` when the target is not in the same world.
|
||||
- `Human->setLifetimeTotalXp()` now limits the maximum value to 2^31.
|
||||
- Fixed players, who died in hardcore mode and were unbanned, getting re-banned on next server join.
|
||||
|
||||
# 3.25.3
|
||||
- Fixed crash when players try to pickup XP while already having max XP.
|
||||
- Added a sanity check to `Human->setCurrentTotalXp()` to try and catch an elusive bug that's been appearing in the wild - please get in touch if you know how to reproduce it!
|
||||
|
||||
# 3.25.4
|
||||
- Fixed a long-standing issue with `Player->removeWindow()` breaking inventory UIs on the client.
|
||||
|
||||
# 3.25.5
|
||||
- Protocol: Fixed incorrect encoding in `StructureSettings`
|
||||
- Fixed reading tags from non-docblock comments in script plugins.
|
||||
- Build number is now defined in phar metadata instead of being patched into the source code directly.
|
||||
|
||||
# 3.25.6
|
||||
- Fixed borked build number in release build of 3.25.5.
|
23
changelogs/3.26.md
Normal file
23
changelogs/3.26.md
Normal file
@ -0,0 +1,23 @@
|
||||
**For Minecraft: Bedrock Edition 1.18.0**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 3.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 3.26.0
|
||||
- Added support for Minecraft: Bedrock Edition 1.18.0.
|
||||
- Removed compatibility with earlier versions.
|
||||
|
||||
# 3.26.1
|
||||
- Fixed a bug in chunk sending that caused double chests to not be paired, signs to be blank, and various other issues.
|
||||
|
||||
# 3.26.2
|
||||
- Improved error messages shown by `start.cmd`, `start.sh` and `start.ps1` when the PHP binary was not found.
|
||||
- The value of PHPRC is now shown when erroring out due to unsatisfied PHP requirements.
|
||||
- Removed restriction on the range of valid channels for `auto-updater.channel` in `pocketmine.yml`.
|
||||
|
||||
# 3.26.3
|
||||
- `PlayerExperienceChangeEvent->setNewProgress()` now performs range checks. This fixes the root of a very old and confusing crash bug which took several years to identify the cause of.
|
||||
- Note that the defective plugin(s) which caused this problem will still cause a server crash, but the plugin responsible will now get blamed correctly.
|
1767
changelogs/4.0-beta.md
Normal file
1767
changelogs/4.0-beta.md
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@
|
||||
"require": {
|
||||
"php": "^8.0",
|
||||
"php-64bit": "*",
|
||||
"ext-chunkutils2": "^0.3.0",
|
||||
"ext-chunkutils2": "^0.3.1",
|
||||
"ext-crypto": "^0.3.1",
|
||||
"ext-ctype": "*",
|
||||
"ext-curl": "*",
|
||||
@ -22,7 +22,7 @@
|
||||
"ext-openssl": "*",
|
||||
"ext-pcre": "*",
|
||||
"ext-phar": "*",
|
||||
"ext-pthreads": "~3.2.0",
|
||||
"ext-pthreads": "^4.0",
|
||||
"ext-reflection": "*",
|
||||
"ext-simplexml": "*",
|
||||
"ext-sockets": "*",
|
||||
@ -34,28 +34,28 @@
|
||||
"adhocore/json-comment": "^1.1",
|
||||
"fgrosse/phpasn1": "^2.3",
|
||||
"netresearch/jsonmapper": "^4.0",
|
||||
"pocketmine/bedrock-protocol": "1.0.0+bedrock1.17.10",
|
||||
"pocketmine/bedrock-data": "^1.5.0+bedrock-1.18.0",
|
||||
"pocketmine/bedrock-protocol": "^7.0.0+bedrock-1.18.0",
|
||||
"pocketmine/binaryutils": "^0.2.1",
|
||||
"pocketmine/callback-validator": "^1.0.2",
|
||||
"pocketmine/classloader": "dev-master",
|
||||
"pocketmine/classloader": "^0.2.0",
|
||||
"pocketmine/color": "^0.2.0",
|
||||
"pocketmine/errorhandler": "^0.3.0",
|
||||
"pocketmine/log": "^0.3.0",
|
||||
"pocketmine/log-pthreads": "^0.2.0",
|
||||
"pocketmine/math": "^0.3.0",
|
||||
"pocketmine/locale-data": "^2.0.16",
|
||||
"pocketmine/log": "^0.4.0",
|
||||
"pocketmine/log-pthreads": "^0.4.0",
|
||||
"pocketmine/math": "^0.4.0",
|
||||
"pocketmine/nbt": "^0.3.0",
|
||||
"pocketmine/raklib": "^0.13.1",
|
||||
"pocketmine/raklib": "^0.14.2",
|
||||
"pocketmine/raklib-ipc": "^0.1.0",
|
||||
"pocketmine/snooze": "^0.3.0",
|
||||
"pocketmine/spl": "dev-master",
|
||||
"ramsey/uuid": "^4.1",
|
||||
"respect/validation": "^2.0",
|
||||
"webmozart/path-util": "^2.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "0.12.98",
|
||||
"phpstan/phpstan-phpunit": "^0.12.6",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.2",
|
||||
"phpstan/phpstan": "1.2.0",
|
||||
"phpstan/phpstan-phpunit": "^1.0.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.0.0",
|
||||
"phpunit/phpunit": "^9.2"
|
||||
},
|
||||
"autoload": {
|
||||
@ -79,7 +79,7 @@
|
||||
"sort-packages": true
|
||||
},
|
||||
"scripts": {
|
||||
"make-devtools": "@php -dphar.readonly=0 tests/plugins/DevTools/src/DevTools/ConsoleScript.php --make tests/plugins/DevTools --out plugins/DevTools.phar",
|
||||
"make-devtools": "@php -dphar.readonly=0 tests/plugins/DevTools/src/ConsoleScript.php --make tests/plugins/DevTools --out plugins/DevTools.phar",
|
||||
"make-server": [
|
||||
"@composer install --no-dev --classmap-authoritative --ignore-platform-reqs",
|
||||
"@php -dphar.readonly=0 build/server-phar.php"
|
||||
|
748
composer.lock
generated
748
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,9 @@
|
||||
includes:
|
||||
- tests/phpstan/configs/actual-problems.neon
|
||||
- tests/phpstan/configs/check-explicit-mixed-baseline.neon
|
||||
- tests/phpstan/configs/gc-hacks.neon
|
||||
- tests/phpstan/configs/impossible-generics.neon
|
||||
- tests/phpstan/configs/l7-baseline.neon
|
||||
- tests/phpstan/configs/l8-baseline.neon
|
||||
- tests/phpstan/configs/php-bugs.neon
|
||||
- tests/phpstan/configs/phpstan-bugs.neon
|
||||
- tests/phpstan/configs/pthreads-bugs.neon
|
||||
- tests/phpstan/configs/runtime-type-checks.neon
|
||||
- tests/phpstan/configs/spl-fixed-array-sucks.neon
|
||||
- vendor/phpstan/phpstan-phpunit/extension.neon
|
||||
@ -16,11 +12,11 @@ includes:
|
||||
|
||||
rules:
|
||||
- pocketmine\phpstan\rules\DisallowEnumComparisonRule
|
||||
- pocketmine\phpstan\rules\UnsafeForeachArrayOfStringRule
|
||||
# - pocketmine\phpstan\rules\ThreadedSupportedTypesRule
|
||||
|
||||
parameters:
|
||||
level: 8
|
||||
checkExplicitMixed: true
|
||||
level: 9
|
||||
checkMissingCallableSignature: true
|
||||
treatPhpDocTypesAsCertain: false
|
||||
bootstrapFiles:
|
||||
@ -38,6 +34,9 @@ parameters:
|
||||
- tests/phpunit
|
||||
- tests/plugins/TesterPlugin
|
||||
- tools
|
||||
excludePaths:
|
||||
analyseAndScan:
|
||||
- build/php
|
||||
dynamicConstantNames:
|
||||
- pocketmine\VersionInfo::IS_DEVELOPMENT_BUILD
|
||||
- pocketmine\DEBUG
|
||||
@ -54,5 +53,5 @@ parameters:
|
||||
#variadics don't work for this - mixed probably shouldn't work either, but for now it does
|
||||
#what we actually need is something that accepts an infinite number of parameters, but in the absence of that,
|
||||
#we'll just fill it with 10 - it's very unlikely to encounter a callable with 10 parameters anyway.
|
||||
anyCallable: 'callable(mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed) : mixed'
|
||||
anyClosure: '\Closure(mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed) : mixed'
|
||||
anyCallable: 'callable(never, never, never, never, never, never, never, never, never, never) : mixed'
|
||||
anyClosure: '\Closure(never, never, never, never, never, never, never, never, never, never) : mixed'
|
||||
|
@ -1,4 +1,691 @@
|
||||
{
|
||||
"-2": -2,
|
||||
"-3": -3,
|
||||
"-4": -4,
|
||||
"-5": -5,
|
||||
"-6": -6,
|
||||
"-7": -7,
|
||||
"-8": -8,
|
||||
"-9": -9,
|
||||
"-10": -10,
|
||||
"-11": -11,
|
||||
"-12": -12,
|
||||
"-13": -13,
|
||||
"-14": -14,
|
||||
"-15": -15,
|
||||
"-16": -16,
|
||||
"-17": -17,
|
||||
"-18": -18,
|
||||
"-19": -19,
|
||||
"-20": -20,
|
||||
"-21": -21,
|
||||
"-22": -22,
|
||||
"-23": -23,
|
||||
"-24": -24,
|
||||
"-25": -25,
|
||||
"-26": -26,
|
||||
"-27": -27,
|
||||
"-28": -28,
|
||||
"-29": -29,
|
||||
"-30": -30,
|
||||
"-31": -31,
|
||||
"-32": -32,
|
||||
"-33": -33,
|
||||
"-34": -34,
|
||||
"-35": -35,
|
||||
"-36": -36,
|
||||
"-37": -37,
|
||||
"-38": -38,
|
||||
"-39": -39,
|
||||
"-40": -40,
|
||||
"-41": -41,
|
||||
"-42": -42,
|
||||
"-43": -43,
|
||||
"-44": -44,
|
||||
"-45": -45,
|
||||
"-46": -46,
|
||||
"-47": -47,
|
||||
"-48": -48,
|
||||
"-49": -49,
|
||||
"-50": -50,
|
||||
"-51": -51,
|
||||
"-52": -52,
|
||||
"-53": -53,
|
||||
"-54": -54,
|
||||
"-55": -55,
|
||||
"-56": -56,
|
||||
"-57": -57,
|
||||
"-58": -58,
|
||||
"-59": -59,
|
||||
"-60": -60,
|
||||
"-61": -61,
|
||||
"-62": -62,
|
||||
"-63": -63,
|
||||
"-64": -64,
|
||||
"-65": -65,
|
||||
"-66": -66,
|
||||
"-67": -67,
|
||||
"-68": -68,
|
||||
"-69": -69,
|
||||
"-70": -70,
|
||||
"-71": -71,
|
||||
"-72": -72,
|
||||
"-73": -73,
|
||||
"-74": -74,
|
||||
"-75": -75,
|
||||
"-76": -76,
|
||||
"-77": -77,
|
||||
"-78": -78,
|
||||
"-79": -79,
|
||||
"-80": -80,
|
||||
"-81": -81,
|
||||
"-82": -82,
|
||||
"-83": -83,
|
||||
"-84": -84,
|
||||
"-85": -85,
|
||||
"-86": -86,
|
||||
"-87": -87,
|
||||
"-88": -88,
|
||||
"-89": -89,
|
||||
"-90": -90,
|
||||
"-91": -91,
|
||||
"-92": -92,
|
||||
"-93": -93,
|
||||
"-94": -94,
|
||||
"-95": -95,
|
||||
"-96": -96,
|
||||
"-97": -97,
|
||||
"-98": -98,
|
||||
"-99": -99,
|
||||
"-100": -100,
|
||||
"-101": -101,
|
||||
"-102": -102,
|
||||
"-103": -103,
|
||||
"-104": -104,
|
||||
"-105": -105,
|
||||
"-106": -106,
|
||||
"-107": -107,
|
||||
"-108": -108,
|
||||
"-109": -109,
|
||||
"-110": -110,
|
||||
"-111": -111,
|
||||
"-112": -112,
|
||||
"-113": -113,
|
||||
"-114": -114,
|
||||
"-115": -115,
|
||||
"-116": -116,
|
||||
"-117": -117,
|
||||
"-118": -118,
|
||||
"-119": -119,
|
||||
"-120": -120,
|
||||
"-121": -121,
|
||||
"-122": -122,
|
||||
"-123": -123,
|
||||
"-124": -124,
|
||||
"-125": -125,
|
||||
"-126": -126,
|
||||
"-127": -127,
|
||||
"-128": -128,
|
||||
"-129": -129,
|
||||
"-130": -130,
|
||||
"-131": -131,
|
||||
"-132": -132,
|
||||
"-133": -133,
|
||||
"-134": -134,
|
||||
"-135": -135,
|
||||
"-136": -136,
|
||||
"-137": -137,
|
||||
"-138": -138,
|
||||
"-139": -139,
|
||||
"-140": -140,
|
||||
"-141": -141,
|
||||
"-142": -142,
|
||||
"-143": -143,
|
||||
"-144": -144,
|
||||
"-145": -145,
|
||||
"-146": -146,
|
||||
"-147": -147,
|
||||
"-148": -148,
|
||||
"-149": -149,
|
||||
"-150": -150,
|
||||
"-151": -151,
|
||||
"-152": -152,
|
||||
"-153": -153,
|
||||
"-154": -154,
|
||||
"-155": -155,
|
||||
"-156": -156,
|
||||
"-157": -157,
|
||||
"-159": -159,
|
||||
"-160": -160,
|
||||
"-161": -161,
|
||||
"-162": -162,
|
||||
"-163": -163,
|
||||
"-164": -164,
|
||||
"-165": -165,
|
||||
"-166": -166,
|
||||
"-167": -167,
|
||||
"-168": -168,
|
||||
"-169": -169,
|
||||
"-170": -170,
|
||||
"-171": -171,
|
||||
"-172": -172,
|
||||
"-173": -173,
|
||||
"-174": -174,
|
||||
"-175": -175,
|
||||
"-176": -176,
|
||||
"-177": -177,
|
||||
"-178": -178,
|
||||
"-179": -179,
|
||||
"-180": -180,
|
||||
"-181": -181,
|
||||
"-182": -182,
|
||||
"-183": -183,
|
||||
"-184": -184,
|
||||
"-185": -185,
|
||||
"-186": -186,
|
||||
"-187": -187,
|
||||
"-188": -188,
|
||||
"-189": -189,
|
||||
"-190": -190,
|
||||
"-191": -191,
|
||||
"-192": -192,
|
||||
"-193": -193,
|
||||
"-194": -194,
|
||||
"-195": -195,
|
||||
"-196": -196,
|
||||
"-197": -197,
|
||||
"-198": -198,
|
||||
"-199": -199,
|
||||
"-200": -200,
|
||||
"-201": -201,
|
||||
"-202": -202,
|
||||
"-203": -203,
|
||||
"-204": -204,
|
||||
"-206": -206,
|
||||
"-207": -207,
|
||||
"-208": -208,
|
||||
"-209": -209,
|
||||
"-210": -210,
|
||||
"-211": -211,
|
||||
"-213": -213,
|
||||
"-214": -214,
|
||||
"0": 0,
|
||||
"1": 1,
|
||||
"2": 2,
|
||||
"3": 3,
|
||||
"4": 4,
|
||||
"5": 5,
|
||||
"6": 6,
|
||||
"7": 7,
|
||||
"8": 8,
|
||||
"9": 9,
|
||||
"10": 10,
|
||||
"11": 11,
|
||||
"12": 12,
|
||||
"13": 13,
|
||||
"14": 14,
|
||||
"15": 15,
|
||||
"16": 16,
|
||||
"17": 17,
|
||||
"18": 18,
|
||||
"19": 19,
|
||||
"20": 20,
|
||||
"21": 21,
|
||||
"22": 22,
|
||||
"23": 23,
|
||||
"24": 24,
|
||||
"25": 25,
|
||||
"26": 26,
|
||||
"27": 27,
|
||||
"28": 28,
|
||||
"29": 29,
|
||||
"30": 30,
|
||||
"31": 31,
|
||||
"32": 32,
|
||||
"33": 33,
|
||||
"34": 34,
|
||||
"35": 35,
|
||||
"36": 36,
|
||||
"37": 37,
|
||||
"38": 38,
|
||||
"39": 39,
|
||||
"40": 40,
|
||||
"41": 41,
|
||||
"42": 42,
|
||||
"43": 43,
|
||||
"44": 44,
|
||||
"45": 45,
|
||||
"46": 46,
|
||||
"47": 47,
|
||||
"48": 48,
|
||||
"49": 49,
|
||||
"50": 50,
|
||||
"51": 51,
|
||||
"52": 52,
|
||||
"53": 53,
|
||||
"54": 54,
|
||||
"55": 55,
|
||||
"56": 56,
|
||||
"57": 57,
|
||||
"58": 58,
|
||||
"59": 59,
|
||||
"60": 60,
|
||||
"61": 61,
|
||||
"62": 62,
|
||||
"63": 63,
|
||||
"64": 64,
|
||||
"65": 65,
|
||||
"66": 66,
|
||||
"67": 67,
|
||||
"68": 68,
|
||||
"69": 69,
|
||||
"70": 70,
|
||||
"71": 71,
|
||||
"72": 72,
|
||||
"73": 73,
|
||||
"74": 74,
|
||||
"75": 75,
|
||||
"76": 76,
|
||||
"77": 77,
|
||||
"78": 78,
|
||||
"79": 79,
|
||||
"80": 80,
|
||||
"81": 81,
|
||||
"82": 82,
|
||||
"83": 83,
|
||||
"84": 84,
|
||||
"85": 85,
|
||||
"86": 86,
|
||||
"87": 87,
|
||||
"88": 88,
|
||||
"89": 89,
|
||||
"90": 90,
|
||||
"91": 91,
|
||||
"92": 92,
|
||||
"93": 93,
|
||||
"94": 94,
|
||||
"95": 95,
|
||||
"96": 96,
|
||||
"97": 97,
|
||||
"98": 98,
|
||||
"99": 99,
|
||||
"100": 100,
|
||||
"101": 101,
|
||||
"102": 102,
|
||||
"103": 103,
|
||||
"104": 104,
|
||||
"105": 105,
|
||||
"106": 106,
|
||||
"107": 107,
|
||||
"108": 108,
|
||||
"109": 109,
|
||||
"110": 110,
|
||||
"111": 111,
|
||||
"112": 112,
|
||||
"113": 113,
|
||||
"114": 114,
|
||||
"115": 115,
|
||||
"116": 116,
|
||||
"117": 117,
|
||||
"118": 118,
|
||||
"119": 119,
|
||||
"120": 120,
|
||||
"121": 121,
|
||||
"122": 122,
|
||||
"123": 123,
|
||||
"124": 124,
|
||||
"125": 125,
|
||||
"126": 126,
|
||||
"127": 127,
|
||||
"128": 128,
|
||||
"129": 129,
|
||||
"130": 130,
|
||||
"131": 131,
|
||||
"132": 132,
|
||||
"133": 133,
|
||||
"134": 134,
|
||||
"135": 135,
|
||||
"136": 136,
|
||||
"137": 137,
|
||||
"138": 138,
|
||||
"139": 139,
|
||||
"140": 140,
|
||||
"141": 141,
|
||||
"142": 142,
|
||||
"143": 143,
|
||||
"144": 144,
|
||||
"145": 145,
|
||||
"146": 146,
|
||||
"147": 147,
|
||||
"148": 148,
|
||||
"149": 149,
|
||||
"150": 150,
|
||||
"151": 151,
|
||||
"152": 152,
|
||||
"153": 153,
|
||||
"154": 154,
|
||||
"155": 155,
|
||||
"156": 156,
|
||||
"157": 157,
|
||||
"158": 158,
|
||||
"159": 159,
|
||||
"160": 160,
|
||||
"161": 161,
|
||||
"162": 162,
|
||||
"163": 163,
|
||||
"164": 164,
|
||||
"165": 165,
|
||||
"166": 166,
|
||||
"167": 167,
|
||||
"168": 168,
|
||||
"169": 169,
|
||||
"170": 170,
|
||||
"171": 171,
|
||||
"172": 172,
|
||||
"173": 173,
|
||||
"174": 174,
|
||||
"175": 175,
|
||||
"176": 176,
|
||||
"177": 177,
|
||||
"178": 178,
|
||||
"179": 179,
|
||||
"180": 180,
|
||||
"181": 181,
|
||||
"182": 182,
|
||||
"183": 183,
|
||||
"184": 184,
|
||||
"185": 185,
|
||||
"186": 186,
|
||||
"187": 187,
|
||||
"188": 188,
|
||||
"189": 189,
|
||||
"190": 190,
|
||||
"191": 191,
|
||||
"192": 192,
|
||||
"193": 193,
|
||||
"194": 194,
|
||||
"195": 195,
|
||||
"196": 196,
|
||||
"197": 197,
|
||||
"198": 198,
|
||||
"199": 199,
|
||||
"200": 200,
|
||||
"201": 201,
|
||||
"202": 202,
|
||||
"203": 203,
|
||||
"204": 204,
|
||||
"205": 205,
|
||||
"206": 206,
|
||||
"207": 207,
|
||||
"208": 208,
|
||||
"209": 209,
|
||||
"213": 213,
|
||||
"214": 214,
|
||||
"215": 215,
|
||||
"216": 216,
|
||||
"218": 218,
|
||||
"219": 219,
|
||||
"220": 220,
|
||||
"221": 221,
|
||||
"222": 222,
|
||||
"223": 223,
|
||||
"224": 224,
|
||||
"225": 225,
|
||||
"226": 226,
|
||||
"227": 227,
|
||||
"228": 228,
|
||||
"229": 229,
|
||||
"231": 231,
|
||||
"232": 232,
|
||||
"233": 233,
|
||||
"234": 234,
|
||||
"235": 235,
|
||||
"236": 236,
|
||||
"237": 237,
|
||||
"238": 238,
|
||||
"239": 239,
|
||||
"240": 240,
|
||||
"241": 241,
|
||||
"243": 243,
|
||||
"244": 244,
|
||||
"245": 245,
|
||||
"246": 246,
|
||||
"247": 247,
|
||||
"248": 248,
|
||||
"249": 249,
|
||||
"250": 250,
|
||||
"251": 251,
|
||||
"252": 252,
|
||||
"253": 253,
|
||||
"254": 254,
|
||||
"255": 255,
|
||||
"256": 256,
|
||||
"257": 257,
|
||||
"258": 258,
|
||||
"259": 259,
|
||||
"260": 260,
|
||||
"261": 261,
|
||||
"262": 262,
|
||||
"263": 263,
|
||||
"264": 264,
|
||||
"265": 265,
|
||||
"266": 266,
|
||||
"267": 267,
|
||||
"268": 268,
|
||||
"269": 269,
|
||||
"270": 270,
|
||||
"271": 271,
|
||||
"272": 272,
|
||||
"273": 273,
|
||||
"274": 274,
|
||||
"275": 275,
|
||||
"276": 276,
|
||||
"277": 277,
|
||||
"278": 278,
|
||||
"279": 279,
|
||||
"280": 280,
|
||||
"281": 281,
|
||||
"282": 282,
|
||||
"283": 283,
|
||||
"284": 284,
|
||||
"285": 285,
|
||||
"286": 286,
|
||||
"287": 287,
|
||||
"288": 288,
|
||||
"289": 289,
|
||||
"290": 290,
|
||||
"291": 291,
|
||||
"292": 292,
|
||||
"293": 293,
|
||||
"294": 294,
|
||||
"295": 295,
|
||||
"296": 296,
|
||||
"297": 297,
|
||||
"298": 298,
|
||||
"299": 299,
|
||||
"300": 300,
|
||||
"301": 301,
|
||||
"302": 302,
|
||||
"303": 303,
|
||||
"304": 304,
|
||||
"305": 305,
|
||||
"306": 306,
|
||||
"307": 307,
|
||||
"308": 308,
|
||||
"309": 309,
|
||||
"310": 310,
|
||||
"311": 311,
|
||||
"312": 312,
|
||||
"313": 313,
|
||||
"314": 314,
|
||||
"315": 315,
|
||||
"316": 316,
|
||||
"317": 317,
|
||||
"318": 318,
|
||||
"319": 319,
|
||||
"320": 320,
|
||||
"321": 321,
|
||||
"322": 322,
|
||||
"323": 323,
|
||||
"324": 324,
|
||||
"325": 325,
|
||||
"328": 328,
|
||||
"329": 329,
|
||||
"330": 330,
|
||||
"331": 331,
|
||||
"332": 332,
|
||||
"333": 333,
|
||||
"334": 334,
|
||||
"335": 335,
|
||||
"336": 336,
|
||||
"337": 337,
|
||||
"338": 338,
|
||||
"339": 339,
|
||||
"340": 340,
|
||||
"341": 341,
|
||||
"342": 342,
|
||||
"344": 344,
|
||||
"345": 345,
|
||||
"346": 346,
|
||||
"347": 347,
|
||||
"348": 348,
|
||||
"349": 349,
|
||||
"350": 350,
|
||||
"351": 351,
|
||||
"352": 352,
|
||||
"353": 353,
|
||||
"354": 354,
|
||||
"355": 355,
|
||||
"356": 356,
|
||||
"357": 357,
|
||||
"358": 358,
|
||||
"359": 359,
|
||||
"360": 360,
|
||||
"361": 361,
|
||||
"362": 362,
|
||||
"363": 363,
|
||||
"364": 364,
|
||||
"365": 365,
|
||||
"366": 366,
|
||||
"367": 367,
|
||||
"368": 368,
|
||||
"369": 369,
|
||||
"370": 370,
|
||||
"371": 371,
|
||||
"372": 372,
|
||||
"373": 373,
|
||||
"374": 374,
|
||||
"375": 375,
|
||||
"376": 376,
|
||||
"377": 377,
|
||||
"378": 378,
|
||||
"379": 379,
|
||||
"380": 380,
|
||||
"381": 381,
|
||||
"382": 382,
|
||||
"383": 383,
|
||||
"384": 384,
|
||||
"385": 385,
|
||||
"386": 386,
|
||||
"387": 387,
|
||||
"388": 388,
|
||||
"389": 389,
|
||||
"390": 390,
|
||||
"391": 391,
|
||||
"392": 392,
|
||||
"393": 393,
|
||||
"394": 394,
|
||||
"395": 395,
|
||||
"396": 396,
|
||||
"397": 397,
|
||||
"398": 398,
|
||||
"399": 399,
|
||||
"400": 400,
|
||||
"401": 401,
|
||||
"402": 402,
|
||||
"403": 403,
|
||||
"404": 404,
|
||||
"405": 405,
|
||||
"406": 406,
|
||||
"407": 407,
|
||||
"408": 408,
|
||||
"409": 409,
|
||||
"410": 410,
|
||||
"411": 411,
|
||||
"412": 412,
|
||||
"413": 413,
|
||||
"414": 414,
|
||||
"415": 415,
|
||||
"416": 416,
|
||||
"417": 417,
|
||||
"418": 418,
|
||||
"419": 419,
|
||||
"420": 420,
|
||||
"421": 421,
|
||||
"422": 422,
|
||||
"423": 423,
|
||||
"424": 424,
|
||||
"425": 425,
|
||||
"426": 426,
|
||||
"427": 427,
|
||||
"428": 428,
|
||||
"429": 429,
|
||||
"430": 430,
|
||||
"431": 431,
|
||||
"432": 432,
|
||||
"433": 433,
|
||||
"434": 434,
|
||||
"437": 437,
|
||||
"438": 438,
|
||||
"441": 441,
|
||||
"442": 442,
|
||||
"443": 443,
|
||||
"444": 444,
|
||||
"445": 445,
|
||||
"446": 446,
|
||||
"447": 447,
|
||||
"448": 448,
|
||||
"449": 449,
|
||||
"450": 450,
|
||||
"451": 451,
|
||||
"452": 452,
|
||||
"453": 453,
|
||||
"455": 455,
|
||||
"457": 457,
|
||||
"458": 458,
|
||||
"459": 459,
|
||||
"460": 460,
|
||||
"461": 461,
|
||||
"462": 462,
|
||||
"463": 463,
|
||||
"464": 464,
|
||||
"465": 465,
|
||||
"466": 466,
|
||||
"467": 467,
|
||||
"468": 468,
|
||||
"469": 469,
|
||||
"470": 470,
|
||||
"471": 471,
|
||||
"472": 472,
|
||||
"473": 473,
|
||||
"474": 474,
|
||||
"475": 475,
|
||||
"476": 476,
|
||||
"477": 477,
|
||||
"499": 499,
|
||||
"500": 500,
|
||||
"501": 501,
|
||||
"502": 502,
|
||||
"503": 503,
|
||||
"504": 504,
|
||||
"505": 505,
|
||||
"506": 506,
|
||||
"507": 507,
|
||||
"508": 508,
|
||||
"509": 509,
|
||||
"510": 510,
|
||||
"511": 511,
|
||||
"513": 513,
|
||||
"acacia_button": -140,
|
||||
"acacia_door": 430,
|
||||
"acacia_door_block": 196,
|
||||
@ -226,27 +913,16 @@
|
||||
"egg": 344,
|
||||
"element_0": 36,
|
||||
"element_1": -12,
|
||||
"element_2": -13,
|
||||
"element_3": -14,
|
||||
"element_4": -15,
|
||||
"element_5": -16,
|
||||
"element_6": -17,
|
||||
"element_7": -18,
|
||||
"element_8": -19,
|
||||
"element_9": -20,
|
||||
"element_10": -21,
|
||||
"element_100": -111,
|
||||
"element_101": -112,
|
||||
"element_102": -113,
|
||||
"element_103": -114,
|
||||
"element_104": -115,
|
||||
"element_105": -116,
|
||||
"element_106": -117,
|
||||
"element_107": -118,
|
||||
"element_108": -119,
|
||||
"element_109": -120,
|
||||
"element_11": -22,
|
||||
"element_110": -121,
|
||||
"element_111": -122,
|
||||
"element_112": -123,
|
||||
"element_113": -124,
|
||||
"element_114": -125,
|
||||
"element_115": -126,
|
||||
"element_116": -127,
|
||||
"element_117": -128,
|
||||
"element_118": -129,
|
||||
"element_12": -23,
|
||||
"element_13": -24,
|
||||
"element_14": -25,
|
||||
@ -255,7 +931,6 @@
|
||||
"element_17": -28,
|
||||
"element_18": -29,
|
||||
"element_19": -30,
|
||||
"element_2": -13,
|
||||
"element_20": -31,
|
||||
"element_21": -32,
|
||||
"element_22": -33,
|
||||
@ -266,7 +941,6 @@
|
||||
"element_27": -38,
|
||||
"element_28": -39,
|
||||
"element_29": -40,
|
||||
"element_3": -14,
|
||||
"element_30": -41,
|
||||
"element_31": -42,
|
||||
"element_32": -43,
|
||||
@ -277,7 +951,6 @@
|
||||
"element_37": -48,
|
||||
"element_38": -49,
|
||||
"element_39": -50,
|
||||
"element_4": -15,
|
||||
"element_40": -51,
|
||||
"element_41": -52,
|
||||
"element_42": -53,
|
||||
@ -288,7 +961,6 @@
|
||||
"element_47": -58,
|
||||
"element_48": -59,
|
||||
"element_49": -60,
|
||||
"element_5": -16,
|
||||
"element_50": -61,
|
||||
"element_51": -62,
|
||||
"element_52": -63,
|
||||
@ -299,7 +971,6 @@
|
||||
"element_57": -68,
|
||||
"element_58": -69,
|
||||
"element_59": -70,
|
||||
"element_6": -17,
|
||||
"element_60": -71,
|
||||
"element_61": -72,
|
||||
"element_62": -73,
|
||||
@ -310,7 +981,6 @@
|
||||
"element_67": -78,
|
||||
"element_68": -79,
|
||||
"element_69": -80,
|
||||
"element_7": -18,
|
||||
"element_70": -81,
|
||||
"element_71": -82,
|
||||
"element_72": -83,
|
||||
@ -321,7 +991,6 @@
|
||||
"element_77": -88,
|
||||
"element_78": -89,
|
||||
"element_79": -90,
|
||||
"element_8": -19,
|
||||
"element_80": -91,
|
||||
"element_81": -92,
|
||||
"element_82": -93,
|
||||
@ -332,7 +1001,6 @@
|
||||
"element_87": -98,
|
||||
"element_88": -99,
|
||||
"element_89": -100,
|
||||
"element_9": -20,
|
||||
"element_90": -101,
|
||||
"element_91": -102,
|
||||
"element_92": -103,
|
||||
@ -343,6 +1011,25 @@
|
||||
"element_97": -108,
|
||||
"element_98": -109,
|
||||
"element_99": -110,
|
||||
"element_100": -111,
|
||||
"element_101": -112,
|
||||
"element_102": -113,
|
||||
"element_103": -114,
|
||||
"element_104": -115,
|
||||
"element_105": -116,
|
||||
"element_106": -117,
|
||||
"element_107": -118,
|
||||
"element_108": -119,
|
||||
"element_109": -120,
|
||||
"element_110": -121,
|
||||
"element_111": -122,
|
||||
"element_112": -123,
|
||||
"element_113": -124,
|
||||
"element_114": -125,
|
||||
"element_115": -126,
|
||||
"element_116": -127,
|
||||
"element_117": -128,
|
||||
"element_118": -129,
|
||||
"elytra": 444,
|
||||
"emerald": 388,
|
||||
"emerald_block": 133,
|
||||
@ -532,8 +1219,8 @@
|
||||
"leather_pants": 300,
|
||||
"leather_tunic": 299,
|
||||
"leave": 18,
|
||||
"leaves": 18,
|
||||
"leave2": 161,
|
||||
"leaves": 18,
|
||||
"leaves2": 161,
|
||||
"lectern": -194,
|
||||
"lever": 69,
|
||||
|
Submodule resources/locale deleted from 95b9c82f25
@ -108,7 +108,7 @@ player:
|
||||
verify-xuid: true
|
||||
|
||||
level-settings:
|
||||
#The default format that levels will use when created
|
||||
#The default format that worlds will use when created
|
||||
default-format: leveldb
|
||||
|
||||
chunk-sending:
|
||||
@ -176,7 +176,7 @@ aliases:
|
||||
#savestop: [save-all, stop]
|
||||
|
||||
worlds:
|
||||
#These settings will override the generator set in server.properties and allows loading multiple levels
|
||||
#These settings will override the generator set in server.properties and allows loading multiple worlds
|
||||
#Example:
|
||||
#world:
|
||||
# seed: 404
|
||||
|
Submodule resources/vanilla deleted from 21ec07f14e
@ -35,3 +35,6 @@ define('pocketmine\_CORE_CONSTANTS_INCLUDED', true);
|
||||
|
||||
define('pocketmine\PATH', dirname(__DIR__) . '/');
|
||||
define('pocketmine\RESOURCE_PATH', dirname(__DIR__) . '/resources/');
|
||||
define('pocketmine\BEDROCK_DATA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-data/');
|
||||
define('pocketmine\LOCALE_DATA_PATH', dirname(__DIR__) . '/vendor/pocketmine/locale-data/');
|
||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', dirname(__DIR__) . '/vendor/autoload.php');
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\event\server\LowMemoryEvent;
|
||||
use pocketmine\network\mcpe\cache\ChunkCache;
|
||||
use pocketmine\scheduler\DumpWorkerMemoryTask;
|
||||
use pocketmine\scheduler\GarbageCollectionTask;
|
||||
use pocketmine\timings\Timings;
|
||||
@ -187,6 +188,7 @@ class MemoryManager{
|
||||
foreach($this->server->getWorldManager()->getWorlds() as $world){
|
||||
$world->clearCache(true);
|
||||
}
|
||||
ChunkCache::pruneCaches();
|
||||
}
|
||||
|
||||
if($this->lowMemChunkGC){
|
||||
@ -350,35 +352,33 @@ class MemoryManager{
|
||||
file_put_contents(Path::join($outputFolder, "staticProperties.js"), json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
$logger->info("Wrote $staticCount static properties");
|
||||
|
||||
if(isset($GLOBALS)){ //This might be null if we're on a different thread
|
||||
$globalVariables = [];
|
||||
$globalCount = 0;
|
||||
$globalVariables = [];
|
||||
$globalCount = 0;
|
||||
|
||||
$ignoredGlobals = [
|
||||
'GLOBALS' => true,
|
||||
'_SERVER' => true,
|
||||
'_REQUEST' => true,
|
||||
'_POST' => true,
|
||||
'_GET' => true,
|
||||
'_FILES' => true,
|
||||
'_ENV' => true,
|
||||
'_COOKIE' => true,
|
||||
'_SESSION' => true
|
||||
];
|
||||
$ignoredGlobals = [
|
||||
'GLOBALS' => true,
|
||||
'_SERVER' => true,
|
||||
'_REQUEST' => true,
|
||||
'_POST' => true,
|
||||
'_GET' => true,
|
||||
'_FILES' => true,
|
||||
'_ENV' => true,
|
||||
'_COOKIE' => true,
|
||||
'_SESSION' => true
|
||||
];
|
||||
|
||||
foreach($GLOBALS as $varName => $value){
|
||||
if(isset($ignoredGlobals[$varName])){
|
||||
continue;
|
||||
}
|
||||
|
||||
$globalCount++;
|
||||
$globalVariables[$varName] = self::continueDump($value, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
foreach(Utils::stringifyKeys($GLOBALS) as $varName => $value){
|
||||
if(isset($ignoredGlobals[$varName])){
|
||||
continue;
|
||||
}
|
||||
|
||||
file_put_contents(Path::join($outputFolder, "globalVariables.js"), json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
$logger->info("Wrote $globalCount global variables");
|
||||
$globalCount++;
|
||||
$globalVariables[$varName] = self::continueDump($value, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
|
||||
file_put_contents(Path::join($outputFolder, "globalVariables.js"), json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
$logger->info("Wrote $globalCount global variables");
|
||||
|
||||
foreach(get_defined_functions()["user"] as $function){
|
||||
$reflect = new \ReflectionFunction($function);
|
||||
|
||||
|
@ -34,6 +34,7 @@ namespace pocketmine {
|
||||
use pocketmine\utils\Timezone;
|
||||
use pocketmine\wizard\SetupWizard;
|
||||
use Webmozart\PathUtil\Path;
|
||||
use function defined;
|
||||
use function extension_loaded;
|
||||
use function phpversion;
|
||||
use function preg_match;
|
||||
@ -116,8 +117,8 @@ namespace pocketmine {
|
||||
if(substr_count($pthreads_version, ".") < 2){
|
||||
$pthreads_version = "0.$pthreads_version";
|
||||
}
|
||||
if(version_compare($pthreads_version, "3.2.0") < 0){
|
||||
$messages[] = "pthreads >= 3.2.0 is required, while you have $pthreads_version.";
|
||||
if(version_compare($pthreads_version, "4.0.0") < 0 || version_compare($pthreads_version, "5.0.0") > 0){
|
||||
$messages[] = "pthreads ^4.0.0 is required, while you have $pthreads_version.";
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,6 +127,9 @@ namespace pocketmine {
|
||||
if(version_compare($leveldb_version, "0.2.1") < 0){
|
||||
$messages[] = "php-leveldb >= 0.2.1 is required, while you have $leveldb_version.";
|
||||
}
|
||||
if(!defined('LEVELDB_ZLIB_RAW_COMPRESSION')){
|
||||
$messages[] = "Given version of php-leveldb doesn't support ZLIB_RAW compression (use https://github.com/pmmp/php-leveldb)";
|
||||
}
|
||||
}
|
||||
|
||||
$chunkutils2_version = phpversion("chunkutils2");
|
||||
@ -142,6 +146,10 @@ namespace pocketmine {
|
||||
$messages[] = "The native PocketMine extension is no longer supported.";
|
||||
}
|
||||
|
||||
if(!defined('AF_INET6')){
|
||||
$messages[] = "IPv6 support is required, but your PHP binary was built without IPv6 support.";
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
@ -205,6 +213,8 @@ JIT_WARNING
|
||||
}
|
||||
critical_error("PHP binary used: " . $binary);
|
||||
critical_error("Loaded php.ini: " . (($file = php_ini_loaded_file()) !== false ? $file : "none"));
|
||||
$phprc = getenv("PHPRC");
|
||||
critical_error("Value of PHPRC environment variable: " . ($phprc === false ? "" : $phprc));
|
||||
critical_error("Please recompile PHP with the needed configuration, or refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html.");
|
||||
echo PHP_EOL;
|
||||
exit(1);
|
||||
@ -214,20 +224,13 @@ JIT_WARNING
|
||||
error_reporting(-1);
|
||||
set_ini_entries();
|
||||
|
||||
$opts = getopt("", ["bootstrap:"]);
|
||||
if(isset($opts["bootstrap"])){
|
||||
$bootstrap = ($real = realpath($opts["bootstrap"])) !== false ? $real : $opts["bootstrap"];
|
||||
}else{
|
||||
$bootstrap = dirname(__FILE__, 2) . '/vendor/autoload.php';
|
||||
}
|
||||
|
||||
if($bootstrap === false or !is_file($bootstrap)){
|
||||
$bootstrap = dirname(__FILE__, 2) . '/vendor/autoload.php';
|
||||
if(!is_file($bootstrap)){
|
||||
critical_error("Composer autoloader not found at " . $bootstrap);
|
||||
critical_error("Please install/update Composer dependencies or use provided builds.");
|
||||
exit(1);
|
||||
}
|
||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
|
||||
require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH);
|
||||
require_once($bootstrap);
|
||||
|
||||
$composerGitHash = InstalledVersions::getReference('pocketmine/pocketmine-mp');
|
||||
if($composerGitHash !== null){
|
||||
@ -307,7 +310,7 @@ JIT_WARNING
|
||||
|
||||
if(ThreadManager::getInstance()->stopAll() > 0){
|
||||
$logger->debug("Some threads could not be stopped, performing a force-kill");
|
||||
Process::kill(Process::pid());
|
||||
Process::kill(Process::pid(), true);
|
||||
}
|
||||
}while(false);
|
||||
|
||||
|
372
src/Server.php
372
src/Server.php
@ -34,12 +34,15 @@ use pocketmine\console\ConsoleCommandSender;
|
||||
use pocketmine\console\ConsoleReaderThread;
|
||||
use pocketmine\crafting\CraftingManager;
|
||||
use pocketmine\crafting\CraftingManagerFromDataHelper;
|
||||
use pocketmine\crash\CrashDump;
|
||||
use pocketmine\crash\CrashDumpRenderer;
|
||||
use pocketmine\data\java\GameModeIdMap;
|
||||
use pocketmine\entity\EntityDataHelper;
|
||||
use pocketmine\entity\Location;
|
||||
use pocketmine\event\HandlerListManager;
|
||||
use pocketmine\event\player\PlayerCreationEvent;
|
||||
use pocketmine\event\player\PlayerDataSaveEvent;
|
||||
use pocketmine\event\player\PlayerLoginEvent;
|
||||
use pocketmine\event\server\CommandEvent;
|
||||
use pocketmine\event\server\DataPacketSendEvent;
|
||||
use pocketmine\event\server\QueryRegenerateEvent;
|
||||
@ -63,6 +66,7 @@ use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
||||
use pocketmine\network\mcpe\protocol\serializer\PacketBatch;
|
||||
use pocketmine\network\mcpe\raklib\RakLibInterface;
|
||||
use pocketmine\network\Network;
|
||||
use pocketmine\network\NetworkInterfaceStartException;
|
||||
use pocketmine\network\query\DedicatedQueryNetworkInterface;
|
||||
use pocketmine\network\query\QueryHandler;
|
||||
use pocketmine\network\query\QueryInfo;
|
||||
@ -80,6 +84,8 @@ use pocketmine\plugin\PluginGraylist;
|
||||
use pocketmine\plugin\PluginManager;
|
||||
use pocketmine\plugin\PluginOwned;
|
||||
use pocketmine\plugin\ScriptPluginLoader;
|
||||
use pocketmine\promise\Promise;
|
||||
use pocketmine\promise\PromiseResolver;
|
||||
use pocketmine\resourcepacks\ResourcePackManager;
|
||||
use pocketmine\scheduler\AsyncPool;
|
||||
use pocketmine\snooze\SleeperHandler;
|
||||
@ -96,7 +102,7 @@ use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\NotCloneable;
|
||||
use pocketmine\utils\NotSerializable;
|
||||
use pocketmine\utils\Process;
|
||||
use pocketmine\utils\Promise;
|
||||
use pocketmine\utils\SignalHandler;
|
||||
use pocketmine\utils\Terminal;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\utils\Utils;
|
||||
@ -105,26 +111,29 @@ use pocketmine\world\format\io\WorldProviderManager;
|
||||
use pocketmine\world\format\io\WritableWorldProviderManagerEntry;
|
||||
use pocketmine\world\generator\Generator;
|
||||
use pocketmine\world\generator\GeneratorManager;
|
||||
use pocketmine\world\generator\InvalidGeneratorOptionsException;
|
||||
use pocketmine\world\World;
|
||||
use pocketmine\world\WorldCreationOptions;
|
||||
use pocketmine\world\WorldManager;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
use Webmozart\PathUtil\Path;
|
||||
use function array_shift;
|
||||
use function array_sum;
|
||||
use function base64_encode;
|
||||
use function cli_set_process_title;
|
||||
use function copy;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function date;
|
||||
use function fclose;
|
||||
use function file_exists;
|
||||
use function file_get_contents;
|
||||
use function file_put_contents;
|
||||
use function filemtime;
|
||||
use function fopen;
|
||||
use function get_class;
|
||||
use function implode;
|
||||
use function ini_set;
|
||||
use function is_array;
|
||||
use function is_dir;
|
||||
use function is_resource;
|
||||
use function is_string;
|
||||
use function json_decode;
|
||||
use function max;
|
||||
@ -251,6 +260,8 @@ class Server{
|
||||
/** @var Player[] */
|
||||
private array $playerList = [];
|
||||
|
||||
private SignalHandler $signalHandler;
|
||||
|
||||
/**
|
||||
* @var CommandSender[][]
|
||||
* @phpstan-var array<string, array<int, CommandSender>>
|
||||
@ -316,6 +327,10 @@ class Server{
|
||||
return $this->configGroup->getConfigInt("server-port", 19132);
|
||||
}
|
||||
|
||||
public function getPortV6() : int{
|
||||
return $this->configGroup->getConfigInt("server-portv6", 19133);
|
||||
}
|
||||
|
||||
public function getViewDistance() : int{
|
||||
return max(2, $this->configGroup->getConfigInt("view-distance", 8));
|
||||
}
|
||||
@ -332,6 +347,11 @@ class Server{
|
||||
return $str !== "" ? $str : "0.0.0.0";
|
||||
}
|
||||
|
||||
public function getIpV6() : string{
|
||||
$str = $this->configGroup->getConfigString("server-ipv6");
|
||||
return $str !== "" ? $str : "::";
|
||||
}
|
||||
|
||||
public function getServerUniqueId() : UuidInterface{
|
||||
return $this->serverID;
|
||||
}
|
||||
@ -517,9 +537,13 @@ class Server{
|
||||
if(!$ev->isCancelled()){
|
||||
Timings::$syncPlayerDataSave->time(function() use ($name, $ev) : void{
|
||||
$nbt = new BigEndianNbtSerializer();
|
||||
$contents = zlib_encode($nbt->write(new TreeRoot($ev->getSaveData())), ZLIB_ENCODING_GZIP);
|
||||
if($contents === false){
|
||||
throw new AssumptionFailedError("zlib_encode() failed unexpectedly");
|
||||
}
|
||||
try{
|
||||
file_put_contents($this->getPlayerDataPath($name), zlib_encode($nbt->write(new TreeRoot($ev->getSaveData())), ZLIB_ENCODING_GZIP));
|
||||
}catch(\ErrorException $e){
|
||||
Filesystem::safeFilePutContents($this->getPlayerDataPath($name), $contents);
|
||||
}catch(\RuntimeException | \ErrorException $e){
|
||||
$this->logger->critical($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_data_saveError($name, $e->getMessage())));
|
||||
$this->logger->logException($e);
|
||||
}
|
||||
@ -546,11 +570,11 @@ class Server{
|
||||
$playerPos = null;
|
||||
$spawn = $world->getSpawnLocation();
|
||||
}
|
||||
$playerPromise = new Promise();
|
||||
$playerPromiseResolver = new PromiseResolver();
|
||||
$world->requestChunkPopulation($spawn->getFloorX() >> Chunk::COORD_BIT_SIZE, $spawn->getFloorZ() >> Chunk::COORD_BIT_SIZE, null)->onCompletion(
|
||||
function() use ($playerPromise, $class, $session, $playerInfo, $authenticated, $world, $playerPos, $spawn, $offlinePlayerData) : void{
|
||||
function() use ($playerPromiseResolver, $class, $session, $playerInfo, $authenticated, $world, $playerPos, $spawn, $offlinePlayerData) : void{
|
||||
if(!$session->isConnected()){
|
||||
$playerPromise->reject();
|
||||
$playerPromiseResolver->reject();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -570,16 +594,16 @@ class Server{
|
||||
if(!$player->hasPlayedBefore()){
|
||||
$player->onGround = true; //TODO: this hack is needed for new players in-air ticks - they don't get detected as on-ground until they move
|
||||
}
|
||||
$playerPromise->resolve($player);
|
||||
$playerPromiseResolver->resolve($player);
|
||||
},
|
||||
static function() use ($playerPromise, $session) : void{
|
||||
static function() use ($playerPromiseResolver, $session) : void{
|
||||
if($session->isConnected()){
|
||||
$session->disconnect("Spawn terrain generation failed");
|
||||
}
|
||||
$playerPromise->reject();
|
||||
$playerPromiseResolver->reject();
|
||||
}
|
||||
);
|
||||
return $playerPromise;
|
||||
return $playerPromiseResolver->getPromise();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -735,7 +759,7 @@ class Server{
|
||||
|
||||
public function __construct(\DynamicClassLoader $autoloader, \AttachableThreadedLogger $logger, string $dataPath, string $pluginPath){
|
||||
if(self::$instance !== null){
|
||||
throw new \InvalidStateException("Only one server instance can exist at once");
|
||||
throw new \LogicException("Only one server instance can exist at once");
|
||||
}
|
||||
self::$instance = $this;
|
||||
$this->startTime = microtime(true);
|
||||
@ -744,6 +768,11 @@ class Server{
|
||||
$this->autoloader = $autoloader;
|
||||
$this->logger = $logger;
|
||||
|
||||
$this->signalHandler = new SignalHandler(function() : void{
|
||||
$this->logger->info("Received signal interrupt, stopping the server");
|
||||
$this->shutdown();
|
||||
});
|
||||
|
||||
try{
|
||||
foreach([
|
||||
$dataPath,
|
||||
@ -774,6 +803,8 @@ class Server{
|
||||
new Config(Path::join($this->dataPath, "server.properties"), Config::PROPERTIES, [
|
||||
"motd" => VersionInfo::NAME . " Server",
|
||||
"server-port" => 19132,
|
||||
"server-portv6" => 19133,
|
||||
"enable-ipv6" => true,
|
||||
"white-list" => false,
|
||||
"max-players" => 20,
|
||||
"gamemode" => 0,
|
||||
@ -923,7 +954,7 @@ class Server{
|
||||
|
||||
$this->commandMap = new SimpleCommandMap($this);
|
||||
|
||||
$this->craftingManager = CraftingManagerFromDataHelper::make(Path::join(\pocketmine\RESOURCE_PATH, "vanilla", "recipes.json"));
|
||||
$this->craftingManager = CraftingManagerFromDataHelper::make(Path::join(\pocketmine\BEDROCK_DATA_PATH, "recipes.json"));
|
||||
|
||||
$this->resourceManager = new ResourcePackManager(Path::join($this->getDataPath(), "resource_packs"), $this->logger);
|
||||
|
||||
@ -966,91 +997,17 @@ class Server{
|
||||
$this->pluginManager->loadPlugins($this->pluginPath);
|
||||
$this->enablePlugins(PluginEnableOrder::STARTUP());
|
||||
|
||||
foreach((array) $this->configGroup->getProperty("worlds", []) as $name => $options){
|
||||
if($options === null){
|
||||
$options = [];
|
||||
}elseif(!is_array($options)){
|
||||
continue;
|
||||
}
|
||||
if(!$this->worldManager->loadWorld($name, true)){
|
||||
$creationOptions = WorldCreationOptions::create();
|
||||
//TODO: error checking
|
||||
|
||||
if(isset($options["generator"])){
|
||||
$generatorOptions = explode(":", $options["generator"]);
|
||||
$creationOptions->setGeneratorClass(GeneratorManager::getInstance()->getGenerator(array_shift($generatorOptions)));
|
||||
if(count($generatorOptions) > 0){
|
||||
$creationOptions->setGeneratorOptions(implode(":", $generatorOptions));
|
||||
}
|
||||
}
|
||||
if(isset($options["difficulty"]) && is_string($options["difficulty"])){
|
||||
$creationOptions->setDifficulty(World::getDifficultyFromString($options["difficulty"]));
|
||||
}
|
||||
if(isset($options["preset"]) && is_string($options["preset"])){
|
||||
$creationOptions->setGeneratorOptions($options["preset"]);
|
||||
}
|
||||
if(isset($options["seed"])){
|
||||
$convertedSeed = Generator::convertSeed((string) ($options["seed"] ?? ""));
|
||||
if($convertedSeed !== null){
|
||||
$creationOptions->setSeed($convertedSeed);
|
||||
}
|
||||
}
|
||||
|
||||
$this->worldManager->generateWorld($name, $creationOptions);
|
||||
}
|
||||
if(!$this->startupPrepareWorlds()){
|
||||
return;
|
||||
}
|
||||
|
||||
if($this->worldManager->getDefaultWorld() === null){
|
||||
$default = $this->configGroup->getConfigString("level-name", "world");
|
||||
if(trim($default) == ""){
|
||||
$this->getLogger()->warning("level-name cannot be null, using default");
|
||||
$default = "world";
|
||||
$this->configGroup->setConfigString("level-name", "world");
|
||||
}
|
||||
if(!$this->worldManager->loadWorld($default, true)){
|
||||
$creationOptions = WorldCreationOptions::create()
|
||||
->setGeneratorClass(GeneratorManager::getInstance()->getGenerator($this->configGroup->getConfigString("level-type")))
|
||||
->setGeneratorOptions($this->configGroup->getConfigString("generator-settings"));
|
||||
$convertedSeed = Generator::convertSeed($this->configGroup->getConfigString("level-seed"));
|
||||
if($convertedSeed !== null){
|
||||
$creationOptions->setSeed($convertedSeed);
|
||||
}
|
||||
$this->worldManager->generateWorld($default, $creationOptions);
|
||||
}
|
||||
|
||||
$world = $this->worldManager->getWorldByName($default);
|
||||
if($world === null){
|
||||
$this->getLogger()->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_level_defaultError()));
|
||||
$this->forceShutdown();
|
||||
|
||||
return;
|
||||
}
|
||||
$this->worldManager->setDefaultWorld($world);
|
||||
}
|
||||
|
||||
$this->enablePlugins(PluginEnableOrder::POSTWORLD());
|
||||
|
||||
$useQuery = $this->configGroup->getConfigBool("enable-query", true);
|
||||
if(!$this->network->registerInterface(new RakLibInterface($this)) && $useQuery){
|
||||
//RakLib would normally handle the transport for Query packets
|
||||
//if it's not registered we need to make sure Query still works
|
||||
$this->network->registerInterface(new DedicatedQueryNetworkInterface($this->getIp(), $this->getPort(), new \PrefixedLogger($this->logger, "Dedicated Query Interface")));
|
||||
}
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_networkStart($this->getIp(), (string) $this->getPort())));
|
||||
|
||||
if($useQuery){
|
||||
$this->network->registerRawPacketHandler(new QueryHandler($this));
|
||||
if(!$this->startupPrepareNetworkInterfaces()){
|
||||
$this->forceShutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach($this->getIPBans()->getEntries() as $entry){
|
||||
$this->network->blockAddress($entry->getName(), -1);
|
||||
}
|
||||
|
||||
if($this->configGroup->getPropertyBool("network.upnp-forwarding", false)){
|
||||
$this->network->registerInterface(new UPnPNetworkInterface($this->logger, Internet::getInternalIP(), $this->getPort()));
|
||||
}
|
||||
|
||||
if($this->configGroup->getPropertyBool("settings.send-usage", true)){
|
||||
if($this->configGroup->getPropertyBool("anonymous-statistics.enabled", true)){
|
||||
$this->sendUsageTicker = 6000;
|
||||
$this->sendUsage(SendUsageTask::TYPE_OPEN);
|
||||
}
|
||||
@ -1085,6 +1042,153 @@ class Server{
|
||||
}
|
||||
}
|
||||
|
||||
private function startupPrepareWorlds() : bool{
|
||||
$getGenerator = function(string $generatorName, string $generatorOptions, string $worldName) : ?string{
|
||||
$generatorEntry = GeneratorManager::getInstance()->getGenerator($generatorName);
|
||||
if($generatorEntry === null){
|
||||
$this->logger->error($this->language->translate(KnownTranslationFactory::pocketmine_level_generationError(
|
||||
$worldName,
|
||||
KnownTranslationFactory::pocketmine_level_unknownGenerator($generatorName)
|
||||
)));
|
||||
return null;
|
||||
}
|
||||
try{
|
||||
$generatorEntry->validateGeneratorOptions($generatorOptions);
|
||||
}catch(InvalidGeneratorOptionsException $e){
|
||||
$this->logger->error($this->language->translate(KnownTranslationFactory::pocketmine_level_generationError(
|
||||
$worldName,
|
||||
KnownTranslationFactory::pocketmine_level_invalidGeneratorOptions($generatorOptions, $generatorName, $e->getMessage())
|
||||
)));
|
||||
return null;
|
||||
}
|
||||
return $generatorEntry->getGeneratorClass();
|
||||
};
|
||||
|
||||
foreach((array) $this->configGroup->getProperty("worlds", []) as $name => $options){
|
||||
if($options === null){
|
||||
$options = [];
|
||||
}elseif(!is_array($options)){
|
||||
continue;
|
||||
}
|
||||
if(!$this->worldManager->loadWorld($name, true) && !$this->worldManager->isWorldGenerated($name)){
|
||||
$creationOptions = WorldCreationOptions::create();
|
||||
//TODO: error checking
|
||||
|
||||
$generatorName = $options["generator"] ?? "default";
|
||||
$generatorOptions = isset($options["preset"]) && is_string($options["preset"]) ? $options["preset"] : "";
|
||||
|
||||
$generatorClass = $getGenerator($generatorName, $generatorOptions, $name);
|
||||
if($generatorClass === null){
|
||||
continue;
|
||||
}
|
||||
$creationOptions->setGeneratorClass($generatorClass);
|
||||
$creationOptions->setGeneratorOptions($generatorOptions);
|
||||
|
||||
if(isset($options["difficulty"]) && is_string($options["difficulty"])){
|
||||
$creationOptions->setDifficulty(World::getDifficultyFromString($options["difficulty"]));
|
||||
}
|
||||
|
||||
if(isset($options["seed"])){
|
||||
$convertedSeed = Generator::convertSeed((string) ($options["seed"] ?? ""));
|
||||
if($convertedSeed !== null){
|
||||
$creationOptions->setSeed($convertedSeed);
|
||||
}
|
||||
}
|
||||
|
||||
$this->worldManager->generateWorld($name, $creationOptions);
|
||||
}
|
||||
}
|
||||
|
||||
if($this->worldManager->getDefaultWorld() === null){
|
||||
$default = $this->configGroup->getConfigString("level-name", "world");
|
||||
if(trim($default) == ""){
|
||||
$this->getLogger()->warning("level-name cannot be null, using default");
|
||||
$default = "world";
|
||||
$this->configGroup->setConfigString("level-name", "world");
|
||||
}
|
||||
if(!$this->worldManager->loadWorld($default, true) && !$this->worldManager->isWorldGenerated($default)){
|
||||
$generatorName = $this->configGroup->getConfigString("level-type");
|
||||
$generatorOptions = $this->configGroup->getConfigString("generator-settings");
|
||||
$generatorClass = $getGenerator($generatorName, $generatorOptions, $default);
|
||||
if($generatorClass !== null){
|
||||
$creationOptions = WorldCreationOptions::create()
|
||||
->setGeneratorClass($generatorClass)
|
||||
->setGeneratorOptions($generatorOptions);
|
||||
$convertedSeed = Generator::convertSeed($this->configGroup->getConfigString("level-seed"));
|
||||
if($convertedSeed !== null){
|
||||
$creationOptions->setSeed($convertedSeed);
|
||||
}
|
||||
$this->worldManager->generateWorld($default, $creationOptions);
|
||||
}
|
||||
}
|
||||
|
||||
$world = $this->worldManager->getWorldByName($default);
|
||||
if($world === null){
|
||||
$this->getLogger()->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_level_defaultError()));
|
||||
$this->forceShutdown();
|
||||
|
||||
return false;
|
||||
}
|
||||
$this->worldManager->setDefaultWorld($world);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function startupPrepareConnectableNetworkInterfaces(string $ip, int $port, bool $ipV6, bool $useQuery) : bool{
|
||||
$prettyIp = $ipV6 ? "[$ip]" : $ip;
|
||||
try{
|
||||
$rakLibRegistered = $this->network->registerInterface(new RakLibInterface($this, $ip, $port, $ipV6));
|
||||
}catch(NetworkInterfaceStartException $e){
|
||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_networkStartFailed(
|
||||
$ip,
|
||||
(string) $port,
|
||||
$e->getMessage()
|
||||
)));
|
||||
return false;
|
||||
}
|
||||
if($rakLibRegistered){
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_networkStart($prettyIp, (string) $port)));
|
||||
}
|
||||
if($useQuery){
|
||||
if(!$rakLibRegistered){
|
||||
//RakLib would normally handle the transport for Query packets
|
||||
//if it's not registered we need to make sure Query still works
|
||||
$this->network->registerInterface(new DedicatedQueryNetworkInterface($ip, $port, $ipV6, new \PrefixedLogger($this->logger, "Dedicated Query Interface")));
|
||||
}
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_query_running($prettyIp, (string) $port)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function startupPrepareNetworkInterfaces() : bool{
|
||||
$useQuery = $this->configGroup->getConfigBool("enable-query", true);
|
||||
|
||||
if(
|
||||
!$this->startupPrepareConnectableNetworkInterfaces($this->getIp(), $this->getPort(), false, $useQuery) ||
|
||||
(
|
||||
$this->configGroup->getConfigBool("enable-ipv6", true) &&
|
||||
!$this->startupPrepareConnectableNetworkInterfaces($this->getIpV6(), $this->getPortV6(), true, $useQuery)
|
||||
)
|
||||
){
|
||||
return false;
|
||||
}
|
||||
|
||||
if($useQuery){
|
||||
$this->network->registerRawPacketHandler(new QueryHandler($this));
|
||||
}
|
||||
|
||||
foreach($this->getIPBans()->getEntries() as $entry){
|
||||
$this->network->blockAddress($entry->getName(), -1);
|
||||
}
|
||||
|
||||
if($this->configGroup->getPropertyBool("network.upnp-forwarding", false)){
|
||||
$this->network->registerInterface(new UPnPNetworkInterface($this->logger, Internet::getInternalIP(), $this->getPort()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes to a particular message broadcast channel.
|
||||
* The channel ID can be any arbitrary string.
|
||||
@ -1109,7 +1213,7 @@ class Server{
|
||||
* Unsubscribes from all broadcast channels.
|
||||
*/
|
||||
public function unsubscribeFromAllBroadcastChannels(CommandSender $subscriber) : void{
|
||||
foreach($this->broadcastSubscribers as $channelId => $recipients){
|
||||
foreach(Utils::stringifyKeys($this->broadcastSubscribers) as $channelId => $recipients){
|
||||
$this->unsubscribeFromBroadcastChannel($channelId, $subscriber);
|
||||
}
|
||||
}
|
||||
@ -1293,20 +1397,17 @@ class Server{
|
||||
$commandLine = $ev->getCommand();
|
||||
}
|
||||
|
||||
if($this->commandMap->dispatch($sender, $commandLine)){
|
||||
return true;
|
||||
}
|
||||
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_generic_notFound()->prefix(TextFormat::RED));
|
||||
|
||||
return false;
|
||||
return $this->commandMap->dispatch($sender, $commandLine);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts the server down correctly
|
||||
*/
|
||||
public function shutdown() : void{
|
||||
$this->isRunning = false;
|
||||
if($this->isRunning){
|
||||
$this->isRunning = false;
|
||||
$this->signalHandler->unregister();
|
||||
}
|
||||
}
|
||||
|
||||
public function forceShutdown() : void{
|
||||
@ -1318,6 +1419,9 @@ class Server{
|
||||
echo "\x1b]0;\x07";
|
||||
}
|
||||
|
||||
if($this->isRunning){
|
||||
$this->logger->emergency("Forcing server shutdown");
|
||||
}
|
||||
try{
|
||||
if(!$this->isRunning()){
|
||||
$this->sendUsage(SendUsageTask::TYPE_CLOSE);
|
||||
@ -1371,7 +1475,7 @@ class Server{
|
||||
}catch(\Throwable $e){
|
||||
$this->logger->logException($e);
|
||||
$this->logger->emergency("Crashed while crashing, killing process");
|
||||
@Process::kill(Process::pid());
|
||||
@Process::kill(Process::pid(), true);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1416,6 +1520,25 @@ class Server{
|
||||
$this->crashDump();
|
||||
}
|
||||
|
||||
private function writeCrashDumpFile(CrashDump $dump) : string{
|
||||
$crashFolder = Path::join($this->getDataPath(), "crashdumps");
|
||||
if(!is_dir($crashFolder)){
|
||||
mkdir($crashFolder);
|
||||
}
|
||||
$crashDumpPath = Path::join($crashFolder, date("D_M_j-H.i.s-T_Y", (int) $dump->getData()->time) . ".log");
|
||||
|
||||
$fp = @fopen($crashDumpPath, "wb");
|
||||
if(!is_resource($fp)){
|
||||
throw new \RuntimeException("Unable to open new file to generate crashdump");
|
||||
}
|
||||
$writer = new CrashDumpRenderer($fp, $dump->getData());
|
||||
$writer->renderHumanReadable();
|
||||
$dump->encodeData($writer);
|
||||
|
||||
fclose($fp);
|
||||
return $crashDumpPath;
|
||||
}
|
||||
|
||||
public function crashDump() : void{
|
||||
while(@ob_end_flush()){}
|
||||
if(!$this->isRunning){
|
||||
@ -1430,9 +1553,11 @@ class Server{
|
||||
ini_set("memory_limit", '-1'); //Fix error dump not dumped on memory problems
|
||||
try{
|
||||
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_create()));
|
||||
$dump = new CrashDump($this);
|
||||
$dump = new CrashDump($this, $this->pluginManager ?? null);
|
||||
|
||||
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_submit($dump->getPath())));
|
||||
$crashDumpPath = $this->writeCrashDumpFile($dump);
|
||||
|
||||
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_submit($crashDumpPath)));
|
||||
|
||||
if($this->configGroup->getPropertyBool("auto-report.enabled", true)){
|
||||
$report = true;
|
||||
@ -1444,8 +1569,8 @@ class Server{
|
||||
}
|
||||
@touch($stamp); //update file timestamp
|
||||
|
||||
$plugin = $dump->getData()["plugin"];
|
||||
if(is_string($plugin)){
|
||||
$plugin = $dump->getData()->plugin;
|
||||
if($plugin !== ""){
|
||||
$p = $this->pluginManager->getPlugin($plugin);
|
||||
if($p instanceof Plugin and !($p->getPluginLoader() instanceof PharPluginLoader)){
|
||||
$this->logger->debug("Not sending crashdump due to caused by non-phar plugin");
|
||||
@ -1453,7 +1578,7 @@ class Server{
|
||||
}
|
||||
}
|
||||
|
||||
if($dump->getData()["error"]["type"] === \ParseError::class){
|
||||
if($dump->getData()->error["type"] === \ParseError::class){
|
||||
$report = false;
|
||||
}
|
||||
|
||||
@ -1501,7 +1626,7 @@ class Server{
|
||||
echo "--- Waiting $spacing seconds to throttle automatic restart (you can kill the process safely now) ---" . PHP_EOL;
|
||||
sleep($spacing);
|
||||
}
|
||||
@Process::kill(Process::pid());
|
||||
@Process::kill(Process::pid(), true);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -1527,7 +1652,28 @@ class Server{
|
||||
}
|
||||
}
|
||||
|
||||
public function addOnlinePlayer(Player $player) : void{
|
||||
public function addOnlinePlayer(Player $player) : bool{
|
||||
$ev = new PlayerLoginEvent($player, "Plugin reason");
|
||||
$ev->call();
|
||||
if($ev->isCancelled() or !$player->isConnected()){
|
||||
$player->disconnect($ev->getKickMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$session = $player->getNetworkSession();
|
||||
$position = $player->getPosition();
|
||||
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_player_logIn(
|
||||
TextFormat::AQUA . $player->getName() . TextFormat::WHITE,
|
||||
$session->getIp(),
|
||||
(string) $session->getPort(),
|
||||
(string) $player->getId(),
|
||||
$position->getWorld()->getDisplayName(),
|
||||
(string) round($position->x, 4),
|
||||
(string) round($position->y, 4),
|
||||
(string) round($position->z, 4)
|
||||
)));
|
||||
|
||||
foreach($this->playerList as $p){
|
||||
$p->getNetworkSession()->onPlayerAdded($player);
|
||||
}
|
||||
@ -1537,6 +1683,8 @@ class Server{
|
||||
if($this->sendUsageTicker > 0){
|
||||
$this->uniquePlayers[$rawUUID] = $rawUUID;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function removeOnlinePlayer(Player $player) : void{
|
||||
|
@ -27,6 +27,8 @@ use pocketmine\utils\Config;
|
||||
use function array_key_exists;
|
||||
use function getopt;
|
||||
use function is_bool;
|
||||
use function is_int;
|
||||
use function is_string;
|
||||
use function strtolower;
|
||||
|
||||
final class ServerConfigGroup{
|
||||
@ -110,16 +112,20 @@ final class ServerConfigGroup{
|
||||
}else{
|
||||
$value = $this->serverProperties->exists($variable) ? $this->serverProperties->get($variable) : $defaultValue;
|
||||
}
|
||||
|
||||
if(is_bool($value)){
|
||||
return $value;
|
||||
}
|
||||
switch(strtolower($value)){
|
||||
case "on":
|
||||
case "true":
|
||||
case "1":
|
||||
case "yes":
|
||||
return true;
|
||||
if(is_int($value)){
|
||||
return $value !== 0;
|
||||
}
|
||||
if(is_string($value)){
|
||||
switch(strtolower($value)){
|
||||
case "on":
|
||||
case "true":
|
||||
case "1":
|
||||
case "yes":
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -25,14 +25,15 @@ namespace pocketmine;
|
||||
|
||||
use pocketmine\utils\Git;
|
||||
use pocketmine\utils\VersionString;
|
||||
use function is_array;
|
||||
use function is_int;
|
||||
use function str_repeat;
|
||||
|
||||
final class VersionInfo{
|
||||
public const NAME = "PocketMine-MP";
|
||||
public const BASE_VERSION = "4.0.0-BETA2";
|
||||
public const BASE_VERSION = "4.0.2";
|
||||
public const IS_DEVELOPMENT_BUILD = false;
|
||||
public const BUILD_NUMBER = 0;
|
||||
public const BUILD_CHANNEL = "beta";
|
||||
public const BUILD_CHANNEL = "stable";
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
@ -61,12 +62,29 @@ final class VersionInfo{
|
||||
return self::$gitHash;
|
||||
}
|
||||
|
||||
private static ?int $buildNumber = null;
|
||||
|
||||
public static function BUILD_NUMBER() : int{
|
||||
if(self::$buildNumber === null){
|
||||
self::$buildNumber = 0;
|
||||
if(\Phar::running(true) !== ""){
|
||||
$phar = new \Phar(\Phar::running(false));
|
||||
$meta = $phar->getMetadata();
|
||||
if(is_array($meta) && isset($meta["build"]) && is_int($meta["build"])){
|
||||
self::$buildNumber = $meta["build"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self::$buildNumber;
|
||||
}
|
||||
|
||||
/** @var VersionString|null */
|
||||
private static $fullVersion = null;
|
||||
|
||||
public static function VERSION() : VersionString{
|
||||
if(self::$fullVersion === null){
|
||||
self::$fullVersion = new VersionString(self::BASE_VERSION, self::IS_DEVELOPMENT_BUILD, self::BUILD_NUMBER);
|
||||
self::$fullVersion = new VersionString(self::BASE_VERSION, self::IS_DEVELOPMENT_BUILD, self::BUILD_NUMBER());
|
||||
}
|
||||
return self::$fullVersion;
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ class Bamboo extends Transparent{
|
||||
return 12 + (self::getOffsetSeed($x, 0, $z) % 5);
|
||||
}
|
||||
|
||||
public function getPositionOffset() : ?Vector3{
|
||||
public function getModelPositionOffset() : ?Vector3{
|
||||
$seed = self::getOffsetSeed($this->position->getFloorX(), 0, $this->position->getFloorZ());
|
||||
$retX = (($seed % 12) + 1) / 16;
|
||||
$retZ = ((($seed >> 8) % 12) + 1) / 16;
|
||||
@ -145,12 +145,12 @@ class Bamboo extends Transparent{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($item instanceof Fertilizer){
|
||||
$top = $this->seekToTop();
|
||||
if($top->grow(self::getMaxHeight($top->position->getFloorX(), $top->position->getFloorZ()), mt_rand(1, 2))){
|
||||
if($top->grow(self::getMaxHeight($top->position->getFloorX(), $top->position->getFloorZ()), mt_rand(1, 2), $player)){
|
||||
$item->pop();
|
||||
return true;
|
||||
}
|
||||
}elseif($item instanceof ItemBamboo){
|
||||
if($this->seekToTop()->grow(PHP_INT_MAX, 1)){
|
||||
if($this->seekToTop()->grow(PHP_INT_MAX, 1, $player)){
|
||||
$item->pop();
|
||||
return true;
|
||||
}
|
||||
@ -165,7 +165,7 @@ class Bamboo extends Transparent{
|
||||
}
|
||||
}
|
||||
|
||||
private function grow(int $maxHeight, int $growAmount) : bool{
|
||||
private function grow(int $maxHeight, int $growAmount, ?Player $player) : bool{
|
||||
$world = $this->position->getWorld();
|
||||
if(!$world->getBlock($this->position->up())->canBeReplaced()){
|
||||
return false;
|
||||
@ -212,7 +212,7 @@ class Bamboo extends Transparent{
|
||||
$tx->addBlock($this->position->subtract(0, $idx - $growAmount, 0), $newBlock);
|
||||
}
|
||||
|
||||
$ev = new StructureGrowEvent($this, $tx);
|
||||
$ev = new StructureGrowEvent($this, $tx, $player);
|
||||
$ev->call();
|
||||
if($ev->isCancelled()){
|
||||
return false;
|
||||
@ -229,7 +229,7 @@ class Bamboo extends Transparent{
|
||||
$world = $this->position->getWorld();
|
||||
if($this->ready){
|
||||
$this->ready = false;
|
||||
if($world->getFullLight($this->position) < 9 || !$this->grow(self::getMaxHeight($this->position->getFloorX(), $this->position->getFloorZ()), 1)){
|
||||
if($world->getFullLight($this->position) < 9 || !$this->grow(self::getMaxHeight($this->position->getFloorX(), $this->position->getFloorZ()), 1, null)){
|
||||
$world->setBlock($this->position, $this);
|
||||
}
|
||||
}elseif($world->getBlock($this->position->up())->canBeReplaced()){
|
||||
|
@ -73,7 +73,7 @@ final class BambooSapling extends Flowable{
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($item instanceof Fertilizer || $item instanceof ItemBamboo){
|
||||
if($this->grow()){
|
||||
if($this->grow($player)){
|
||||
$item->pop();
|
||||
return true;
|
||||
}
|
||||
@ -87,7 +87,7 @@ final class BambooSapling extends Flowable{
|
||||
}
|
||||
}
|
||||
|
||||
private function grow() : bool{
|
||||
private function grow(?Player $player) : bool{
|
||||
$world = $this->position->getWorld();
|
||||
if(!$world->getBlock($this->position->up())->canBeReplaced()){
|
||||
return false;
|
||||
@ -98,7 +98,7 @@ final class BambooSapling extends Flowable{
|
||||
$tx->addBlock($this->position, $bamboo)
|
||||
->addBlock($this->position->up(), (clone $bamboo)->setLeafSize(Bamboo::SMALL_LEAVES));
|
||||
|
||||
$ev = new StructureGrowEvent($this, $tx);
|
||||
$ev = new StructureGrowEvent($this, $tx, $player);
|
||||
$ev->call();
|
||||
if($ev->isCancelled()){
|
||||
return false;
|
||||
@ -115,7 +115,7 @@ final class BambooSapling extends Flowable{
|
||||
$world = $this->position->getWorld();
|
||||
if($this->ready){
|
||||
$this->ready = false;
|
||||
if($world->getFullLight($this->position) < 9 || !$this->grow()){
|
||||
if($world->getFullLight($this->position) < 9 || !$this->grow(null)){
|
||||
$world->setBlock($this->position, $this);
|
||||
}
|
||||
}elseif($world->getBlock($this->position->up())->canBeReplaced()){
|
||||
|
@ -37,8 +37,6 @@ use pocketmine\world\BlockTransaction;
|
||||
use pocketmine\world\sound\BellRingSound;
|
||||
|
||||
final class Bell extends Transparent{
|
||||
private const BELL_RINGING_REPEAT_TICKS = 20;
|
||||
|
||||
use HorizontalFacingTrait;
|
||||
|
||||
private BellAttachmentType $attachmentType;
|
||||
|
@ -179,7 +179,7 @@ class Block{
|
||||
* Returns whether the given block has the same type and properties as this block.
|
||||
*/
|
||||
public function isSameState(Block $other) : bool{
|
||||
return $this->isSameType($other) and $this->writeStateToMeta() === $other->writeStateToMeta();
|
||||
return $this->getFullId() === $other->getFullId();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -493,7 +493,7 @@ class Block{
|
||||
return $this->position->getWorld()->getBlock($this->position->getSide($side, $step));
|
||||
}
|
||||
|
||||
throw new \InvalidStateException("Block does not have a valid world");
|
||||
throw new \LogicException("Block does not have a valid world");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -577,7 +577,7 @@ class Block{
|
||||
final public function getCollisionBoxes() : array{
|
||||
if($this->collisionBoxes === null){
|
||||
$this->collisionBoxes = $this->recalculateCollisionBoxes();
|
||||
$extraOffset = $this->getPositionOffset();
|
||||
$extraOffset = $this->getModelPositionOffset();
|
||||
$offset = $extraOffset !== null ? $this->position->addVector($extraOffset) : $this->position;
|
||||
foreach($this->collisionBoxes as $bb){
|
||||
$bb->offset($offset->x, $offset->y, $offset->z);
|
||||
@ -588,10 +588,10 @@ class Block{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an additional fractional vector to shift the block's effective position by based on the current position.
|
||||
* Returns an additional fractional vector to shift the block model's position by based on the current position.
|
||||
* Used to randomize position of things like bamboo canes and tall grass.
|
||||
*/
|
||||
public function getPositionOffset() : ?Vector3{
|
||||
public function getModelPositionOffset() : ?Vector3{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -94,8 +94,7 @@ class Cake extends Transparent implements FoodSource{
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($player !== null){
|
||||
$player->consumeObject($this);
|
||||
return true;
|
||||
return $player->consumeObject($this);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -26,6 +26,7 @@ namespace pocketmine\block;
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\block\utils\HorizontalFacingTrait;
|
||||
use pocketmine\block\utils\TreeType;
|
||||
use pocketmine\event\block\BlockGrowEvent;
|
||||
use pocketmine\item\Fertilizer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\VanillaItems;
|
||||
@ -94,10 +95,7 @@ class CocoaBlock extends Transparent{
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($this->age < 2 and $item instanceof Fertilizer){
|
||||
$this->age++;
|
||||
$this->position->getWorld()->setBlock($this->position, $this);
|
||||
|
||||
if($item instanceof Fertilizer && $this->grow()){
|
||||
$item->pop();
|
||||
|
||||
return true;
|
||||
@ -117,12 +115,25 @@ class CocoaBlock extends Transparent{
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
if($this->age < 2 and mt_rand(1, 5) === 1){
|
||||
$this->age++;
|
||||
$this->position->getWorld()->setBlock($this->position, $this);
|
||||
if(mt_rand(1, 5) === 1){
|
||||
$this->grow();
|
||||
}
|
||||
}
|
||||
|
||||
private function grow() : bool{
|
||||
if($this->age < 2){
|
||||
$block = clone $this;
|
||||
$block->age++;
|
||||
$ev = new BlockGrowEvent($this, $block);
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
VanillaItems::COCOA_BEANS()->setCount($this->age === 2 ? mt_rand(2, 3) : 1)
|
||||
|
@ -23,7 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\crafting\CraftingGrid;
|
||||
use pocketmine\block\inventory\CraftingTableInventory;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
@ -32,7 +32,7 @@ class CraftingTable extends Opaque{
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($player instanceof Player){
|
||||
$player->setCraftingGrid(new CraftingGrid($player, CraftingGrid::SIZE_BIG));
|
||||
$player->setCurrentWindow(new CraftingTableInventory($this->position));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -80,10 +80,9 @@ abstract class Crops extends Flowable{
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
|
||||
$item->pop();
|
||||
}
|
||||
|
||||
$item->pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
30
src/block/FletchingTable.php
Normal file
30
src/block/FletchingTable.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class FletchingTable extends Opaque{
|
||||
public function getFuelTime() : int{
|
||||
return 300;
|
||||
}
|
||||
}
|
@ -23,50 +23,72 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\block\utils\LeverFacing;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Axis;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use pocketmine\world\sound\RedstonePowerOffSound;
|
||||
use pocketmine\world\sound\RedstonePowerOnSound;
|
||||
|
||||
class Lever extends Flowable{
|
||||
protected const BOTTOM = 0;
|
||||
protected const SIDE = 1;
|
||||
protected const TOP = 2;
|
||||
protected LeverFacing $facing;
|
||||
protected bool $activated = false;
|
||||
|
||||
protected int $leverPos = self::BOTTOM;
|
||||
protected int $facing = Facing::NORTH;
|
||||
protected bool $powered = false;
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
|
||||
$this->facing = LeverFacing::UP_AXIS_X();
|
||||
parent::__construct($idInfo, $name, $breakInfo);
|
||||
}
|
||||
|
||||
protected function writeStateToMeta() : int{
|
||||
if($this->leverPos === self::BOTTOM){
|
||||
$rotationMeta = Facing::axis($this->facing) === Axis::Z ? 7 : 0;
|
||||
}elseif($this->leverPos === self::TOP){
|
||||
$rotationMeta = Facing::axis($this->facing) === Axis::Z ? 5 : 6;
|
||||
}else{
|
||||
$rotationMeta = 6 - BlockDataSerializer::writeHorizontalFacing($this->facing);
|
||||
}
|
||||
return $rotationMeta | ($this->powered ? BlockLegacyMetadata::LEVER_FLAG_POWERED : 0);
|
||||
$rotationMeta = match($this->facing->id()){
|
||||
LeverFacing::DOWN_AXIS_X()->id() => 0,
|
||||
LeverFacing::EAST()->id() => 1,
|
||||
LeverFacing::WEST()->id() => 2,
|
||||
LeverFacing::SOUTH()->id() => 3,
|
||||
LeverFacing::NORTH()->id() => 4,
|
||||
LeverFacing::UP_AXIS_Z()->id() => 5,
|
||||
LeverFacing::UP_AXIS_X()->id() => 6,
|
||||
LeverFacing::DOWN_AXIS_Z()->id() => 7,
|
||||
default => throw new AssumptionFailedError(),
|
||||
};
|
||||
return $rotationMeta | ($this->activated ? BlockLegacyMetadata::LEVER_FLAG_POWERED : 0);
|
||||
}
|
||||
|
||||
public function readStateFromData(int $id, int $stateMeta) : void{
|
||||
$rotationMeta = $stateMeta & 0x07;
|
||||
if($rotationMeta === 5 or $rotationMeta === 6){
|
||||
$this->leverPos = self::TOP;
|
||||
$this->facing = $rotationMeta === 5 ? Facing::SOUTH : Facing::EAST;
|
||||
}elseif($rotationMeta === 7 or $rotationMeta === 0){
|
||||
$this->leverPos = self::BOTTOM;
|
||||
$this->facing = $rotationMeta === 7 ? Facing::SOUTH : Facing::EAST;
|
||||
}else{
|
||||
$this->leverPos = self::SIDE;
|
||||
$this->facing = BlockDataSerializer::readHorizontalFacing(6 - $rotationMeta);
|
||||
}
|
||||
$this->facing = match($rotationMeta){
|
||||
0 => LeverFacing::DOWN_AXIS_X(),
|
||||
1 => LeverFacing::EAST(),
|
||||
2 => LeverFacing::WEST(),
|
||||
3 => LeverFacing::SOUTH(),
|
||||
4 => LeverFacing::NORTH(),
|
||||
5 => LeverFacing::UP_AXIS_Z(),
|
||||
6 => LeverFacing::UP_AXIS_X(),
|
||||
7 => LeverFacing::DOWN_AXIS_Z(),
|
||||
default => throw new AssumptionFailedError("0x07 mask should make this impossible"), //phpstan doesn't understand :(
|
||||
};
|
||||
|
||||
$this->powered = ($stateMeta & BlockLegacyMetadata::LEVER_FLAG_POWERED) !== 0;
|
||||
$this->activated = ($stateMeta & BlockLegacyMetadata::LEVER_FLAG_POWERED) !== 0;
|
||||
}
|
||||
|
||||
public function getFacing() : LeverFacing{ return $this->facing; }
|
||||
|
||||
/** @return $this */
|
||||
public function setFacing(LeverFacing $facing) : self{
|
||||
$this->facing = $facing;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isActivated() : bool{ return $this->activated; }
|
||||
|
||||
/** @return $this */
|
||||
public function setActivated(bool $activated) : self{
|
||||
$this->activated = $activated;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStateBitmask() : int{
|
||||
@ -78,39 +100,37 @@ class Lever extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(Facing::axis($face) === Axis::Y){
|
||||
$selectUpDownPos = function(LeverFacing $x, LeverFacing $z) use ($player) : LeverFacing{
|
||||
if($player !== null){
|
||||
$this->facing = Facing::opposite($player->getHorizontalFacing());
|
||||
return Facing::axis($player->getHorizontalFacing()) === Axis::X ? $x : $z;
|
||||
}
|
||||
$this->leverPos = $face === Facing::DOWN ? self::BOTTOM : self::TOP;
|
||||
}else{
|
||||
$this->facing = $face;
|
||||
$this->leverPos = self::SIDE;
|
||||
}
|
||||
return $x;
|
||||
};
|
||||
$this->facing = match($face){
|
||||
Facing::DOWN => $selectUpDownPos(LeverFacing::DOWN_AXIS_X(), LeverFacing::DOWN_AXIS_Z()),
|
||||
Facing::UP => $selectUpDownPos(LeverFacing::UP_AXIS_X(), LeverFacing::UP_AXIS_Z()),
|
||||
Facing::NORTH => LeverFacing::NORTH(),
|
||||
Facing::SOUTH => LeverFacing::SOUTH(),
|
||||
Facing::WEST => LeverFacing::WEST(),
|
||||
Facing::EAST => LeverFacing::EAST(),
|
||||
default => throw new AssumptionFailedError("Bad facing value"),
|
||||
};
|
||||
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->leverPos === self::BOTTOM){
|
||||
$face = Facing::UP;
|
||||
}elseif($this->leverPos === self::TOP){
|
||||
$face = Facing::DOWN;
|
||||
}else{
|
||||
$face = Facing::opposite($this->facing);
|
||||
}
|
||||
|
||||
if(!$this->getSide($face)->isSolid()){
|
||||
if(!$this->getSide(Facing::opposite($this->facing->getFacing()))->isSolid()){
|
||||
$this->position->getWorld()->useBreakOn($this->position);
|
||||
}
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
$this->powered = !$this->powered;
|
||||
$this->activated = !$this->activated;
|
||||
$this->position->getWorld()->setBlock($this->position, $this);
|
||||
$this->position->getWorld()->addSound(
|
||||
$this->position->add(0.5, 0.5, 0.5),
|
||||
$this->powered ? new RedstonePowerOnSound() : new RedstonePowerOffSound()
|
||||
$this->activated ? new RedstonePowerOnSound() : new RedstonePowerOffSound()
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
@ -24,19 +24,17 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\block\utils\MinimumCostFlowCalculator;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\event\block\BlockFormEvent;
|
||||
use pocketmine\event\block\BlockSpreadEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\world\sound\FizzSound;
|
||||
use pocketmine\world\sound\Sound;
|
||||
use pocketmine\world\World;
|
||||
use function array_fill;
|
||||
use function intdiv;
|
||||
use function lcg_value;
|
||||
use function min;
|
||||
|
||||
abstract class Liquid extends Transparent{
|
||||
|
||||
@ -46,13 +44,6 @@ abstract class Liquid extends Transparent{
|
||||
|
||||
protected ?Vector3 $flowVector = null;
|
||||
|
||||
/** @var int[] */
|
||||
private array $flowCostVisited = [];
|
||||
|
||||
private const CAN_FLOW_DOWN = 1;
|
||||
private const CAN_FLOW = 0;
|
||||
private const BLOCKED = -1;
|
||||
|
||||
protected bool $falling = false;
|
||||
protected int $decay = 0; //PC "level" property
|
||||
protected bool $still = false;
|
||||
@ -186,21 +177,17 @@ abstract class Liquid extends Transparent{
|
||||
|
||||
$world = $this->position->getWorld();
|
||||
|
||||
for($j = 0; $j < 4; ++$j){
|
||||
|
||||
foreach(Facing::HORIZONTAL as $j){
|
||||
$x = $this->position->x;
|
||||
$y = $this->position->y;
|
||||
$z = $this->position->z;
|
||||
|
||||
if($j === 0){
|
||||
--$x;
|
||||
}elseif($j === 1){
|
||||
++$x;
|
||||
}elseif($j === 2){
|
||||
--$z;
|
||||
}elseif($j === 3){
|
||||
++$z;
|
||||
}
|
||||
match($j){
|
||||
Facing::WEST => --$x,
|
||||
Facing::EAST => ++$x,
|
||||
Facing::NORTH => --$z,
|
||||
Facing::SOUTH => ++$z
|
||||
};
|
||||
|
||||
$sideBlock = $world->getBlockAt($x, $y, $z);
|
||||
$blockDecay = $this->getEffectiveFlowDecay($sideBlock);
|
||||
@ -231,17 +218,15 @@ abstract class Liquid extends Transparent{
|
||||
$vector = new Vector3($vX, $vY, $vZ);
|
||||
|
||||
if($this->falling){
|
||||
if(
|
||||
!$this->canFlowInto($world->getBlockAt($this->position->x, $this->position->y, $this->position->z - 1)) or
|
||||
!$this->canFlowInto($world->getBlockAt($this->position->x, $this->position->y, $this->position->z + 1)) or
|
||||
!$this->canFlowInto($world->getBlockAt($this->position->x - 1, $this->position->y, $this->position->z)) or
|
||||
!$this->canFlowInto($world->getBlockAt($this->position->x + 1, $this->position->y, $this->position->z)) or
|
||||
!$this->canFlowInto($world->getBlockAt($this->position->x, $this->position->y + 1, $this->position->z - 1)) or
|
||||
!$this->canFlowInto($world->getBlockAt($this->position->x, $this->position->y + 1, $this->position->z + 1)) or
|
||||
!$this->canFlowInto($world->getBlockAt($this->position->x - 1, $this->position->y + 1, $this->position->z)) or
|
||||
!$this->canFlowInto($world->getBlockAt($this->position->x + 1, $this->position->y + 1, $this->position->z))
|
||||
){
|
||||
$vector = $vector->normalize()->add(0, -6, 0);
|
||||
foreach(Facing::HORIZONTAL as $facing){
|
||||
$pos = $this->position->getSide($facing);
|
||||
if(
|
||||
!$this->canFlowInto($world->getBlockAt($pos->x, $pos->y, $pos->z)) ||
|
||||
!$this->canFlowInto($world->getBlockAt($pos->x, $pos->y + 1, $pos->z))
|
||||
){
|
||||
$vector = $vector->normalize()->add(0, -6, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,6 +249,14 @@ abstract class Liquid extends Transparent{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of source blocks of this liquid that must be horizontally adjacent to this block in order for
|
||||
* this block to become a source block itself, or null if the liquid does not exhibit source-forming behaviour.
|
||||
*/
|
||||
public function getMinAdjacentSourcesToFormSource() : ?int{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if(!$this->checkForHarden()){
|
||||
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, $this->tickRate());
|
||||
@ -273,13 +266,15 @@ abstract class Liquid extends Transparent{
|
||||
public function onScheduledUpdate() : void{
|
||||
$multiplier = $this->getFlowDecayPerBlock();
|
||||
|
||||
$world = $this->position->getWorld();
|
||||
|
||||
if(!$this->isSource()){
|
||||
$smallestFlowDecay = -100;
|
||||
$this->adjacentSources = 0;
|
||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->position->getWorld()->getBlockAt($this->position->x, $this->position->y, $this->position->z - 1), $smallestFlowDecay);
|
||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->position->getWorld()->getBlockAt($this->position->x, $this->position->y, $this->position->z + 1), $smallestFlowDecay);
|
||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->position->getWorld()->getBlockAt($this->position->x - 1, $this->position->y, $this->position->z), $smallestFlowDecay);
|
||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->position->getWorld()->getBlockAt($this->position->x + 1, $this->position->y, $this->position->z), $smallestFlowDecay);
|
||||
$smallestFlowDecay = $this->getSmallestFlowDecay($world->getBlockAt($this->position->x, $this->position->y, $this->position->z - 1), $smallestFlowDecay);
|
||||
$smallestFlowDecay = $this->getSmallestFlowDecay($world->getBlockAt($this->position->x, $this->position->y, $this->position->z + 1), $smallestFlowDecay);
|
||||
$smallestFlowDecay = $this->getSmallestFlowDecay($world->getBlockAt($this->position->x - 1, $this->position->y, $this->position->z), $smallestFlowDecay);
|
||||
$smallestFlowDecay = $this->getSmallestFlowDecay($world->getBlockAt($this->position->x + 1, $this->position->y, $this->position->z), $smallestFlowDecay);
|
||||
|
||||
$newDecay = $smallestFlowDecay + $multiplier;
|
||||
$falling = false;
|
||||
@ -288,13 +283,14 @@ abstract class Liquid extends Transparent{
|
||||
$newDecay = -1;
|
||||
}
|
||||
|
||||
if($this->getEffectiveFlowDecay($this->position->getWorld()->getBlockAt($this->position->x, $this->position->y + 1, $this->position->z)) >= 0){
|
||||
if($this->getEffectiveFlowDecay($world->getBlockAt($this->position->x, $this->position->y + 1, $this->position->z)) >= 0){
|
||||
$falling = true;
|
||||
}
|
||||
|
||||
if($this->adjacentSources >= 2 and $this instanceof Water){
|
||||
$bottomBlock = $this->position->getWorld()->getBlockAt($this->position->x, $this->position->y - 1, $this->position->z);
|
||||
if($bottomBlock->isSolid() or ($bottomBlock instanceof Water and $bottomBlock->isSource())){
|
||||
$minAdjacentSources = $this->getMinAdjacentSourcesToFormSource();
|
||||
if($minAdjacentSources !== null && $this->adjacentSources >= $minAdjacentSources){
|
||||
$bottomBlock = $world->getBlockAt($this->position->x, $this->position->y - 1, $this->position->z);
|
||||
if($bottomBlock->isSolid() or ($bottomBlock instanceof Liquid and $bottomBlock->isSameType($this) and $bottomBlock->isSource())){
|
||||
$newDecay = 0;
|
||||
$falling = false;
|
||||
}
|
||||
@ -302,17 +298,17 @@ abstract class Liquid extends Transparent{
|
||||
|
||||
if($falling !== $this->falling or (!$falling and $newDecay !== $this->decay)){
|
||||
if(!$falling and $newDecay < 0){
|
||||
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::AIR());
|
||||
$world->setBlock($this->position, VanillaBlocks::AIR());
|
||||
return;
|
||||
}
|
||||
|
||||
$this->falling = $falling;
|
||||
$this->decay = $falling ? 0 : $newDecay;
|
||||
$this->position->getWorld()->setBlock($this->position, $this); //local block update will cause an update to be scheduled
|
||||
$world->setBlock($this->position, $this); //local block update will cause an update to be scheduled
|
||||
}
|
||||
}
|
||||
|
||||
$bottomBlock = $this->position->getWorld()->getBlockAt($this->position->x, $this->position->y - 1, $this->position->z);
|
||||
$bottomBlock = $world->getBlockAt($this->position->x, $this->position->y - 1, $this->position->z);
|
||||
|
||||
$this->flowIntoBlock($bottomBlock, 0, true);
|
||||
|
||||
@ -324,22 +320,9 @@ abstract class Liquid extends Transparent{
|
||||
}
|
||||
|
||||
if($adjacentDecay < 8){
|
||||
$flags = $this->getOptimalFlowDirections();
|
||||
|
||||
if($flags[0]){
|
||||
$this->flowIntoBlock($this->position->getWorld()->getBlockAt($this->position->x - 1, $this->position->y, $this->position->z), $adjacentDecay, false);
|
||||
}
|
||||
|
||||
if($flags[1]){
|
||||
$this->flowIntoBlock($this->position->getWorld()->getBlockAt($this->position->x + 1, $this->position->y, $this->position->z), $adjacentDecay, false);
|
||||
}
|
||||
|
||||
if($flags[2]){
|
||||
$this->flowIntoBlock($this->position->getWorld()->getBlockAt($this->position->x, $this->position->y, $this->position->z - 1), $adjacentDecay, false);
|
||||
}
|
||||
|
||||
if($flags[3]){
|
||||
$this->flowIntoBlock($this->position->getWorld()->getBlockAt($this->position->x, $this->position->y, $this->position->z + 1), $adjacentDecay, false);
|
||||
$calculator = new MinimumCostFlowCalculator($this->position->getWorld(), $this->getFlowDecayPerBlock(), \Closure::fromCallable([$this, 'canFlowInto']));
|
||||
foreach($calculator->getOptimalFlowDirections($this->position->getFloorX(), $this->position->getFloorY(), $this->position->getFloorZ()) as $facing){
|
||||
$this->flowIntoBlock($world->getBlock($this->position->getSide($facing)), $adjacentDecay, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -365,109 +348,6 @@ abstract class Liquid extends Transparent{
|
||||
}
|
||||
}
|
||||
|
||||
private function calculateFlowCost(int $blockX, int $blockY, int $blockZ, int $accumulatedCost, int $maxCost, int $originOpposite, int $lastOpposite) : int{
|
||||
$cost = 1000;
|
||||
|
||||
for($j = 0; $j < 4; ++$j){
|
||||
if($j === $originOpposite or $j === $lastOpposite){
|
||||
continue;
|
||||
}
|
||||
|
||||
$x = $blockX;
|
||||
$y = $blockY;
|
||||
$z = $blockZ;
|
||||
|
||||
if($j === 0){
|
||||
--$x;
|
||||
}elseif($j === 1){
|
||||
++$x;
|
||||
}elseif($j === 2){
|
||||
--$z;
|
||||
}elseif($j === 3){
|
||||
++$z;
|
||||
}
|
||||
|
||||
if(!isset($this->flowCostVisited[$hash = World::blockHash($x, $y, $z)])){
|
||||
$blockSide = $this->position->getWorld()->getBlockAt($x, $y, $z);
|
||||
if(!$this->canFlowInto($blockSide)){
|
||||
$this->flowCostVisited[$hash] = self::BLOCKED;
|
||||
}elseif($this->position->getWorld()->getBlockAt($x, $y - 1, $z)->canBeFlowedInto()){
|
||||
$this->flowCostVisited[$hash] = self::CAN_FLOW_DOWN;
|
||||
}else{
|
||||
$this->flowCostVisited[$hash] = self::CAN_FLOW;
|
||||
}
|
||||
}
|
||||
|
||||
$status = $this->flowCostVisited[$hash];
|
||||
|
||||
if($status === self::BLOCKED){
|
||||
continue;
|
||||
}elseif($status === self::CAN_FLOW_DOWN){
|
||||
return $accumulatedCost;
|
||||
}
|
||||
|
||||
if($accumulatedCost >= $maxCost){
|
||||
continue;
|
||||
}
|
||||
|
||||
$realCost = $this->calculateFlowCost($x, $y, $z, $accumulatedCost + 1, $maxCost, $originOpposite, $j ^ 0x01);
|
||||
|
||||
if($realCost < $cost){
|
||||
$cost = $realCost;
|
||||
}
|
||||
}
|
||||
|
||||
return $cost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool[]
|
||||
*/
|
||||
private function getOptimalFlowDirections() : array{
|
||||
$flowCost = array_fill(0, 4, 1000);
|
||||
$maxCost = intdiv(4, $this->getFlowDecayPerBlock());
|
||||
for($j = 0; $j < 4; ++$j){
|
||||
$x = $this->position->x;
|
||||
$y = $this->position->y;
|
||||
$z = $this->position->z;
|
||||
|
||||
if($j === 0){
|
||||
--$x;
|
||||
}elseif($j === 1){
|
||||
++$x;
|
||||
}elseif($j === 2){
|
||||
--$z;
|
||||
}elseif($j === 3){
|
||||
++$z;
|
||||
}
|
||||
$block = $this->position->getWorld()->getBlockAt($x, $y, $z);
|
||||
|
||||
if(!$this->canFlowInto($block)){
|
||||
$this->flowCostVisited[World::blockHash($x, $y, $z)] = self::BLOCKED;
|
||||
continue;
|
||||
}elseif($this->position->getWorld()->getBlockAt($x, $y - 1, $z)->canBeFlowedInto()){
|
||||
$this->flowCostVisited[World::blockHash($x, $y, $z)] = self::CAN_FLOW_DOWN;
|
||||
$flowCost[$j] = $maxCost = 0;
|
||||
}elseif($maxCost > 0){
|
||||
$this->flowCostVisited[World::blockHash($x, $y, $z)] = self::CAN_FLOW;
|
||||
$flowCost[$j] = $this->calculateFlowCost($x, $y, $z, 1, $maxCost, $j ^ 0x01, $j ^ 0x01);
|
||||
$maxCost = min($maxCost, $flowCost[$j]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->flowCostVisited = [];
|
||||
|
||||
$minCost = min($flowCost);
|
||||
|
||||
$isOptimalFlowDirection = [];
|
||||
|
||||
for($i = 0; $i < 4; ++$i){
|
||||
$isOptimalFlowDirection[$i] = ($flowCost[$i] === $minCost);
|
||||
}
|
||||
|
||||
return $isOptimalFlowDirection;
|
||||
}
|
||||
|
||||
/** @phpstan-impure */
|
||||
private function getSmallestFlowDecay(Block $block, int $decay) : int{
|
||||
if(!($block instanceof Liquid) or !$block->isSameType($this)){
|
||||
@ -500,6 +380,9 @@ abstract class Liquid extends Transparent{
|
||||
}
|
||||
|
||||
protected function canFlowInto(Block $block) : bool{
|
||||
return $this->position->getWorld()->isInWorld($block->position->x, $block->position->y, $block->position->z) and $block->canBeFlowedInto() and !($block instanceof Liquid and $block->isSource()); //TODO: I think this should only be liquids of the same type
|
||||
return
|
||||
$this->position->getWorld()->isInWorld($block->position->x, $block->position->y, $block->position->z) and
|
||||
$block->canBeFlowedInto() and
|
||||
!($block instanceof Liquid and $block->isSource()); //TODO: I think this should only be liquids of the same type
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
||||
class Podzol extends Opaque{
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
VanillaBlocks::DIRT()->asItem()
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -76,9 +76,7 @@ class Sapling extends Flowable{
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($item instanceof Fertilizer){
|
||||
$this->grow();
|
||||
|
||||
if($item instanceof Fertilizer && $this->grow($player)){
|
||||
$item->pop();
|
||||
|
||||
return true;
|
||||
@ -100,7 +98,7 @@ class Sapling extends Flowable{
|
||||
public function onRandomTick() : void{
|
||||
if($this->position->getWorld()->getFullLightAt($this->position->getFloorX(), $this->position->getFloorY(), $this->position->getFloorZ()) >= 8 and mt_rand(1, 7) === 1){
|
||||
if($this->ready){
|
||||
$this->grow();
|
||||
$this->grow(null);
|
||||
}else{
|
||||
$this->ready = true;
|
||||
$this->position->getWorld()->setBlock($this->position, $this);
|
||||
@ -108,21 +106,20 @@ class Sapling extends Flowable{
|
||||
}
|
||||
}
|
||||
|
||||
private function grow() : void{
|
||||
private function grow(?Player $player) : bool{
|
||||
$random = new Random(mt_rand());
|
||||
$tree = TreeFactory::get($random, $this->treeType);
|
||||
$transaction = $tree?->getBlockTransaction($this->position->getWorld(), $this->position->getFloorX(), $this->position->getFloorY(), $this->position->getFloorZ(), $random);
|
||||
if($transaction === null){
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
$ev = new StructureGrowEvent($this, $transaction);
|
||||
$ev = new StructureGrowEvent($this, $transaction, $player);
|
||||
$ev->call();
|
||||
if($ev->isCancelled()){
|
||||
return;
|
||||
if(!$ev->isCancelled()){
|
||||
return $transaction->apply();
|
||||
}
|
||||
|
||||
$transaction->apply();
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
|
@ -124,8 +124,14 @@ class Skull extends Flowable{
|
||||
* @return AxisAlignedBB[]
|
||||
*/
|
||||
protected function recalculateCollisionBoxes() : array{
|
||||
//TODO: different bounds depending on attached face
|
||||
return [AxisAlignedBB::one()->contract(0.25, 0, 0.25)->trim(Facing::UP, 0.5)];
|
||||
$collisionBox = AxisAlignedBB::one()->contract(0.25, 0, 0.25)->trim(Facing::UP, 0.5);
|
||||
return match($this->facing){
|
||||
Facing::NORTH => [$collisionBox->offset(0, 0.25, 0.25)],
|
||||
Facing::SOUTH => [$collisionBox->offset(0, 0.25, -0.25)],
|
||||
Facing::WEST => [$collisionBox->offset(0.25, 0.25, 0)],
|
||||
Facing::EAST => [$collisionBox->offset(-0.25, 0.25, 0)],
|
||||
default => [$collisionBox]
|
||||
};
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
|
@ -48,7 +48,8 @@ class Sugarcane extends Flowable{
|
||||
return 0b1111;
|
||||
}
|
||||
|
||||
private function grow() : void{
|
||||
private function grow() : bool{
|
||||
$grew = false;
|
||||
for($y = 1; $y < 3; ++$y){
|
||||
if(!$this->position->getWorld()->isInWorld($this->position->x, $this->position->y + $y, $this->position->z)){
|
||||
break;
|
||||
@ -61,12 +62,14 @@ class Sugarcane extends Flowable{
|
||||
break;
|
||||
}
|
||||
$this->position->getWorld()->setBlock($b->position, $ev->getNewState());
|
||||
$grew = true;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->age = 0;
|
||||
$this->position->getWorld()->setBlock($this->position, $this);
|
||||
return $grew;
|
||||
}
|
||||
|
||||
public function getAge() : int{ return $this->age; }
|
||||
@ -82,12 +85,10 @@ class Sugarcane extends Flowable{
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($item instanceof Fertilizer){
|
||||
if(!$this->getSide(Facing::DOWN)->isSameType($this)){
|
||||
$this->grow();
|
||||
if(!$this->getSide(Facing::DOWN)->isSameType($this) && $this->grow()){
|
||||
$item->pop();
|
||||
}
|
||||
|
||||
$item->pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -99,9 +99,9 @@ class SweetBerryBush extends Flowable{
|
||||
|
||||
if(!$ev->isCancelled()){
|
||||
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
|
||||
$item->pop();
|
||||
}
|
||||
|
||||
$item->pop();
|
||||
}elseif(($dropAmount = $this->getBerryDropAmount()) > 0){
|
||||
$this->position->getWorld()->setBlock($this->position, $this->setAge(self::STAGE_BUSH_NO_BERRIES));
|
||||
$this->position->getWorld()->dropItem($this->position, $this->asItem()->setCount($dropAmount));
|
||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\utils\CloningRegistryTrait;
|
||||
use function assert;
|
||||
|
||||
/**
|
||||
* This doc-block is generated automatically, do not modify it manually.
|
||||
@ -300,6 +299,7 @@ use function assert;
|
||||
* @method static Farmland FARMLAND()
|
||||
* @method static TallGrass FERN()
|
||||
* @method static Fire FIRE()
|
||||
* @method static FletchingTable FLETCHING_TABLE()
|
||||
* @method static FlowerPot FLOWER_POT()
|
||||
* @method static FrostedIce FROSTED_ICE()
|
||||
* @method static Furnace FURNACE()
|
||||
@ -580,12 +580,6 @@ final class VanillaBlocks{
|
||||
self::_registryRegister($name, $block);
|
||||
}
|
||||
|
||||
public static function fromString(string $name) : Block{
|
||||
$result = self::_registryFromString($name);
|
||||
assert($result instanceof Block);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Block[]
|
||||
*/
|
||||
@ -866,6 +860,7 @@ final class VanillaBlocks{
|
||||
self::register("farmland", $factory->get(60, 0));
|
||||
self::register("fern", $factory->get(31, 2));
|
||||
self::register("fire", $factory->get(51, 0));
|
||||
self::register("fletching_table", $factory->get(456, 0));
|
||||
self::register("flower_pot", $factory->get(140, 0));
|
||||
self::register("frosted_ice", $factory->get(207, 0));
|
||||
self::register("furnace", $factory->get(61, 2));
|
||||
|
@ -46,6 +46,10 @@ class Water extends Liquid{
|
||||
return 5;
|
||||
}
|
||||
|
||||
public function getMinAdjacentSourcesToFormSource() : ?int{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function onEntityInside(Entity $entity) : bool{
|
||||
$entity->resetFallDistance();
|
||||
if($entity->isOnFire()){
|
||||
|
@ -24,10 +24,10 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block\inventory;
|
||||
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\inventory\TemporaryInventory;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
class AnvilInventory extends SimpleInventory implements BlockInventory{
|
||||
class AnvilInventory extends SimpleInventory implements BlockInventory, TemporaryInventory{
|
||||
use BlockInventoryTrait;
|
||||
|
||||
public const SLOT_INPUT = 0;
|
||||
@ -37,13 +37,4 @@ class AnvilInventory extends SimpleInventory implements BlockInventory{
|
||||
$this->holder = $holder;
|
||||
parent::__construct(2);
|
||||
}
|
||||
|
||||
public function onClose(Player $who) : void{
|
||||
parent::onClose($who);
|
||||
|
||||
foreach($this->getContents() as $item){
|
||||
$who->dropItem($item);
|
||||
}
|
||||
$this->clearAll();
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block\inventory;
|
||||
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\network\mcpe\protocol\BlockEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\BlockPosition;
|
||||
use pocketmine\world\Position;
|
||||
use pocketmine\world\sound\ChestCloseSound;
|
||||
use pocketmine\world\sound\ChestOpenSound;
|
||||
@ -50,6 +51,6 @@ class ChestInventory extends SimpleInventory implements BlockInventory{
|
||||
$holder = $this->getHolder();
|
||||
|
||||
//event ID is always 1 for a chest
|
||||
$holder->getWorld()->broadcastPacketToViewers($holder, BlockEventPacket::create(1, $isOpen ? 1 : 0, $holder->asVector3()));
|
||||
$holder->getWorld()->broadcastPacketToViewers($holder, BlockEventPacket::create(BlockPosition::fromVector3($holder), 1, $isOpen ? 1 : 0));
|
||||
}
|
||||
}
|
||||
|
37
src/block/inventory/CraftingTableInventory.php
Normal file
37
src/block/inventory/CraftingTableInventory.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
|
||||
use pocketmine\crafting\CraftingGrid;
|
||||
use pocketmine\inventory\TemporaryInventory;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
final class CraftingTableInventory extends CraftingGrid implements BlockInventory, TemporaryInventory{
|
||||
use BlockInventoryTrait;
|
||||
|
||||
public function __construct(Position $holder){
|
||||
$this->holder = $holder;
|
||||
parent::__construct(CraftingGrid::SIZE_BIG);
|
||||
}
|
||||
}
|
@ -24,10 +24,10 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block\inventory;
|
||||
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\inventory\TemporaryInventory;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
class EnchantInventory extends SimpleInventory implements BlockInventory{
|
||||
class EnchantInventory extends SimpleInventory implements BlockInventory, TemporaryInventory{
|
||||
use BlockInventoryTrait;
|
||||
|
||||
public const SLOT_INPUT = 0;
|
||||
@ -37,13 +37,4 @@ class EnchantInventory extends SimpleInventory implements BlockInventory{
|
||||
$this->holder = $holder;
|
||||
parent::__construct(2);
|
||||
}
|
||||
|
||||
public function onClose(Player $who) : void{
|
||||
parent::onClose($who);
|
||||
|
||||
foreach($this->getContents() as $item){
|
||||
$who->dropItem($item);
|
||||
}
|
||||
$this->clearAll();
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ use pocketmine\inventory\DelegateInventory;
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\inventory\PlayerEnderInventory;
|
||||
use pocketmine\network\mcpe\protocol\BlockEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\BlockPosition;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\Position;
|
||||
use pocketmine\world\sound\EnderChestCloseSound;
|
||||
@ -74,7 +75,7 @@ class EnderChestInventory extends DelegateInventory implements BlockInventory{
|
||||
$holder = $this->getHolder();
|
||||
|
||||
//event ID is always 1 for a chest
|
||||
$holder->getWorld()->broadcastPacketToViewers($holder, BlockEventPacket::create(1, $isOpen ? 1 : 0, $holder->asVector3()));
|
||||
$holder->getWorld()->broadcastPacketToViewers($holder, BlockEventPacket::create(BlockPosition::fromVector3($holder), 1, $isOpen ? 1 : 0));
|
||||
}
|
||||
|
||||
public function onClose(Player $who) : void{
|
||||
|
@ -24,10 +24,10 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block\inventory;
|
||||
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\inventory\TemporaryInventory;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
final class LoomInventory extends SimpleInventory implements BlockInventory{
|
||||
final class LoomInventory extends SimpleInventory implements BlockInventory, TemporaryInventory{
|
||||
use BlockInventoryTrait;
|
||||
|
||||
public const SLOT_BANNER = 0;
|
||||
@ -38,13 +38,4 @@ final class LoomInventory extends SimpleInventory implements BlockInventory{
|
||||
$this->holder = $holder;
|
||||
parent::__construct($size);
|
||||
}
|
||||
|
||||
public function onClose(Player $who) : void{
|
||||
parent::onClose($who);
|
||||
|
||||
foreach($this->getContents() as $item){
|
||||
$who->dropItem($item);
|
||||
}
|
||||
$this->clearAll();
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\block\BlockLegacyIds;
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\network\mcpe\protocol\BlockEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\BlockPosition;
|
||||
use pocketmine\world\Position;
|
||||
use pocketmine\world\sound\ShulkerBoxCloseSound;
|
||||
use pocketmine\world\sound\ShulkerBoxOpenSound;
|
||||
@ -59,6 +60,6 @@ class ShulkerBoxInventory extends SimpleInventory implements BlockInventory{
|
||||
$holder = $this->getHolder();
|
||||
|
||||
//event ID is always 1 for a chest
|
||||
$holder->getWorld()->broadcastPacketToViewers($holder, BlockEventPacket::create(1, $isOpen ? 1 : 0, $holder->asVector3()));
|
||||
$holder->getWorld()->broadcastPacketToViewers($holder, BlockEventPacket::create(BlockPosition::fromVector3($holder), 1, $isOpen ? 1 : 0));
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\block\utils\BlockDataSerializer;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\BlockPosition;
|
||||
use pocketmine\network\mcpe\protocol\types\CacheableNbt;
|
||||
|
||||
final class Bell extends Spawnable{
|
||||
@ -81,6 +82,6 @@ final class Bell extends Spawnable{
|
||||
$nbt->setByte(self::TAG_RINGING, 1);
|
||||
$nbt->setInt(self::TAG_DIRECTION, BlockDataSerializer::writeLegacyHorizontalFacing($bellHitFace));
|
||||
$nbt->setInt(self::TAG_TICKS, 0);
|
||||
return BlockActorDataPacket::create($this->position->getFloorX(), $this->position->getFloorY(), $this->position->getFloorZ(), new CacheableNbt($nbt));
|
||||
return BlockActorDataPacket::create(BlockPosition::fromVector3($this->position), new CacheableNbt($nbt));
|
||||
}
|
||||
}
|
||||
|
@ -82,6 +82,10 @@ abstract class Furnace extends Spawnable implements Container, Nameable{
|
||||
|
||||
$this->loadName($nbt);
|
||||
$this->loadItems($nbt);
|
||||
|
||||
if($this->remainingFuelTime > 0){
|
||||
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, 1);
|
||||
}
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
|
@ -23,8 +23,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\tile;
|
||||
|
||||
use pocketmine\data\SavedDataLoadingException;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\NbtDataException;
|
||||
use pocketmine\nbt\NbtException;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\utils\SingletonTrait;
|
||||
use pocketmine\utils\Utils;
|
||||
@ -112,21 +113,25 @@ final class TileFactory{
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @throws NbtDataException
|
||||
* @throws SavedDataLoadingException
|
||||
*/
|
||||
public function createFromData(World $world, CompoundTag $nbt) : ?Tile{
|
||||
$type = $nbt->getString(Tile::TAG_ID, "");
|
||||
if(!isset($this->knownTiles[$type])){
|
||||
return null;
|
||||
try{
|
||||
$type = $nbt->getString(Tile::TAG_ID, "");
|
||||
if(!isset($this->knownTiles[$type])){
|
||||
return null;
|
||||
}
|
||||
$class = $this->knownTiles[$type];
|
||||
assert(is_a($class, Tile::class, true));
|
||||
/**
|
||||
* @var Tile $tile
|
||||
* @see Tile::__construct()
|
||||
*/
|
||||
$tile = new $class($world, new Vector3($nbt->getInt(Tile::TAG_X), $nbt->getInt(Tile::TAG_Y), $nbt->getInt(Tile::TAG_Z)));
|
||||
$tile->readSaveData($nbt);
|
||||
}catch(NbtException $e){
|
||||
throw new SavedDataLoadingException($e->getMessage(), 0, $e);
|
||||
}
|
||||
$class = $this->knownTiles[$type];
|
||||
assert(is_a($class, Tile::class, true));
|
||||
/**
|
||||
* @var Tile $tile
|
||||
* @see Tile::__construct()
|
||||
*/
|
||||
$tile = new $class($world, new Vector3($nbt->getInt(Tile::TAG_X), $nbt->getInt(Tile::TAG_Y), $nbt->getInt(Tile::TAG_Z)));
|
||||
$tile->readSaveData($nbt);
|
||||
|
||||
return $tile;
|
||||
}
|
||||
|
67
src/block/utils/LeverFacing.php
Normal file
67
src/block/utils/LeverFacing.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\utils;
|
||||
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\utils\EnumTrait;
|
||||
|
||||
/**
|
||||
* This doc-block is generated automatically, do not modify it manually.
|
||||
* This must be regenerated whenever registry members are added, removed or changed.
|
||||
* @see build/generate-registry-annotations.php
|
||||
* @generate-registry-docblock
|
||||
*
|
||||
* @method static LeverFacing DOWN_AXIS_X()
|
||||
* @method static LeverFacing DOWN_AXIS_Z()
|
||||
* @method static LeverFacing EAST()
|
||||
* @method static LeverFacing NORTH()
|
||||
* @method static LeverFacing SOUTH()
|
||||
* @method static LeverFacing UP_AXIS_X()
|
||||
* @method static LeverFacing UP_AXIS_Z()
|
||||
* @method static LeverFacing WEST()
|
||||
*/
|
||||
final class LeverFacing{
|
||||
use EnumTrait {
|
||||
__construct as Enum___construct;
|
||||
}
|
||||
|
||||
protected static function setup() : void{
|
||||
self::registerAll(
|
||||
new self("up_axis_x", Facing::UP),
|
||||
new self("up_axis_z", Facing::UP),
|
||||
new self("down_axis_x", Facing::DOWN),
|
||||
new self("down_axis_z", Facing::DOWN),
|
||||
new self("north", Facing::NORTH),
|
||||
new self("east", Facing::EAST),
|
||||
new self("south", Facing::SOUTH),
|
||||
new self("west", Facing::WEST),
|
||||
);
|
||||
}
|
||||
|
||||
private function __construct(string $enumName, private int $facing){
|
||||
$this->Enum___construct($enumName);
|
||||
}
|
||||
|
||||
public function getFacing() : int{ return $this->facing; }
|
||||
}
|
154
src/block/utils/MinimumCostFlowCalculator.php
Normal file
154
src/block/utils/MinimumCostFlowCalculator.php
Normal file
@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\utils;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\world\World;
|
||||
use function array_fill_keys;
|
||||
use function intdiv;
|
||||
use function min;
|
||||
|
||||
/**
|
||||
* Calculates the path(s) of least resistance for liquid flow.
|
||||
*/
|
||||
final class MinimumCostFlowCalculator{
|
||||
|
||||
private const CAN_FLOW_DOWN = 1;
|
||||
private const CAN_FLOW = 0;
|
||||
private const BLOCKED = -1;
|
||||
|
||||
/** @var int[] */
|
||||
private array $flowCostVisited = [];
|
||||
|
||||
/**
|
||||
* @phpstan-param \Closure(Block) : bool $canFlowInto
|
||||
*/
|
||||
public function __construct(
|
||||
private World $world,
|
||||
private int $flowDecayPerBlock,
|
||||
private \Closure $canFlowInto
|
||||
){}
|
||||
|
||||
private function calculateFlowCost(int $blockX, int $blockY, int $blockZ, int $accumulatedCost, int $maxCost, int $originOpposite, int $lastOpposite) : int{
|
||||
$cost = 1000;
|
||||
|
||||
foreach(Facing::HORIZONTAL as $j){
|
||||
if($j === $originOpposite or $j === $lastOpposite){
|
||||
continue;
|
||||
}
|
||||
|
||||
$x = $blockX;
|
||||
$y = $blockY;
|
||||
$z = $blockZ;
|
||||
|
||||
match($j){
|
||||
Facing::WEST => --$x,
|
||||
Facing::EAST => ++$x,
|
||||
Facing::NORTH => --$z,
|
||||
Facing::SOUTH => ++$z
|
||||
};
|
||||
|
||||
if(!isset($this->flowCostVisited[$hash = World::blockHash($x, $y, $z)])){
|
||||
if(!$this->world->isInWorld($x, $y, $z) || !$this->canFlowInto($this->world->getBlockAt($x, $y, $z))){
|
||||
$this->flowCostVisited[$hash] = self::BLOCKED;
|
||||
}elseif($this->world->getBlockAt($x, $y - 1, $z)->canBeFlowedInto()){
|
||||
$this->flowCostVisited[$hash] = self::CAN_FLOW_DOWN;
|
||||
}else{
|
||||
$this->flowCostVisited[$hash] = self::CAN_FLOW;
|
||||
}
|
||||
}
|
||||
|
||||
$status = $this->flowCostVisited[$hash];
|
||||
|
||||
if($status === self::BLOCKED){
|
||||
continue;
|
||||
}elseif($status === self::CAN_FLOW_DOWN){
|
||||
return $accumulatedCost;
|
||||
}
|
||||
|
||||
if($accumulatedCost >= $maxCost){
|
||||
continue;
|
||||
}
|
||||
|
||||
$realCost = $this->calculateFlowCost($x, $y, $z, $accumulatedCost + 1, $maxCost, $originOpposite, Facing::opposite($j));
|
||||
|
||||
if($realCost < $cost){
|
||||
$cost = $realCost;
|
||||
}
|
||||
}
|
||||
|
||||
return $cost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
*/
|
||||
public function getOptimalFlowDirections(int $originX, int $originY, int $originZ) : array{
|
||||
$flowCost = array_fill_keys(Facing::HORIZONTAL, 1000);
|
||||
$maxCost = intdiv(4, $this->flowDecayPerBlock);
|
||||
foreach(Facing::HORIZONTAL as $j){
|
||||
$x = $originX;
|
||||
$y = $originY;
|
||||
$z = $originZ;
|
||||
|
||||
match($j){
|
||||
Facing::WEST => --$x,
|
||||
Facing::EAST => ++$x,
|
||||
Facing::NORTH => --$z,
|
||||
Facing::SOUTH => ++$z
|
||||
};
|
||||
|
||||
if(!$this->world->isInWorld($x, $y, $z) || !$this->canFlowInto($this->world->getBlockAt($x, $y, $z))){
|
||||
$this->flowCostVisited[World::blockHash($x, $y, $z)] = self::BLOCKED;
|
||||
}elseif($this->world->getBlockAt($x, $y - 1, $z)->canBeFlowedInto()){
|
||||
$this->flowCostVisited[World::blockHash($x, $y, $z)] = self::CAN_FLOW_DOWN;
|
||||
$flowCost[$j] = $maxCost = 0;
|
||||
}elseif($maxCost > 0){
|
||||
$this->flowCostVisited[World::blockHash($x, $y, $z)] = self::CAN_FLOW;
|
||||
$opposite = Facing::opposite($j);
|
||||
$flowCost[$j] = $this->calculateFlowCost($x, $y, $z, 1, $maxCost, $opposite, $opposite);
|
||||
$maxCost = min($maxCost, $flowCost[$j]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->flowCostVisited = [];
|
||||
|
||||
$minCost = min($flowCost);
|
||||
|
||||
$isOptimalFlowDirection = [];
|
||||
|
||||
foreach($flowCost as $facing => $cost){
|
||||
if($cost === $minCost){
|
||||
$isOptimalFlowDirection[] = $facing;
|
||||
}
|
||||
}
|
||||
|
||||
return $isOptimalFlowDirection;
|
||||
}
|
||||
|
||||
private function canFlowInto(Block $block) : bool{
|
||||
return ($this->canFlowInto)($block);
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ namespace pocketmine\block\utils;
|
||||
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\Translatable;
|
||||
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\LevelSoundEvent;
|
||||
use pocketmine\utils\EnumTrait;
|
||||
|
||||
/**
|
||||
@ -54,18 +54,18 @@ final class RecordType{
|
||||
|
||||
protected static function setup() : void{
|
||||
self::registerAll(
|
||||
new RecordType("disk_13", "C418 - 13", LevelSoundEventPacket::SOUND_RECORD_13, KnownTranslationFactory::item_record_13_desc()),
|
||||
new RecordType("disk_cat", "C418 - cat", LevelSoundEventPacket::SOUND_RECORD_CAT, KnownTranslationFactory::item_record_cat_desc()),
|
||||
new RecordType("disk_blocks", "C418 - blocks", LevelSoundEventPacket::SOUND_RECORD_BLOCKS, KnownTranslationFactory::item_record_blocks_desc()),
|
||||
new RecordType("disk_chirp", "C418 - chirp", LevelSoundEventPacket::SOUND_RECORD_CHIRP, KnownTranslationFactory::item_record_chirp_desc()),
|
||||
new RecordType("disk_far", "C418 - far", LevelSoundEventPacket::SOUND_RECORD_FAR, KnownTranslationFactory::item_record_far_desc()),
|
||||
new RecordType("disk_mall", "C418 - mall", LevelSoundEventPacket::SOUND_RECORD_MALL, KnownTranslationFactory::item_record_mall_desc()),
|
||||
new RecordType("disk_mellohi", "C418 - mellohi", LevelSoundEventPacket::SOUND_RECORD_MELLOHI, KnownTranslationFactory::item_record_mellohi_desc()),
|
||||
new RecordType("disk_stal", "C418 - stal", LevelSoundEventPacket::SOUND_RECORD_STAL, KnownTranslationFactory::item_record_stal_desc()),
|
||||
new RecordType("disk_strad", "C418 - strad", LevelSoundEventPacket::SOUND_RECORD_STRAD, KnownTranslationFactory::item_record_strad_desc()),
|
||||
new RecordType("disk_ward", "C418 - ward", LevelSoundEventPacket::SOUND_RECORD_WARD, KnownTranslationFactory::item_record_ward_desc()),
|
||||
new RecordType("disk_11", "C418 - 11", LevelSoundEventPacket::SOUND_RECORD_11, KnownTranslationFactory::item_record_11_desc()),
|
||||
new RecordType("disk_wait", "C418 - wait", LevelSoundEventPacket::SOUND_RECORD_WAIT, KnownTranslationFactory::item_record_wait_desc())
|
||||
new RecordType("disk_13", "C418 - 13", LevelSoundEvent::RECORD_13, KnownTranslationFactory::item_record_13_desc()),
|
||||
new RecordType("disk_cat", "C418 - cat", LevelSoundEvent::RECORD_CAT, KnownTranslationFactory::item_record_cat_desc()),
|
||||
new RecordType("disk_blocks", "C418 - blocks", LevelSoundEvent::RECORD_BLOCKS, KnownTranslationFactory::item_record_blocks_desc()),
|
||||
new RecordType("disk_chirp", "C418 - chirp", LevelSoundEvent::RECORD_CHIRP, KnownTranslationFactory::item_record_chirp_desc()),
|
||||
new RecordType("disk_far", "C418 - far", LevelSoundEvent::RECORD_FAR, KnownTranslationFactory::item_record_far_desc()),
|
||||
new RecordType("disk_mall", "C418 - mall", LevelSoundEvent::RECORD_MALL, KnownTranslationFactory::item_record_mall_desc()),
|
||||
new RecordType("disk_mellohi", "C418 - mellohi", LevelSoundEvent::RECORD_MELLOHI, KnownTranslationFactory::item_record_mellohi_desc()),
|
||||
new RecordType("disk_stal", "C418 - stal", LevelSoundEvent::RECORD_STAL, KnownTranslationFactory::item_record_stal_desc()),
|
||||
new RecordType("disk_strad", "C418 - strad", LevelSoundEvent::RECORD_STRAD, KnownTranslationFactory::item_record_strad_desc()),
|
||||
new RecordType("disk_ward", "C418 - ward", LevelSoundEvent::RECORD_WARD, KnownTranslationFactory::item_record_ward_desc()),
|
||||
new RecordType("disk_11", "C418 - 11", LevelSoundEvent::RECORD_11, KnownTranslationFactory::item_record_11_desc()),
|
||||
new RecordType("disk_wait", "C418 - wait", LevelSoundEvent::RECORD_WAIT, KnownTranslationFactory::item_record_wait_desc())
|
||||
//TODO: Lena Raine - Pigstep
|
||||
);
|
||||
}
|
||||
|
@ -58,10 +58,10 @@ abstract class Command{
|
||||
/** @var CommandMap|null */
|
||||
private $commandMap = null;
|
||||
|
||||
/** @var string */
|
||||
/** @var Translatable|string */
|
||||
protected $description = "";
|
||||
|
||||
/** @var string */
|
||||
/** @var Translatable|string */
|
||||
protected $usageMessage;
|
||||
|
||||
/** @var string|null */
|
||||
@ -76,7 +76,7 @@ abstract class Command{
|
||||
/**
|
||||
* @param string[] $aliases
|
||||
*/
|
||||
public function __construct(string $name, string $description = "", ?string $usageMessage = null, array $aliases = []){
|
||||
public function __construct(string $name, Translatable|string $description = "", Translatable|string|null $usageMessage = null, array $aliases = []){
|
||||
$this->name = $name;
|
||||
$this->setLabel($name);
|
||||
$this->setDescription($description);
|
||||
@ -117,7 +117,7 @@ abstract class Command{
|
||||
}
|
||||
|
||||
if($this->permissionMessage === null){
|
||||
$target->sendMessage(KnownTranslationFactory::commands_generic_permission()->prefix(TextFormat::RED));
|
||||
$target->sendMessage(KnownTranslationFactory::pocketmine_command_error_permission($this->name)->prefix(TextFormat::RED));
|
||||
}elseif($this->permissionMessage !== ""){
|
||||
$target->sendMessage(str_replace("<permission>", $permission ?? $this->permission, $this->permissionMessage));
|
||||
}
|
||||
@ -200,11 +200,11 @@ abstract class Command{
|
||||
return $this->permissionMessage;
|
||||
}
|
||||
|
||||
public function getDescription() : string{
|
||||
public function getDescription() : Translatable|string{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function getUsage() : string{
|
||||
public function getUsage() : Translatable|string{
|
||||
return $this->usageMessage;
|
||||
}
|
||||
|
||||
@ -218,7 +218,7 @@ abstract class Command{
|
||||
}
|
||||
}
|
||||
|
||||
public function setDescription(string $description) : void{
|
||||
public function setDescription(Translatable|string $description) : void{
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
@ -226,7 +226,7 @@ abstract class Command{
|
||||
$this->permissionMessage = $permissionMessage;
|
||||
}
|
||||
|
||||
public function setUsage(string $usage) : void{
|
||||
public function setUsage(Translatable|string $usage) : void{
|
||||
$this->usageMessage = $usage;
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,7 @@ use pocketmine\command\defaults\WhitelistCommand;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function explode;
|
||||
@ -205,31 +206,28 @@ class SimpleCommandMap implements CommandMap{
|
||||
foreach($matches[0] as $k => $_){
|
||||
for($i = 1; $i <= 2; ++$i){
|
||||
if($matches[$i][$k] !== ""){
|
||||
$args[$k] = stripslashes($matches[$i][$k]);
|
||||
$args[$k] = $i === 1 ? stripslashes($matches[$i][$k]) : $matches[$i][$k];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$sentCommandLabel = array_shift($args);
|
||||
if($sentCommandLabel === null){
|
||||
return false;
|
||||
}
|
||||
$target = $this->getCommand($sentCommandLabel);
|
||||
if($target === null){
|
||||
return false;
|
||||
if($sentCommandLabel !== null && ($target = $this->getCommand($sentCommandLabel)) !== null){
|
||||
$target->timings->startTiming();
|
||||
|
||||
try{
|
||||
$target->execute($sender, $sentCommandLabel, $args);
|
||||
}catch(InvalidCommandSyntaxException $e){
|
||||
$sender->sendMessage($sender->getLanguage()->translate(KnownTranslationFactory::commands_generic_usage($target->getUsage())));
|
||||
}finally{
|
||||
$target->timings->stopTiming();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
$target->timings->startTiming();
|
||||
|
||||
try{
|
||||
$target->execute($sender, $sentCommandLabel, $args);
|
||||
}catch(InvalidCommandSyntaxException $e){
|
||||
$sender->sendMessage($sender->getLanguage()->translate(KnownTranslationFactory::commands_generic_usage($sender->getLanguage()->translateString($target->getUsage()))));
|
||||
}finally{
|
||||
$target->timings->stopTiming();
|
||||
}
|
||||
|
||||
return true;
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_notFound($sentCommandLabel ?? "", "/help")->prefix(TextFormat::RED));
|
||||
return false;
|
||||
}
|
||||
|
||||
public function clearCommands() : void{
|
||||
|
@ -27,7 +27,6 @@ use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use function array_shift;
|
||||
@ -39,8 +38,8 @@ class BanCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_BAN_PLAYER_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_BAN_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_ban_player_description(),
|
||||
KnownTranslationFactory::commands_ban_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_BAN_PLAYER);
|
||||
}
|
||||
|
@ -27,21 +27,20 @@ use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function implode;
|
||||
use function preg_match;
|
||||
use function inet_pton;
|
||||
|
||||
class BanIpCommand extends VanillaCommand{
|
||||
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_BAN_IP_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_BANIP_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_ban_ip_description(),
|
||||
KnownTranslationFactory::commands_banip_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_BAN_IP);
|
||||
}
|
||||
@ -58,7 +57,7 @@ class BanIpCommand extends VanillaCommand{
|
||||
$value = array_shift($args);
|
||||
$reason = implode(" ", $args);
|
||||
|
||||
if(preg_match("/^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$/", $value)){
|
||||
if(inet_pton($value) !== false){
|
||||
$this->processIPBan($value, $sender, $reason);
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_banip_success($value));
|
||||
|
@ -26,7 +26,6 @@ namespace pocketmine\command\defaults;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\BanEntry;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use function array_map;
|
||||
@ -41,8 +40,8 @@ class BanListCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_BANLIST_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_BANLIST_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_banlist_description(),
|
||||
KnownTranslationFactory::commands_banlist_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_BAN_LIST);
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ use pocketmine\item\LegacyStringToItemParser;
|
||||
use pocketmine\item\LegacyStringToItemParserException;
|
||||
use pocketmine\item\StringToItemParser;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
@ -43,8 +42,8 @@ class ClearCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_CLEAR_DESCRIPTION,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_CLEAR_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_clear_description(),
|
||||
KnownTranslationFactory::pocketmine_command_clear_usage()
|
||||
);
|
||||
$this->setPermission(implode(";", [DefaultPermissionNames::COMMAND_CLEAR_SELF, DefaultPermissionNames::COMMAND_CLEAR_OTHER]));
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\data\java\GameModeIdMap;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\GameMode;
|
||||
use function count;
|
||||
@ -37,8 +36,8 @@ class DefaultGamemodeCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_DEFAULTGAMEMODE_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_DEFAULTGAMEMODE_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_defaultgamemode_description(),
|
||||
KnownTranslationFactory::commands_defaultgamemode_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_DEFAULTGAMEMODE);
|
||||
}
|
||||
@ -54,7 +53,7 @@ class DefaultGamemodeCommand extends VanillaCommand{
|
||||
|
||||
$gameMode = GameMode::fromString($args[0]);
|
||||
if($gameMode === null){
|
||||
$sender->sendMessage("Unknown game mode");
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_gamemode_unknown($args[0]));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,6 @@ use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
@ -39,8 +38,8 @@ class DeopCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_DEOP_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_DEOP_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_deop_description(),
|
||||
KnownTranslationFactory::commands_deop_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_OP_TAKE);
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\world\World;
|
||||
use function count;
|
||||
@ -37,8 +36,8 @@ class DifficultyCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_DIFFICULTY_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_DIFFICULTY_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_difficulty_description(),
|
||||
KnownTranslationFactory::commands_difficulty_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_DIFFICULTY);
|
||||
}
|
||||
|
@ -26,9 +26,8 @@ namespace pocketmine\command\defaults;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\entity\effect\EffectInstance;
|
||||
use pocketmine\entity\effect\VanillaEffects;
|
||||
use pocketmine\entity\effect\StringToEffectParser;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\utils\Limits;
|
||||
use pocketmine\utils\TextFormat;
|
||||
@ -40,8 +39,8 @@ class EffectCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_EFFECT_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_EFFECT_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_effect_description(),
|
||||
KnownTranslationFactory::commands_effect_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_EFFECT);
|
||||
}
|
||||
@ -70,9 +69,8 @@ class EffectCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
try{
|
||||
$effect = VanillaEffects::fromString($args[1]);
|
||||
}catch(\InvalidArgumentException $e){
|
||||
$effect = StringToEffectParser::getInstance()->parse($args[1]);
|
||||
if($effect === null){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_effect_notFound($args[1])->prefix(TextFormat::RED));
|
||||
return true;
|
||||
}
|
||||
|
@ -26,9 +26,8 @@ namespace pocketmine\command\defaults;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\item\enchantment\EnchantmentInstance;
|
||||
use pocketmine\item\enchantment\VanillaEnchantments;
|
||||
use pocketmine\item\enchantment\StringToEnchantmentParser;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
@ -38,8 +37,8 @@ class EnchantCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_ENCHANT_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_ENCHANT_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_enchant_description(),
|
||||
KnownTranslationFactory::commands_enchant_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_ENCHANT);
|
||||
}
|
||||
@ -67,9 +66,8 @@ class EnchantCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
try{
|
||||
$enchantment = VanillaEnchantments::fromString($args[1]);
|
||||
}catch(\InvalidArgumentException $e){
|
||||
$enchantment = StringToEnchantmentParser::getInstance()->parse($args[1]);
|
||||
if($enchantment === null){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_enchant_notFound($args[1]));
|
||||
return true;
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\GameMode;
|
||||
use pocketmine\player\Player;
|
||||
@ -39,8 +38,8 @@ class GamemodeCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_GAMEMODE_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_GAMEMODE_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_gamemode_description(),
|
||||
KnownTranslationFactory::commands_gamemode_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_GAMEMODE);
|
||||
}
|
||||
@ -56,7 +55,7 @@ class GamemodeCommand extends VanillaCommand{
|
||||
|
||||
$gameMode = GameMode::fromString($args[0]);
|
||||
if($gameMode === null){
|
||||
$sender->sendMessage("Unknown game mode");
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_gamemode_unknown($args[0]));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -75,7 +74,7 @@ class GamemodeCommand extends VanillaCommand{
|
||||
|
||||
$target->setGamemode($gameMode);
|
||||
if(!$gameMode->equals($target->getGamemode())){
|
||||
$sender->sendMessage("Game mode change for " . $target->getName() . " failed!");
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_gamemode_failure($target->getName()));
|
||||
}else{
|
||||
if($target === $sender){
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_gamemode_success_self($gameMode->getTranslatableName()));
|
||||
|
@ -25,7 +25,6 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
@ -38,8 +37,7 @@ class GarbageCollectorCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_GC_DESCRIPTION,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_GC_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_gc_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_GC);
|
||||
}
|
||||
@ -70,7 +68,7 @@ class GarbageCollectorCommand extends VanillaCommand{
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_gc_entities(TextFormat::RED . number_format($entitiesCollected))->prefix(TextFormat::GOLD));
|
||||
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_gc_cycles(TextFormat::RED . number_format($cyclesCollected))->prefix(TextFormat::GOLD));
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_gc_memoryFreed(TextFormat::RED . number_format(round((($memory - memory_get_usage()) / 1024) / 1024, 2), 2) . " MB")->prefix(TextFormat::GOLD));
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_gc_memoryFreed(TextFormat::RED . number_format(round((($memory - memory_get_usage()) / 1024) / 1024, 2), 2))->prefix(TextFormat::GOLD));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -30,9 +30,9 @@ use pocketmine\item\LegacyStringToItemParser;
|
||||
use pocketmine\item\LegacyStringToItemParserException;
|
||||
use pocketmine\item\StringToItemParser;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\nbt\JsonNbtParser;
|
||||
use pocketmine\nbt\NbtDataException;
|
||||
use pocketmine\nbt\NbtException;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function array_slice;
|
||||
@ -44,8 +44,8 @@ class GiveCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_GIVE_DESCRIPTION,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_GIVE_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_give_description(),
|
||||
KnownTranslationFactory::pocketmine_command_give_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_GIVE);
|
||||
}
|
||||
@ -87,7 +87,12 @@ class GiveCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
$item->setNamedTag($tags);
|
||||
try{
|
||||
$item->setNamedTag($tags);
|
||||
}catch(NbtException $e){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_give_tagError($e->getMessage()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: overflow
|
||||
|
@ -26,7 +26,7 @@ namespace pocketmine\command\defaults;
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\lang\Translatable;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function array_chunk;
|
||||
@ -46,8 +46,8 @@ class HelpCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_HELP_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_HELP_USAGE,
|
||||
KnownTranslationFactory::pocketmine_command_help_description(),
|
||||
KnownTranslationFactory::commands_help_usage(),
|
||||
["?"]
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_HELP);
|
||||
@ -92,7 +92,9 @@ class HelpCommand extends VanillaCommand{
|
||||
$lang = $sender->getLanguage();
|
||||
if(isset($commands[$pageNumber - 1])){
|
||||
foreach($commands[$pageNumber - 1] as $command){
|
||||
$sender->sendMessage(TextFormat::DARK_GREEN . "/" . $command->getName() . ": " . TextFormat::WHITE . $lang->translateString($command->getDescription()));
|
||||
$description = $command->getDescription();
|
||||
$descriptionString = $description instanceof Translatable ? $lang->translate($description) : $description;
|
||||
$sender->sendMessage(TextFormat::DARK_GREEN . "/" . $command->getName() . ": " . TextFormat::WHITE . $descriptionString);
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,15 +102,23 @@ class HelpCommand extends VanillaCommand{
|
||||
}else{
|
||||
if(($cmd = $sender->getServer()->getCommandMap()->getCommand(strtolower($commandName))) instanceof Command){
|
||||
if($cmd->testPermissionSilent($sender)){
|
||||
$message = TextFormat::YELLOW . "--------- " . TextFormat::WHITE . " Help: /" . $cmd->getName() . TextFormat::YELLOW . " ---------\n";
|
||||
$message .= TextFormat::GOLD . "Description: " . TextFormat::WHITE . $sender->getLanguage()->translateString($cmd->getDescription()) . "\n";
|
||||
$message .= TextFormat::GOLD . "Usage: " . TextFormat::WHITE . implode("\n" . TextFormat::WHITE, explode("\n", $sender->getLanguage()->translateString($cmd->getUsage()))) . "\n";
|
||||
$sender->sendMessage($message);
|
||||
$lang = $sender->getLanguage();
|
||||
$description = $cmd->getDescription();
|
||||
$descriptionString = $description instanceof Translatable ? $lang->translate($description) : $description;
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_help_specificCommand_header($commandName)
|
||||
->format(TextFormat::YELLOW . "--------- " . TextFormat::WHITE, TextFormat::YELLOW . " ---------"));
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_help_specificCommand_description(TextFormat::WHITE . $descriptionString)
|
||||
->prefix(TextFormat::GOLD));
|
||||
|
||||
$usage = $cmd->getUsage();
|
||||
$usageString = $usage instanceof Translatable ? $lang->translate($usage) : $usage;
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_help_specificCommand_usage(TextFormat::WHITE . implode("\n" . TextFormat::WHITE, explode("\n", $usageString)))
|
||||
->prefix(TextFormat::GOLD));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
$sender->sendMessage(TextFormat::RED . "No help for " . strtolower($commandName));
|
||||
$sender->sendMessage(KnownTranslationFactory::pocketmine_command_notFound($commandName, "/help")->prefix(TextFormat::RED));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
@ -41,8 +40,8 @@ class KickCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_KICK_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_KICK_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_kick_description(),
|
||||
KnownTranslationFactory::commands_kick_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_KICK);
|
||||
}
|
||||
|
@ -28,7 +28,6 @@ use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
@ -40,8 +39,8 @@ class KillCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_KILL_DESCRIPTION,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_KILL_USAGE,
|
||||
KnownTranslationFactory::pocketmine_command_kill_description(),
|
||||
KnownTranslationFactory::pocketmine_command_kill_usage(),
|
||||
["suicide"]
|
||||
);
|
||||
$this->setPermission(implode(";", [DefaultPermissionNames::COMMAND_KILL_SELF, DefaultPermissionNames::COMMAND_KILL_OTHER]));
|
||||
|
@ -25,7 +25,6 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use function array_filter;
|
||||
@ -40,8 +39,7 @@ class ListCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_LIST_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_PLAYERS_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_list_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_LIST);
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ namespace pocketmine\command\defaults;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
@ -38,8 +37,8 @@ class MeCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_ME_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_ME_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_me_description(),
|
||||
KnownTranslationFactory::commands_me_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_ME);
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
@ -39,8 +38,8 @@ class OpCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_OP_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_OP_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_op_description(),
|
||||
KnownTranslationFactory::commands_op_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_OP_GIVE);
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use function count;
|
||||
|
||||
@ -36,8 +35,8 @@ class PardonCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_UNBAN_PLAYER_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_UNBAN_USAGE,
|
||||
KnownTranslationFactory::pocketmine_command_unban_player_description(),
|
||||
KnownTranslationFactory::commands_unban_usage(),
|
||||
["unban"]
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_UNBAN_PLAYER);
|
||||
|
@ -27,18 +27,17 @@ use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use function count;
|
||||
use function preg_match;
|
||||
use function inet_pton;
|
||||
|
||||
class PardonIpCommand extends VanillaCommand{
|
||||
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_UNBAN_IP_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_UNBANIP_USAGE,
|
||||
KnownTranslationFactory::pocketmine_command_unban_ip_description(),
|
||||
KnownTranslationFactory::commands_unbanip_usage(),
|
||||
["unban-ip"]
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_UNBAN_IP);
|
||||
@ -53,7 +52,7 @@ class PardonIpCommand extends VanillaCommand{
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
if(preg_match("/^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$/", $args[0])){
|
||||
if(inet_pton($args[0]) !== false){
|
||||
$sender->getServer()->getIPBans()->remove($args[0]);
|
||||
$sender->getServer()->getNetwork()->unblockAddress($args[0]);
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_unbanip_success($args[0]));
|
||||
|
@ -30,7 +30,6 @@ use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
@ -79,8 +78,8 @@ class ParticleCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_PARTICLE_DESCRIPTION,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_PARTICLE_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_particle_description(),
|
||||
KnownTranslationFactory::pocketmine_command_particle_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_PARTICLE);
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\plugin\Plugin;
|
||||
use pocketmine\utils\TextFormat;
|
||||
@ -40,8 +39,8 @@ class PluginsCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_PLUGINS_DESCRIPTION,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_PLUGINS_USAGE,
|
||||
KnownTranslationFactory::pocketmine_command_plugins_description(),
|
||||
null,
|
||||
["pl"]
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_PLUGINS);
|
||||
|
@ -26,7 +26,6 @@ namespace pocketmine\command\defaults;
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use function microtime;
|
||||
use function round;
|
||||
@ -36,8 +35,7 @@ class SaveCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_SAVE_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_SAVE_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_save_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_SAVE_PERFORM);
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ namespace pocketmine\command\defaults;
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
|
||||
class SaveOffCommand extends VanillaCommand{
|
||||
@ -34,8 +33,7 @@ class SaveOffCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_SAVEOFF_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_SAVE_OFF_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_saveoff_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_SAVE_DISABLE);
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ namespace pocketmine\command\defaults;
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
|
||||
class SaveOnCommand extends VanillaCommand{
|
||||
@ -34,8 +33,7 @@ class SaveOnCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_SAVEON_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_SAVE_ON_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_saveon_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_SAVE_ENABLE);
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\console\ConsoleCommandSender;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
@ -39,8 +38,8 @@ class SayCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_SAY_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_SAY_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_say_description(),
|
||||
KnownTranslationFactory::commands_say_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_SAY);
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
|
||||
@ -34,8 +33,7 @@ class SeedCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_SEED_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_SEED_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_seed_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_SEED);
|
||||
}
|
||||
|
@ -27,21 +27,20 @@ use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\world\World;
|
||||
use function count;
|
||||
use function round;
|
||||
|
||||
class SetWorldSpawnCommand extends VanillaCommand{
|
||||
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_SETWORLDSPAWN_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_SETWORLDSPAWN_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_setworldspawn_description(),
|
||||
KnownTranslationFactory::commands_setworldspawn_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_SETWORLDSPAWN);
|
||||
}
|
||||
@ -55,22 +54,32 @@ class SetWorldSpawnCommand extends VanillaCommand{
|
||||
if($sender instanceof Player){
|
||||
$location = $sender->getPosition();
|
||||
$world = $location->getWorld();
|
||||
$pos = $location->asVector3()->round();
|
||||
$pos = $location->asVector3()->floor();
|
||||
}else{
|
||||
$sender->sendMessage(TextFormat::RED . "You can only perform this command as a player");
|
||||
|
||||
return true;
|
||||
}
|
||||
}elseif(count($args) === 3){
|
||||
$world = $sender->getServer()->getWorldManager()->getDefaultWorld();
|
||||
$pos = new Vector3($this->getInteger($sender, $args[0]), $this->getInteger($sender, $args[1]), $this->getInteger($sender, $args[2]));
|
||||
if($sender instanceof Player){
|
||||
$base = $sender->getPosition();
|
||||
$world = $base->getWorld();
|
||||
}else{
|
||||
$base = new Vector3(0.0, 0.0, 0.0);
|
||||
$world = $sender->getServer()->getWorldManager()->getDefaultWorld();
|
||||
}
|
||||
$pos = (new Vector3(
|
||||
$this->getRelativeDouble($base->x, $sender, $args[0]),
|
||||
$this->getRelativeDouble($base->y, $sender, $args[1], World::Y_MIN, World::Y_MAX),
|
||||
$this->getRelativeDouble($base->z, $sender, $args[2]),
|
||||
))->floor();
|
||||
}else{
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$world->setSpawnLocation($pos);
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_setworldspawn_success((string) round($pos->x, 2), (string) round($pos->y, 2), (string) round($pos->z, 2)));
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_setworldspawn_success((string) $pos->x, (string) $pos->y, (string) $pos->z));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
@ -41,8 +40,8 @@ class SpawnpointCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_SPAWNPOINT_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_SPAWNPOINT_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_spawnpoint_description(),
|
||||
KnownTranslationFactory::commands_spawnpoint_usage()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_SPAWNPOINT);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\utils\Process;
|
||||
use pocketmine\utils\TextFormat;
|
||||
@ -39,8 +39,7 @@ class StatusCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_STATUS_DESCRIPTION,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_STATUS_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_status_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_STATUS);
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ namespace pocketmine\command\defaults;
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
|
||||
class StopCommand extends VanillaCommand{
|
||||
@ -34,8 +33,7 @@ class StopCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_STOP_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_STOP_USAGE
|
||||
KnownTranslationFactory::pocketmine_command_stop_description()
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_STOP);
|
||||
}
|
||||
|
@ -28,11 +28,11 @@ use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\entity\Location;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\world\World;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function round;
|
||||
@ -42,8 +42,8 @@ class TeleportCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_TP_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_TP_USAGE,
|
||||
KnownTranslationFactory::pocketmine_command_tp_description(),
|
||||
KnownTranslationFactory::commands_tp_usage(),
|
||||
["teleport"]
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_TELEPORT);
|
||||
@ -112,9 +112,9 @@ class TeleportCommand extends VanillaCommand{
|
||||
}
|
||||
|
||||
$x = $this->getRelativeDouble($base->x, $sender, $targetArgs[0]);
|
||||
$y = $this->getRelativeDouble($base->y, $sender, $targetArgs[1], 0, 256);
|
||||
$y = $this->getRelativeDouble($base->y, $sender, $targetArgs[1], World::Y_MIN, World::Y_MAX);
|
||||
$z = $this->getRelativeDouble($base->z, $sender, $targetArgs[2]);
|
||||
$targetLocation = new Location($x, $y, $z, $yaw, $pitch, $base->getWorld());
|
||||
$targetLocation = new Location($x, $y, $z, $base->getWorld(), $yaw, $pitch);
|
||||
|
||||
$subject->teleport($targetLocation);
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_tp_success_coordinates(
|
||||
|
@ -27,7 +27,6 @@ use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\lang\KnownTranslationKeys;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
@ -40,8 +39,8 @@ class TellCommand extends VanillaCommand{
|
||||
public function __construct(string $name){
|
||||
parent::__construct(
|
||||
$name,
|
||||
KnownTranslationKeys::POCKETMINE_COMMAND_TELL_DESCRIPTION,
|
||||
KnownTranslationKeys::COMMANDS_MESSAGE_USAGE,
|
||||
KnownTranslationFactory::pocketmine_command_tell_description(),
|
||||
KnownTranslationFactory::commands_message_usage(),
|
||||
["w", "msg"]
|
||||
);
|
||||
$this->setPermission(DefaultPermissionNames::COMMAND_TELL);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user