mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-11 03:58:06 +00:00
Compare commits
97 Commits
Author | SHA1 | Date | |
---|---|---|---|
b296ae1b87 | |||
f9e42b716a | |||
34c1d455a7 | |||
af8936dba5 | |||
e8ffab1787 | |||
ecc1e1f698 | |||
ea5931e274 | |||
988cf7f535 | |||
e156fb47e8 | |||
efc5f34877 | |||
dd0d8842d5 | |||
7bdc564ccc | |||
69fff23f1a | |||
ae43698e88 | |||
0987e03c03 | |||
97c124edf9 | |||
56501178b7 | |||
da663deea1 | |||
972c911485 | |||
0d8858f948 | |||
da71540fce | |||
ec9b39862b | |||
efca8077d5 | |||
5066d5225b | |||
aefaf73685 | |||
15401d740f | |||
5920b0ba40 | |||
dea75a0687 | |||
873e8740e0 | |||
260c55f23a | |||
9ed430acb9 | |||
f0241043de | |||
135f1c95e4 | |||
5431807e43 | |||
d49ae832e8 | |||
ff9d013005 | |||
b0e1317818 | |||
8653afb0fb | |||
995b56aaa0 | |||
3ecddf312d | |||
470243ca6f | |||
3f21e59917 | |||
fdd74a4f46 | |||
a43b46a93c | |||
0604dfc9e5 | |||
dd2c3db285 | |||
c95e283507 | |||
6afbd1f55c | |||
0682c93f5a | |||
da90ae85da | |||
e87127f309 | |||
0237a50d90 | |||
8b53e4150e | |||
1c43538238 | |||
68887105b2 | |||
104e90b794 | |||
994062f6dc | |||
69a41a5ed4 | |||
3903b70ef5 | |||
692e63ad7c | |||
4d1be4d41d | |||
5f0310a8b6 | |||
9b01fb3d89 | |||
f28405fcfb | |||
9c07c206f6 | |||
d0d701f232 | |||
07cae8a129 | |||
6869ee1c2d | |||
26155acff2 | |||
b550cf5163 | |||
48fa19fdcd | |||
bac986d0b2 | |||
215bac8dd7 | |||
3709ba172b | |||
ef034f2d68 | |||
ab18332572 | |||
48595630fc | |||
4102205ba6 | |||
9e85ee4a7a | |||
e8e6b9304c | |||
23849b7f63 | |||
d2f68836c6 | |||
d19db5d2e4 | |||
98cdc80d37 | |||
8273f789ee | |||
29eccba5f0 | |||
9984b15de6 | |||
6ea01e0dd4 | |||
46331df7db | |||
691c49fb32 | |||
db815360d1 | |||
6e297168c2 | |||
95dbb00d4c | |||
50e29a5ed8 | |||
9f3fb935b5 | |||
e30b1ee2c7 | |||
574b7f6343 |
1
.github/ISSUE_TEMPLATE/crash.md
vendored
1
.github/ISSUE_TEMPLATE/crash.md
vendored
@ -9,6 +9,7 @@ assignees: ''
|
||||
|
||||
<!--- submit crashdump files to https://crash.pmmp.io -->
|
||||
<!--- or, copy the data between ===BEGIN CRASH DUMP=== and ===END CRASH DUMP and paste it on a site like https://pastebin.com -->
|
||||
<!--- DON'T JUST PASTE the crashdump into an issue -->
|
||||
Link to crashdump:
|
||||
|
||||
<!--- write additional information about the crash to help us find the problem -->
|
||||
|
166
.github/workflows/main.yml
vendored
Normal file
166
.github/workflows/main.yml
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-php:
|
||||
name: Prepare PHP
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php: [7.3.25, 7.4.13]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2 #needed for build.sh
|
||||
- name: Check for PHP build cache
|
||||
id: php-build-cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "./bin"
|
||||
key: "php-build-generic-${{ matrix.php }}-${{ 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 }}"
|
||||
|
||||
phpstan:
|
||||
name: PHPStan analysis
|
||||
needs: build-php
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php: [7.3.25, 7.4.13]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Restore PHP build cache
|
||||
id: php-build-cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "./bin"
|
||||
key: "php-build-generic-${{ matrix.php }}-${{ 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: Prefix PHP to PATH
|
||||
run: echo "$(pwd)/bin/php7/bin" >> $GITHUB_PATH
|
||||
|
||||
- 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 --prefer-dist --no-interaction
|
||||
|
||||
- name: Run PHPStan
|
||||
run: ./vendor/bin/phpstan analyze --no-progress --memory-limit=2G
|
||||
|
||||
phpunit:
|
||||
name: PHPUnit tests
|
||||
needs: build-php
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php: [7.3.25, 7.4.13]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Restore PHP build cache
|
||||
id: php-build-cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "./bin"
|
||||
key: "php-build-generic-${{ matrix.php }}-${{ 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: Prefix PHP to PATH
|
||||
run: echo "$(pwd)/bin/php7/bin" >> $GITHUB_PATH
|
||||
|
||||
- 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 --prefer-dist --no-interaction
|
||||
|
||||
- name: Run PHPUnit tests
|
||||
run: ./vendor/bin/phpunit --bootstrap vendor/autoload.php --fail-on-warning tests/phpunit
|
||||
|
||||
integration:
|
||||
name: Integration tests
|
||||
needs: build-php
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php: [7.3.25, 7.4.13]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
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 }}-${{ 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: Prefix PHP to PATH
|
||||
run: echo "$(pwd)/bin/php7/bin" >> $GITHUB_PATH
|
||||
|
||||
- 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: Run integration tests
|
||||
run: ./tests/travis.sh -t4
|
21
.travis.yml
21
.travis.yml
@ -1,21 +0,0 @@
|
||||
import:
|
||||
source: ./tests/travis/setup-php.yml
|
||||
|
||||
script:
|
||||
- composer install --prefer-dist
|
||||
- ./vendor/bin/phpstan analyze --no-progress --memory-limit=2G
|
||||
- ./vendor/bin/phpunit --bootstrap vendor/autoload.php --fail-on-warning tests/phpunit
|
||||
- composer install --no-dev --prefer-dist
|
||||
- ./tests/travis.sh -t4
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache/files
|
||||
- $HOME/.composer/cache/vcs
|
||||
|
||||
notifications:
|
||||
email:
|
||||
recipients:
|
||||
- team@pmmp.io
|
||||
on_success: change
|
||||
on_failure: always
|
@ -30,7 +30,7 @@ If you use a custom binary, you'll need to replace `composer` usages in this gui
|
||||
Preprocessor requires that the `cpp` (c preprocessor) is available in your PATH.
|
||||
|
||||
## Building `PocketMine-MP.phar`
|
||||
Run `build/server-phar.php` using your preferred PHP binary. It'll drop a `PocketMine-MP.phar` into the current working directory.
|
||||
Run `composer make-server` using your preferred PHP binary. It'll drop a `PocketMine-MP.phar` into the current working directory.
|
||||
|
||||
You can also use the `--out` option to change the output filename.
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
<b>A highly customisable, open source server software for Minecraft: Bedrock Edition written in PHP</b>
|
||||
</p>
|
||||
|
||||
[](https://travis-ci.com/pmmp/PocketMine-MP)
|
||||

|
||||
|
||||
## Getting started
|
||||
- [Documentation](http://pmmp.readthedocs.org/)
|
||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
||||
namespace pocketmine\build\make_release;
|
||||
|
||||
use pocketmine\utils\VersionString;
|
||||
use function defined;
|
||||
use function dirname;
|
||||
use function fgets;
|
||||
use function file_get_contents;
|
||||
@ -86,6 +85,4 @@ function main(array $argv) : void{
|
||||
system('git push origin HEAD ' . $currentVer->getBaseVersion());
|
||||
}
|
||||
|
||||
if(!defined('pocketmine\_PHPSTAN_ANALYSIS')){
|
||||
main($argv);
|
||||
}
|
||||
main($argv);
|
||||
|
Submodule build/php updated: e45cfc1ece...60194e8b14
@ -26,7 +26,6 @@ namespace pocketmine\build\server_phar;
|
||||
use pocketmine\utils\Git;
|
||||
use function array_map;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function dirname;
|
||||
use function file_exists;
|
||||
use function getcwd;
|
||||
@ -41,6 +40,7 @@ use function rtrim;
|
||||
use function sprintf;
|
||||
use function str_replace;
|
||||
use function unlink;
|
||||
use const PHP_EOL;
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
@ -129,6 +129,10 @@ function main() : void{
|
||||
echo "Set phar.readonly to 0 with -dphar.readonly=0" . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
if(file_exists(dirname(__DIR__) . '/vendor/phpunit')){
|
||||
echo "Remove Composer dev dependencies before building (composer install --no-dev)" . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$opts = getopt("", ["out:", "git:"]);
|
||||
if(isset($opts["git"])){
|
||||
@ -169,6 +173,4 @@ STUB
|
||||
}
|
||||
}
|
||||
|
||||
if(!defined('pocketmine\_PHPSTAN_ANALYSIS')){
|
||||
main();
|
||||
}
|
||||
main();
|
||||
|
24
changelogs/3.16.md
Normal file
24
changelogs/3.16.md
Normal file
@ -0,0 +1,24 @@
|
||||
**For Minecraft: Bedrock Edition 1.16.100**
|
||||
|
||||
### 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.16.0
|
||||
- Added support for Minecraft: Bedrock Edition 1.16.100.
|
||||
- Removed compatibility with earlier versions.
|
||||
- Added new custom composer commands `make-server` and `make-devtools` to ease setting up a development environment and building the server.
|
||||
|
||||
## Known issues (please don't open issues for these)
|
||||
- Walls don't connect to each other
|
||||
- Pumpkin and melon stems may not connect to their corresponding pumpkin/melon
|
||||
- New blocks, items & mobs aren't implemented
|
||||
- Nether doesn't exist
|
||||
|
||||
# 3.16.1
|
||||
- Fixed incorrect encoding of skins in the protocol.
|
||||
- `/version` no longer crashes when a plugin provides `string[]` for the `author` field in `plugin.yml`.
|
||||
- `author` in `plugin.yml` now accepts arrays, just like `authors`.
|
||||
- Fixed `HellBiome` never being registered.
|
34
changelogs/3.17.md
Normal file
34
changelogs/3.17.md
Normal file
@ -0,0 +1,34 @@
|
||||
**For Minecraft: Bedrock Edition 1.16.200**
|
||||
|
||||
### 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.17.0
|
||||
- Added support for Minecraft: Bedrock Edition 1.16.200.
|
||||
- Removed compatibility with earlier versions.
|
||||
|
||||
## Known issues (please don't open issues for these)
|
||||
- Walls don't connect to each other
|
||||
- Pumpkin and melon stems may not connect to their corresponding pumpkin/melon
|
||||
- New blocks, items & mobs aren't implemented
|
||||
- Nether doesn't exist
|
||||
|
||||
# 3.17.1
|
||||
- Fixed some instances of plugin-caused crashes not being detected (eval()'d code, custom plugin paths).
|
||||
- Server uptime is now included in crash reports.
|
||||
- Hoes now take damage when used to break sponges.
|
||||
- Using lava as fuel in a furnace now leaves behind an empty bucket.
|
||||
|
||||
# 3.17.2
|
||||
- Fixed region header corruption when chunks with larger-than-expected lengths are found. These chunks are now treated as corrupted, instead of automatically attempting to salvage them (which usually fails anyway).
|
||||
- `RegionLoader->removeChunk()` now allows the space used by the removed chunk to be reused by future region saves.
|
||||
- Extracted `Living->applyConsumptionResults()` from `Living->consumeObject()` (preparation for a future bug fix).
|
||||
|
||||
# 3.17.3
|
||||
- Improved performance of chunk loading in Region-based worlds.
|
||||
- Improved performance of region header validation in Region-based worlds (indirect improvement to chunk loading performance).
|
||||
- Fixed some PHP 8.0 language-level compatibility issues.
|
||||
- Source installations will now exit with an error when Composer dependencies are not in sync with the current Git revision. Now, it's required to run `composer install` after every git pull to make sure the correct dependency versions are installed.
|
@ -7,7 +7,6 @@
|
||||
"require": {
|
||||
"php": ">=7.3.0",
|
||||
"php-64bit": "*",
|
||||
"ext-bcmath": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-ctype": "*",
|
||||
"ext-date": "*",
|
||||
@ -38,7 +37,7 @@
|
||||
"composer-runtime-api": "^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "0.12.54",
|
||||
"phpstan/phpstan": "0.12.69",
|
||||
"phpstan/phpstan-phpunit": "^0.12.6",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.2",
|
||||
"phpunit/phpunit": "^9.2"
|
||||
@ -61,6 +60,14 @@
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "7.3.0"
|
||||
}
|
||||
},
|
||||
"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-server": [
|
||||
"@composer install --no-dev --classmap-authoritative",
|
||||
"@php -dphar.readonly=0 build/server-phar.php"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
367
composer.lock
generated
367
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "f7b6b54d43e00372b7dea787d863d8b9",
|
||||
"content-hash": "5466cbf8934081309e4c8ad5c2781f65",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/json-comment",
|
||||
@ -56,25 +56,25 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/binaryutils",
|
||||
"version": "0.1.12",
|
||||
"version": "0.1.13",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BinaryUtils.git",
|
||||
"reference": "566fa87829e007eda0bd96e39fe20b9b0d638132"
|
||||
"reference": "0abee38d4e2861621f262c79a2a3d699d8a697f4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/566fa87829e007eda0bd96e39fe20b9b0d638132",
|
||||
"reference": "566fa87829e007eda0bd96e39fe20b9b0d638132",
|
||||
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/0abee38d4e2861621f262c79a2a3d699d8a697f4",
|
||||
"reference": "0abee38d4e2861621f262c79a2a3d699d8a697f4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"php": "^7.2 || ^8.0",
|
||||
"php-64bit": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "0.12.40",
|
||||
"phpstan/phpstan": "0.12.67",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.4"
|
||||
},
|
||||
"type": "library",
|
||||
@ -90,34 +90,34 @@
|
||||
"description": "Classes and methods for conveniently handling binary data",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/BinaryUtils/issues",
|
||||
"source": "https://github.com/pmmp/BinaryUtils/tree/stable"
|
||||
"source": "https://github.com/pmmp/BinaryUtils/tree/0.1.13"
|
||||
},
|
||||
"time": "2020-08-28T20:43:21+00:00"
|
||||
"time": "2021-01-15T14:19:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/callback-validator",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:pmmp/CallbackValidator.git",
|
||||
"reference": "8321aa3ccfe63639b0d08f0cbf270755cfc99fe2"
|
||||
"url": "https://github.com/pmmp/CallbackValidator.git",
|
||||
"reference": "64787469766bcaa7e5885242e85c23c25e8c55a2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/CallbackValidator/zipball/8321aa3ccfe63639b0d08f0cbf270755cfc99fe2",
|
||||
"reference": "8321aa3ccfe63639b0d08f0cbf270755cfc99fe2",
|
||||
"url": "https://api.github.com/repos/pmmp/CallbackValidator/zipball/64787469766bcaa7e5885242e85c23c25e8c55a2",
|
||||
"reference": "64787469766bcaa7e5885242e85c23c25e8c55a2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-reflection": "*",
|
||||
"php": ">=7.1"
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"replace": {
|
||||
"daverandom/callback-validator": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "0.12.38",
|
||||
"phpstan/phpstan": "0.12.59",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.4",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.0"
|
||||
},
|
||||
@ -138,33 +138,37 @@
|
||||
}
|
||||
],
|
||||
"description": "Fork of daverandom/callback-validator - Tools for validating callback signatures",
|
||||
"time": "2020-08-21T19:51:42+00:00"
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/CallbackValidator/issues",
|
||||
"source": "https://github.com/pmmp/CallbackValidator/tree/1.0.3"
|
||||
},
|
||||
"time": "2020-12-11T01:45:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/classloader",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/ClassLoader.git",
|
||||
"reference": "7c0363491d1ce8f914fe96d41a4338c982adedff"
|
||||
"reference": "9757928424652393b178a3760073113aa7c9911b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/ClassLoader/zipball/7c0363491d1ce8f914fe96d41a4338c982adedff",
|
||||
"reference": "7c0363491d1ce8f914fe96d41a4338c982adedff",
|
||||
"url": "https://api.github.com/repos/pmmp/ClassLoader/zipball/9757928424652393b178a3760073113aa7c9911b",
|
||||
"reference": "9757928424652393b178a3760073113aa7c9911b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-pthreads": "~3.2.0",
|
||||
"ext-reflection": "*",
|
||||
"php": ">=7.2.0"
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"pocketmine/spl": "<0.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "0.12.38",
|
||||
"phpstan/phpstan": "0.12.66",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.4"
|
||||
},
|
||||
"type": "library",
|
||||
@ -180,32 +184,32 @@
|
||||
"description": "Ad-hoc autoloading components used by PocketMine-MP",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/ClassLoader/issues",
|
||||
"source": "https://github.com/pmmp/ClassLoader/tree/stable"
|
||||
"source": "https://github.com/pmmp/ClassLoader/tree/0.1.2"
|
||||
},
|
||||
"time": "2020-08-22T11:48:51+00:00"
|
||||
"time": "2021-01-15T00:40:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/log",
|
||||
"version": "0.2.0",
|
||||
"version": "0.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/Log.git",
|
||||
"reference": "e59bedb5d4bbeb9a26647cb7c367cb2fa72addfa"
|
||||
"reference": "830b44a2cf96ef703c550abe64302f230231ca49"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/Log/zipball/e59bedb5d4bbeb9a26647cb7c367cb2fa72addfa",
|
||||
"reference": "e59bedb5d4bbeb9a26647cb7c367cb2fa72addfa",
|
||||
"url": "https://api.github.com/repos/pmmp/Log/zipball/830b44a2cf96ef703c550abe64302f230231ca49",
|
||||
"reference": "830b44a2cf96ef703c550abe64302f230231ca49",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2"
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"pocketmine/spl": "<0.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^0.12.8",
|
||||
"phpstan/phpstan": "0.12.67",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.2"
|
||||
},
|
||||
"type": "library",
|
||||
@ -221,34 +225,36 @@
|
||||
"description": "Logging components used by PocketMine-MP and related projects",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/Log/issues",
|
||||
"source": "https://github.com/pmmp/Log/tree/0.2.0"
|
||||
"source": "https://github.com/pmmp/Log/tree/0.2.1"
|
||||
},
|
||||
"time": "2020-03-31T15:43:47+00:00"
|
||||
"time": "2021-01-15T14:32:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/log-pthreads",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/LogPthreads.git",
|
||||
"reference": "9bbcef398b01487ab47c234a6a7054722abbe067"
|
||||
"reference": "e477ecf6ec214fdd4415ea1da3fdd9d73bf699ea"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/LogPthreads/zipball/9bbcef398b01487ab47c234a6a7054722abbe067",
|
||||
"reference": "9bbcef398b01487ab47c234a6a7054722abbe067",
|
||||
"url": "https://api.github.com/repos/pmmp/LogPthreads/zipball/e477ecf6ec214fdd4415ea1da3fdd9d73bf699ea",
|
||||
"reference": "e477ecf6ec214fdd4415ea1da3fdd9d73bf699ea",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-pthreads": "~3.2.0",
|
||||
"php": ">=7.2",
|
||||
"php": "^7.2 || ^8.0",
|
||||
"pocketmine/log": "^0.2.0"
|
||||
},
|
||||
"conflict": {
|
||||
"pocketmine/spl": "<0.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^0.12.18"
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "0.12.66",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.4"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@ -263,31 +269,31 @@
|
||||
"description": "Logging components specialized for pthreads used by PocketMine-MP and related projects",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/LogPthreads/issues",
|
||||
"source": "https://github.com/pmmp/LogPthreads/tree/0.1.1"
|
||||
"source": "https://github.com/pmmp/LogPthreads/tree/0.1.3"
|
||||
},
|
||||
"time": "2020-03-31T16:17:19+00:00"
|
||||
"time": "2021-01-15T00:35:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/math",
|
||||
"version": "0.2.5",
|
||||
"version": "0.2.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/Math.git",
|
||||
"reference": "8c46cfa95351fb0b2b30739a381310941934b55f"
|
||||
"reference": "43057cb8c179a9859677b496a788db922fd5cfc3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/Math/zipball/8c46cfa95351fb0b2b30739a381310941934b55f",
|
||||
"reference": "8c46cfa95351fb0b2b30739a381310941934b55f",
|
||||
"url": "https://api.github.com/repos/pmmp/Math/zipball/43057cb8c179a9859677b496a788db922fd5cfc3",
|
||||
"reference": "43057cb8c179a9859677b496a788db922fd5cfc3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.0",
|
||||
"php": "^7.2 || ^8.0",
|
||||
"php-64bit": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "0.12.40",
|
||||
"phpstan/phpstan": "0.12.67",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.4"
|
||||
},
|
||||
"type": "library",
|
||||
@ -303,34 +309,34 @@
|
||||
"description": "PHP library containing math related code used in PocketMine-MP",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/Math/issues",
|
||||
"source": "https://github.com/pmmp/Math/tree/stable"
|
||||
"source": "https://github.com/pmmp/Math/tree/0.2.6"
|
||||
},
|
||||
"time": "2020-08-27T11:45:40+00:00"
|
||||
"time": "2021-01-15T14:25:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/nbt",
|
||||
"version": "0.2.15",
|
||||
"version": "0.2.16",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/NBT.git",
|
||||
"reference": "f8a81d37d24eb79fb77d985a52549d68955bc6a1"
|
||||
"reference": "be6d54a8a314967d938b501eee49d4641e2ab07d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/NBT/zipball/f8a81d37d24eb79fb77d985a52549d68955bc6a1",
|
||||
"reference": "f8a81d37d24eb79fb77d985a52549d68955bc6a1",
|
||||
"url": "https://api.github.com/repos/pmmp/NBT/zipball/be6d54a8a314967d938b501eee49d4641e2ab07d",
|
||||
"reference": "be6d54a8a314967d938b501eee49d4641e2ab07d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-zlib": "*",
|
||||
"php": ">=7.2.0",
|
||||
"php": "^7.2 || ^8.0",
|
||||
"php-64bit": "*",
|
||||
"pocketmine/binaryutils": "^0.1.9"
|
||||
},
|
||||
"require-dev": {
|
||||
"irstea/phpunit-shim": "^7.5 || ^8.0",
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "0.12.40",
|
||||
"phpstan/phpstan": "0.12.67",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.4"
|
||||
},
|
||||
"type": "library",
|
||||
@ -346,28 +352,28 @@
|
||||
"description": "PHP library for working with Named Binary Tags",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/NBT/issues",
|
||||
"source": "https://github.com/pmmp/NBT/tree/stable"
|
||||
"source": "https://github.com/pmmp/NBT/tree/0.2.16"
|
||||
},
|
||||
"time": "2020-08-28T15:11:32+00:00"
|
||||
"time": "2021-01-15T15:27:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/raklib",
|
||||
"version": "0.12.9",
|
||||
"version": "0.12.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/RakLib.git",
|
||||
"reference": "5f2a02009f486ca4d90892814570fa13ebdc078d"
|
||||
"reference": "48e70551cca6f2409115d3468bed94c2edd08f31"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/5f2a02009f486ca4d90892814570fa13ebdc078d",
|
||||
"reference": "5f2a02009f486ca4d90892814570fa13ebdc078d",
|
||||
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/48e70551cca6f2409115d3468bed94c2edd08f31",
|
||||
"reference": "48e70551cca6f2409115d3468bed94c2edd08f31",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-pthreads": "~3.2.0",
|
||||
"ext-sockets": "*",
|
||||
"php": ">=7.2.0",
|
||||
"php": "^7.2 || ^8.0",
|
||||
"php-64bit": "*",
|
||||
"php-ipv6": "*",
|
||||
"pocketmine/binaryutils": "^0.1.9",
|
||||
@ -376,7 +382,7 @@
|
||||
"pocketmine/snooze": "^0.1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "0.12.40",
|
||||
"phpstan/phpstan": "0.12.67",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.2"
|
||||
},
|
||||
"type": "library",
|
||||
@ -392,31 +398,31 @@
|
||||
"description": "A RakNet server implementation written in PHP",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/RakLib/issues",
|
||||
"source": "https://github.com/pmmp/RakLib/tree/stable"
|
||||
"source": "https://github.com/pmmp/RakLib/tree/0.12.10"
|
||||
},
|
||||
"time": "2020-08-28T15:22:57+00:00"
|
||||
"time": "2021-01-15T16:19:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/snooze",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/Snooze.git",
|
||||
"reference": "849510fa62e57512b8467e3694e9b3add97038fd"
|
||||
"reference": "382ab149f01ecca0a57f999ff5d7fc9e271c3268"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/Snooze/zipball/849510fa62e57512b8467e3694e9b3add97038fd",
|
||||
"reference": "849510fa62e57512b8467e3694e9b3add97038fd",
|
||||
"url": "https://api.github.com/repos/pmmp/Snooze/zipball/382ab149f01ecca0a57f999ff5d7fc9e271c3268",
|
||||
"reference": "382ab149f01ecca0a57f999ff5d7fc9e271c3268",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-pthreads": ">=3.1.7dev",
|
||||
"php-64bit": ">=7.2.0"
|
||||
"php-64bit": "^7.2 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "0.12.40",
|
||||
"phpstan/phpstan": "0.12.67",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.4"
|
||||
},
|
||||
"type": "library",
|
||||
@ -432,26 +438,26 @@
|
||||
"description": "Thread notification management library for code using the pthreads extension",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/Snooze/issues",
|
||||
"source": "https://github.com/pmmp/Snooze/tree/0.1.3"
|
||||
"source": "https://github.com/pmmp/Snooze/tree/0.1.4"
|
||||
},
|
||||
"time": "2020-08-28T22:19:21+00:00"
|
||||
"time": "2021-01-15T14:44:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/spl",
|
||||
"version": "0.4.1",
|
||||
"version": "0.4.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/SPL.git",
|
||||
"reference": "ff0579a0be41bbe65d3637607715c0f87728a838"
|
||||
"reference": "6b08b7cf8c4afa17139c9a1b3bf1b408531de161"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/SPL/zipball/ff0579a0be41bbe65d3637607715c0f87728a838",
|
||||
"reference": "ff0579a0be41bbe65d3637607715c0f87728a838",
|
||||
"url": "https://api.github.com/repos/pmmp/SPL/zipball/6b08b7cf8c4afa17139c9a1b3bf1b408531de161",
|
||||
"reference": "6b08b7cf8c4afa17139c9a1b3bf1b408531de161",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2"
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^0.12.8"
|
||||
@ -469,44 +475,39 @@
|
||||
"description": "Standard library files required by PocketMine-MP and related projects",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/SPL/issues",
|
||||
"source": "https://github.com/pmmp/SPL/tree/0.4.1"
|
||||
"source": "https://github.com/pmmp/SPL/tree/0.4.2"
|
||||
},
|
||||
"time": "2020-01-31T16:18:03+00:00"
|
||||
"time": "2021-01-15T15:15:23+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "doctrine/instantiator",
|
||||
"version": "1.3.1",
|
||||
"version": "1.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/instantiator.git",
|
||||
"reference": "f350df0268e904597e3bd9c4685c53e0e333feea"
|
||||
"reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/f350df0268e904597e3bd9c4685c53e0e333feea",
|
||||
"reference": "f350df0268e904597e3bd9c4685c53e0e333feea",
|
||||
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b",
|
||||
"reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^6.0",
|
||||
"doctrine/coding-standard": "^8.0",
|
||||
"ext-pdo": "*",
|
||||
"ext-phar": "*",
|
||||
"phpbench/phpbench": "^0.13",
|
||||
"phpstan/phpstan-phpunit": "^0.11",
|
||||
"phpstan/phpstan-shim": "^0.11",
|
||||
"phpunit/phpunit": "^7.0"
|
||||
"phpbench/phpbench": "^0.13 || 1.0.0-alpha2",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"phpstan/phpstan-phpunit": "^0.12",
|
||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
|
||||
@ -520,7 +521,7 @@
|
||||
{
|
||||
"name": "Marco Pivetta",
|
||||
"email": "ocramius@gmail.com",
|
||||
"homepage": "http://ocramius.github.com/"
|
||||
"homepage": "https://ocramius.github.io/"
|
||||
}
|
||||
],
|
||||
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
|
||||
@ -531,7 +532,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/instantiator/issues",
|
||||
"source": "https://github.com/doctrine/instantiator/tree/1.3.x"
|
||||
"source": "https://github.com/doctrine/instantiator/tree/1.4.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -547,20 +548,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-05-29T17:27:14+00:00"
|
||||
"time": "2020-11-10T18:47:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "myclabs/deep-copy",
|
||||
"version": "1.10.1",
|
||||
"version": "1.10.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/myclabs/DeepCopy.git",
|
||||
"reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5"
|
||||
"reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/969b211f9a51aa1f6c01d1d2aef56d3bd91598e5",
|
||||
"reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220",
|
||||
"reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -597,7 +598,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/myclabs/DeepCopy/issues",
|
||||
"source": "https://github.com/myclabs/DeepCopy/tree/1.x"
|
||||
"source": "https://github.com/myclabs/DeepCopy/tree/1.10.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -605,20 +606,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-06-29T13:22:24+00:00"
|
||||
"time": "2020-11-13T09:40:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v4.10.2",
|
||||
"version": "v4.10.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||
"reference": "658f1be311a230e0907f5dfe0213742aff0596de"
|
||||
"reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/658f1be311a230e0907f5dfe0213742aff0596de",
|
||||
"reference": "658f1be311a230e0907f5dfe0213742aff0596de",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/c6d052fc58cb876152f89f532b95a8d7907e7f0e",
|
||||
"reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -659,9 +660,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v4.10.2"
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v4.10.4"
|
||||
},
|
||||
"time": "2020-09-26T10:30:38+00:00"
|
||||
"time": "2020-12-20T10:01:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phar-io/manifest",
|
||||
@ -725,16 +726,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phar-io/version",
|
||||
"version": "3.0.2",
|
||||
"version": "3.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phar-io/version.git",
|
||||
"reference": "c6bb6825def89e0a32220f88337f8ceaf1975fa0"
|
||||
"reference": "e4782611070e50613683d2b9a57730e9a3ba5451"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phar-io/version/zipball/c6bb6825def89e0a32220f88337f8ceaf1975fa0",
|
||||
"reference": "c6bb6825def89e0a32220f88337f8ceaf1975fa0",
|
||||
"url": "https://api.github.com/repos/phar-io/version/zipball/e4782611070e50613683d2b9a57730e9a3ba5451",
|
||||
"reference": "e4782611070e50613683d2b9a57730e9a3ba5451",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -770,9 +771,9 @@
|
||||
"description": "Library for handling version information and constraints",
|
||||
"support": {
|
||||
"issues": "https://github.com/phar-io/version/issues",
|
||||
"source": "https://github.com/phar-io/version/tree/master"
|
||||
"source": "https://github.com/phar-io/version/tree/3.0.4"
|
||||
},
|
||||
"time": "2020-06-27T14:39:04+00:00"
|
||||
"time": "2020-12-13T23:18:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-common",
|
||||
@ -934,16 +935,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpspec/prophecy",
|
||||
"version": "1.12.1",
|
||||
"version": "1.12.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpspec/prophecy.git",
|
||||
"reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d"
|
||||
"reference": "245710e971a030f42e08f4912863805570f23d39"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/8ce87516be71aae9b956f81906aaf0338e0d8a2d",
|
||||
"reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d",
|
||||
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/245710e971a030f42e08f4912863805570f23d39",
|
||||
"reference": "245710e971a030f42e08f4912863805570f23d39",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -955,7 +956,7 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"phpspec/phpspec": "^6.0",
|
||||
"phpunit/phpunit": "^8.0 || ^9.0 <9.3"
|
||||
"phpunit/phpunit": "^8.0 || ^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
@ -995,22 +996,22 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpspec/prophecy/issues",
|
||||
"source": "https://github.com/phpspec/prophecy/tree/1.12.1"
|
||||
"source": "https://github.com/phpspec/prophecy/tree/1.12.2"
|
||||
},
|
||||
"time": "2020-09-29T09:10:42+00:00"
|
||||
"time": "2020-12-19T10:15:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "0.12.54",
|
||||
"version": "0.12.69",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "45c7b999a4b7dd9ac5558bdaaf23dcebbef88223"
|
||||
"reference": "8f436ea35241da33487fd0d38b4bc3e6dfe30ea8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/45c7b999a4b7dd9ac5558bdaaf23dcebbef88223",
|
||||
"reference": "45c7b999a4b7dd9ac5558bdaaf23dcebbef88223",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/8f436ea35241da33487fd0d38b4bc3e6dfe30ea8",
|
||||
"reference": "8f436ea35241da33487fd0d38b4bc3e6dfe30ea8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1041,7 +1042,7 @@
|
||||
"description": "PHPStan - PHP Static Analysis Tool",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan/issues",
|
||||
"source": "https://github.com/phpstan/phpstan/tree/0.12.54"
|
||||
"source": "https://github.com/phpstan/phpstan/tree/0.12.69"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1057,39 +1058,34 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-11-05T13:36:26+00:00"
|
||||
"time": "2021-01-24T14:55:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-phpunit",
|
||||
"version": "0.12.16",
|
||||
"version": "0.12.17",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan-phpunit.git",
|
||||
"reference": "1dd916d181b0539dea5cd37e91546afb8b107e17"
|
||||
"reference": "432575b41cf2d4f44e460234acaf56119ed97d36"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/1dd916d181b0539dea5cd37e91546afb8b107e17",
|
||||
"reference": "1dd916d181b0539dea5cd37e91546afb8b107e17",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/432575b41cf2d4f44e460234acaf56119ed97d36",
|
||||
"reference": "432575b41cf2d4f44e460234acaf56119ed97d36",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0",
|
||||
"phpstan/phpstan": "^0.12.33"
|
||||
"phpstan/phpstan": "^0.12.60"
|
||||
},
|
||||
"conflict": {
|
||||
"phpunit/phpunit": "<7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"consistence/coding-standard": "^3.5",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
|
||||
"ergebnis/composer-normalize": "^2.0.2",
|
||||
"jakub-onderka/php-parallel-lint": "^1.0",
|
||||
"phing/phing": "^2.16.0",
|
||||
"phpstan/phpstan-strict-rules": "^0.12",
|
||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
|
||||
"satooshi/php-coveralls": "^1.0",
|
||||
"slevomat/coding-standard": "^4.7.2"
|
||||
"phing/phing": "^2.16.3",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.2",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.6",
|
||||
"phpunit/phpunit": "^7.5.20"
|
||||
},
|
||||
"type": "phpstan-extension",
|
||||
"extra": {
|
||||
@ -1115,37 +1111,33 @@
|
||||
"description": "PHPUnit extensions and rules for PHPStan",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan-phpunit/issues",
|
||||
"source": "https://github.com/phpstan/phpstan-phpunit/tree/0.12.16"
|
||||
"source": "https://github.com/phpstan/phpstan-phpunit/tree/0.12.17"
|
||||
},
|
||||
"time": "2020-08-05T13:28:50+00:00"
|
||||
"time": "2020-12-13T12:12:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-strict-rules",
|
||||
"version": "0.12.5",
|
||||
"version": "0.12.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
|
||||
"reference": "334898a32217e4605e0f9cfa3d3fc3101bda26be"
|
||||
"reference": "0705fefc7c9168529fd130e341428f5f10f4f01d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/334898a32217e4605e0f9cfa3d3fc3101bda26be",
|
||||
"reference": "334898a32217e4605e0f9cfa3d3fc3101bda26be",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/0705fefc7c9168529fd130e341428f5f10f4f01d",
|
||||
"reference": "0705fefc7c9168529fd130e341428f5f10f4f01d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0",
|
||||
"phpstan/phpstan": "^0.12.33"
|
||||
"phpstan/phpstan": "^0.12.66"
|
||||
},
|
||||
"require-dev": {
|
||||
"consistence/coding-standard": "^3.0.1",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
|
||||
"ergebnis/composer-normalize": "^2.0.2",
|
||||
"jakub-onderka/php-parallel-lint": "^1.0",
|
||||
"phing/phing": "^2.16.0",
|
||||
"phpstan/phpstan-phpunit": "^0.12",
|
||||
"phpunit/phpunit": "^7.0",
|
||||
"slevomat/coding-standard": "^4.5.2"
|
||||
"phing/phing": "^2.16.3",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.2",
|
||||
"phpstan/phpstan-phpunit": "^0.12.16",
|
||||
"phpunit/phpunit": "^7.5.20"
|
||||
},
|
||||
"type": "phpstan-extension",
|
||||
"extra": {
|
||||
@ -1170,22 +1162,22 @@
|
||||
"description": "Extra strict and opinionated rules for PHPStan",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
|
||||
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/master"
|
||||
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/0.12.9"
|
||||
},
|
||||
"time": "2020-08-30T15:42:06+00:00"
|
||||
"time": "2021-01-13T08:50:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "9.2.3",
|
||||
"version": "9.2.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "6b20e2055f7c29b56cb3870b3de7cc463d7add41"
|
||||
"reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6b20e2055f7c29b56cb3870b3de7cc463d7add41",
|
||||
"reference": "6b20e2055f7c29b56cb3870b3de7cc463d7add41",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f3e026641cc91909d421802dd3ac7827ebfd97e1",
|
||||
"reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1199,7 +1191,7 @@
|
||||
"sebastian/code-unit-reverse-lookup": "^2.0.2",
|
||||
"sebastian/complexity": "^2.0",
|
||||
"sebastian/environment": "^5.1.2",
|
||||
"sebastian/lines-of-code": "^1.0",
|
||||
"sebastian/lines-of-code": "^1.0.3",
|
||||
"sebastian/version": "^3.0.1",
|
||||
"theseer/tokenizer": "^1.2.0"
|
||||
},
|
||||
@ -1241,7 +1233,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.3"
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1249,7 +1241,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2020-10-30T10:46:41+00:00"
|
||||
"time": "2020-11-28T06:44:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
@ -1494,16 +1486,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "9.4.2",
|
||||
"version": "9.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "3866b2eeeed21b1b099c4bc0b7a1690ac6fd5baa"
|
||||
"reference": "8e16c225d57c3d6808014df6b1dd7598d0a5bbbe"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3866b2eeeed21b1b099c4bc0b7a1690ac6fd5baa",
|
||||
"reference": "3866b2eeeed21b1b099c4bc0b7a1690ac6fd5baa",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8e16c225d57c3d6808014df6b1dd7598d0a5bbbe",
|
||||
"reference": "8e16c225d57c3d6808014df6b1dd7598d0a5bbbe",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1519,7 +1511,7 @@
|
||||
"phar-io/version": "^3.0.2",
|
||||
"php": ">=7.3",
|
||||
"phpspec/prophecy": "^1.12.1",
|
||||
"phpunit/php-code-coverage": "^9.2",
|
||||
"phpunit/php-code-coverage": "^9.2.3",
|
||||
"phpunit/php-file-iterator": "^3.0.5",
|
||||
"phpunit/php-invoker": "^3.1.1",
|
||||
"phpunit/php-text-template": "^2.0.3",
|
||||
@ -1550,7 +1542,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "9.4-dev"
|
||||
"dev-master": "9.5-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@ -1581,7 +1573,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.4.2"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1593,7 +1585,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2020-10-19T09:23:29+00:00"
|
||||
"time": "2020-12-04T05:05:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
@ -2165,16 +2157,16 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/lines-of-code",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
|
||||
"reference": "acf76492a65401babcf5283296fa510782783a7a"
|
||||
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/acf76492a65401babcf5283296fa510782783a7a",
|
||||
"reference": "acf76492a65401babcf5283296fa510782783a7a",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
|
||||
"reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2210,7 +2202,7 @@
|
||||
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
|
||||
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.2"
|
||||
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2218,7 +2210,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2020-10-26T17:03:56+00:00"
|
||||
"time": "2020-11-28T06:42:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/object-enumerator",
|
||||
@ -2561,16 +2553,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.20.0",
|
||||
"version": "v1.22.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "f4ba089a5b6366e453971d3aad5fe8e897b37f41"
|
||||
"reference": "c6c942b1ac76c82448322025e084cadc56048b4e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f4ba089a5b6366e453971d3aad5fe8e897b37f41",
|
||||
"reference": "f4ba089a5b6366e453971d3aad5fe8e897b37f41",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e",
|
||||
"reference": "c6c942b1ac76c82448322025e084cadc56048b4e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2582,7 +2574,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.20-dev"
|
||||
"dev-main": "1.22-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@ -2620,7 +2612,7 @@
|
||||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.20.0"
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2636,7 +2628,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-10-23T14:02:19+00:00"
|
||||
"time": "2021-01-07T16:49:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "theseer/tokenizer",
|
||||
@ -2750,7 +2742,6 @@
|
||||
"platform": {
|
||||
"php": ">=7.3.0",
|
||||
"php-64bit": "*",
|
||||
"ext-bcmath": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-ctype": "*",
|
||||
"ext-date": "*",
|
||||
|
@ -17,6 +17,7 @@ includes:
|
||||
parameters:
|
||||
level: 8
|
||||
checkExplicitMixed: true
|
||||
checkMissingCallableSignature: true
|
||||
bootstrapFiles:
|
||||
- tests/phpstan/bootstrap.php
|
||||
scanDirectories:
|
||||
|
@ -28,6 +28,7 @@ use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
||||
use pocketmine\plugin\PluginBase;
|
||||
use pocketmine\plugin\PluginLoadOrder;
|
||||
use pocketmine\plugin\PluginManager;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\VersionString;
|
||||
use function base64_encode;
|
||||
@ -46,6 +47,7 @@ use function is_resource;
|
||||
use function json_encode;
|
||||
use function json_last_error_msg;
|
||||
use function max;
|
||||
use function microtime;
|
||||
use function mkdir;
|
||||
use function ob_end_clean;
|
||||
use function ob_get_contents;
|
||||
@ -58,7 +60,6 @@ use function sprintf;
|
||||
use function str_split;
|
||||
use function strpos;
|
||||
use function substr;
|
||||
use function time;
|
||||
use function zend_version;
|
||||
use function zlib_encode;
|
||||
use const E_COMPILE_ERROR;
|
||||
@ -89,7 +90,7 @@ class CrashDump{
|
||||
* having their content changed, version format changing, etc.
|
||||
* It is not necessary to increase this when adding new fields.
|
||||
*/
|
||||
private const FORMAT_VERSION = 3;
|
||||
private const FORMAT_VERSION = 4;
|
||||
|
||||
private const PLUGIN_INVOLVEMENT_NONE = "none";
|
||||
private const PLUGIN_INVOLVEMENT_DIRECT = "direct";
|
||||
@ -99,7 +100,7 @@ class CrashDump{
|
||||
private $server;
|
||||
/** @var resource */
|
||||
private $fp;
|
||||
/** @var int */
|
||||
/** @var float */
|
||||
private $time;
|
||||
/**
|
||||
* @var mixed[]
|
||||
@ -112,12 +113,12 @@ class CrashDump{
|
||||
private $path;
|
||||
|
||||
public function __construct(Server $server){
|
||||
$this->time = time();
|
||||
$this->time = microtime(true);
|
||||
$this->server = $server;
|
||||
if(!is_dir($this->server->getDataPath() . "crashdumps")){
|
||||
mkdir($this->server->getDataPath() . "crashdumps");
|
||||
}
|
||||
$this->path = $this->server->getDataPath() . "crashdumps/" . date("D_M_j-H.i.s-T_Y", $this->time) . ".log";
|
||||
$this->path = $this->server->getDataPath() . "crashdumps/" . date("D_M_j-H.i.s-T_Y", (int) $this->time) . ".log";
|
||||
$fp = @fopen($this->path, "wb");
|
||||
if(!is_resource($fp)){
|
||||
throw new \RuntimeException("Could not create Crash Dump");
|
||||
@ -125,7 +126,8 @@ class CrashDump{
|
||||
$this->fp = $fp;
|
||||
$this->data["format_version"] = self::FORMAT_VERSION;
|
||||
$this->data["time"] = $this->time;
|
||||
$this->addLine($this->server->getName() . " Crash Dump " . date("D M j H:i:s T Y", $this->time));
|
||||
$this->data["uptime"] = $this->time - \pocketmine\START_TIME;
|
||||
$this->addLine($this->server->getName() . " Crash Dump " . date("D M j H:i:s T Y", (int) $this->time));
|
||||
$this->addLine();
|
||||
$this->baseCrash();
|
||||
$this->generalData();
|
||||
@ -166,7 +168,9 @@ class CrashDump{
|
||||
if($json === false){
|
||||
throw new \RuntimeException("Failed to encode crashdump JSON: " . json_last_error_msg());
|
||||
}
|
||||
$this->encodedData = zlib_encode($json, ZLIB_ENCODING_DEFLATE, 9);
|
||||
$zlibEncoded = zlib_encode($json, ZLIB_ENCODING_DEFLATE, 9);
|
||||
if($zlibEncoded === false) throw new AssumptionFailedError("ZLIB compression failed");
|
||||
$this->encodedData = $zlibEncoded;
|
||||
foreach(str_split(base64_encode($this->encodedData), 76) as $line){
|
||||
$this->addLine($line);
|
||||
}
|
||||
@ -310,8 +314,8 @@ class CrashDump{
|
||||
}
|
||||
|
||||
private function determinePluginFromFile(string $filePath, bool $crashFrame) : bool{
|
||||
$frameCleanPath = Utils::cleanPath($filePath); //this will be empty in phar stub
|
||||
if(strpos($frameCleanPath, "plugins") === 0 and file_exists($filePath)){
|
||||
$frameCleanPath = Utils::cleanPath($filePath);
|
||||
if(strpos($frameCleanPath, Utils::CLEAN_PATH_SRC_PREFIX) !== 0){
|
||||
$this->addLine();
|
||||
if($crashFrame){
|
||||
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
|
||||
@ -321,15 +325,17 @@ class CrashDump{
|
||||
$this->data["plugin_involvement"] = self::PLUGIN_INVOLVEMENT_INDIRECT;
|
||||
}
|
||||
|
||||
$reflection = new \ReflectionClass(PluginBase::class);
|
||||
$file = $reflection->getProperty("file");
|
||||
$file->setAccessible(true);
|
||||
foreach($this->server->getPluginManager()->getPlugins() as $plugin){
|
||||
$filePath = Utils::cleanPath($file->getValue($plugin));
|
||||
if(strpos($frameCleanPath, $filePath) === 0){
|
||||
$this->data["plugin"] = $plugin->getName();
|
||||
$this->addLine("BAD PLUGIN: " . $plugin->getDescription()->getFullName());
|
||||
break;
|
||||
if(file_exists($filePath)){
|
||||
$reflection = new \ReflectionClass(PluginBase::class);
|
||||
$file = $reflection->getProperty("file");
|
||||
$file->setAccessible(true);
|
||||
foreach($this->server->getPluginManager()->getPlugins() as $plugin){
|
||||
$filePath = Utils::cleanPath($file->getValue($plugin));
|
||||
if(strpos($frameCleanPath, $filePath) === 0){
|
||||
$this->data["plugin"] = $plugin->getName();
|
||||
$this->addLine("BAD PLUGIN: " . $plugin->getDescription()->getFullName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -100,6 +100,7 @@ use pocketmine\nbt\tag\ByteTag;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\DoubleTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\network\mcpe\convert\ItemTypeDictionary;
|
||||
use pocketmine\network\mcpe\PlayerNetworkSessionAdapter;
|
||||
use pocketmine\network\mcpe\protocol\ActorEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
|
||||
@ -148,6 +149,7 @@ use pocketmine\network\mcpe\protocol\types\CommandEnum;
|
||||
use pocketmine\network\mcpe\protocol\types\CommandParameter;
|
||||
use pocketmine\network\mcpe\protocol\types\ContainerIds;
|
||||
use pocketmine\network\mcpe\protocol\types\DimensionIds;
|
||||
use pocketmine\network\mcpe\protocol\types\Experiments;
|
||||
use pocketmine\network\mcpe\protocol\types\GameMode;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\UIInventorySlotOffset;
|
||||
use pocketmine\network\mcpe\protocol\types\NetworkInventoryAction;
|
||||
@ -1939,7 +1941,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$animation["ImageWidth"],
|
||||
base64_decode($animation["Image"], true)),
|
||||
$animation["Type"],
|
||||
$animation["Frames"]
|
||||
$animation["Frames"],
|
||||
$animation["AnimationExpression"]
|
||||
);
|
||||
}
|
||||
|
||||
@ -2179,6 +2182,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
//but it does have an annoying side-effect when true: it makes
|
||||
//the client remove its own non-server-supplied resource packs.
|
||||
$pk->mustAccept = false;
|
||||
$pk->experiments = new Experiments([], false);
|
||||
$this->dataPacket($pk);
|
||||
break;
|
||||
case ResourcePackClientResponsePacket::STATUS_COMPLETED:
|
||||
@ -2244,6 +2248,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$pk->commandsEnabled = true;
|
||||
$pk->levelId = "";
|
||||
$pk->worldName = $this->server->getMotd();
|
||||
$pk->experiments = new Experiments([], false);
|
||||
$pk->itemTable = ItemTypeDictionary::getInstance()->getEntries();
|
||||
$this->dataPacket($pk);
|
||||
|
||||
$this->sendDataPacket(new AvailableActorIdentifiersPacket());
|
||||
@ -2870,7 +2876,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
|
||||
public function handlePlayerAction(PlayerActionPacket $packet) : bool{
|
||||
if(!$this->spawned or (!$this->isAlive() and $packet->action !== PlayerActionPacket::ACTION_RESPAWN and $packet->action !== PlayerActionPacket::ACTION_DIMENSION_CHANGE_REQUEST)){
|
||||
if(!$this->spawned or (!$this->isAlive() and $packet->action !== PlayerActionPacket::ACTION_RESPAWN)){
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2957,7 +2963,10 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
case PlayerActionPacket::ACTION_STOP_SWIMMING:
|
||||
//TODO: handle this when it doesn't spam every damn tick (yet another spam bug!!)
|
||||
break;
|
||||
case PlayerActionPacket::ACTION_INTERACT_BLOCK: //ignored (for now)
|
||||
case PlayerActionPacket::ACTION_INTERACT_BLOCK: //TODO: ignored (for now)
|
||||
break;
|
||||
case PlayerActionPacket::ACTION_CREATIVE_PLAYER_DESTROY_BLOCK:
|
||||
//TODO: do we need to handle this?
|
||||
break;
|
||||
default:
|
||||
$this->server->getLogger()->debug("Unhandled/unknown player action type " . $packet->action . " from " . $this->getName());
|
||||
@ -3039,6 +3048,12 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @var int|null */
|
||||
private $closingWindowId = null;
|
||||
|
||||
/** @internal */
|
||||
public function getClosingWindowId() : ?int{ return $this->closingWindowId; }
|
||||
|
||||
public function handleContainerClose(ContainerClosePacket $packet) : bool{
|
||||
if(!$this->spawned){
|
||||
return true;
|
||||
@ -3050,12 +3065,15 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
unset($this->openHardcodedWindows[$packet->windowId]);
|
||||
$pk = new ContainerClosePacket();
|
||||
$pk->windowId = $packet->windowId;
|
||||
$pk->server = false;
|
||||
$this->sendDataPacket($pk);
|
||||
return true;
|
||||
}
|
||||
if(isset($this->windowIndex[$packet->windowId])){
|
||||
$this->closingWindowId = $packet->windowId;
|
||||
(new InventoryCloseEvent($this->windowIndex[$packet->windowId], $this))->call();
|
||||
$this->removeWindow($this->windowIndex[$packet->windowId]);
|
||||
$this->closingWindowId = null;
|
||||
//removeWindow handles sending the appropriate
|
||||
return true;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine {
|
||||
|
||||
use Composer\InstalledVersions;
|
||||
use pocketmine\utils\Git;
|
||||
use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\Process;
|
||||
@ -73,7 +74,6 @@ namespace pocketmine {
|
||||
}
|
||||
|
||||
$extensions = [
|
||||
"bcmath" => "BC Math",
|
||||
"curl" => "cURL",
|
||||
"ctype" => "ctype",
|
||||
"date" => "Date",
|
||||
@ -206,6 +206,19 @@ namespace pocketmine {
|
||||
|
||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||
|
||||
$composerGitHash = InstalledVersions::getReference('pocketmine/pocketmine-mp');
|
||||
if($composerGitHash !== null){
|
||||
$currentGitHash = explode("-", \pocketmine\GIT_COMMIT)[0];
|
||||
if($currentGitHash !== $composerGitHash){
|
||||
critical_error("Composer dependencies and/or autoloader are out of sync.");
|
||||
critical_error("- Current revision is $currentGitHash");
|
||||
critical_error("- Composer dependencies were last synchronized for revision $composerGitHash");
|
||||
critical_error("Out-of-sync Composer dependencies may result in crashes and classes not being found.");
|
||||
critical_error("Please synchronize Composer dependencies before running the server.");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]);
|
||||
|
||||
define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR);
|
||||
@ -280,7 +293,7 @@ namespace pocketmine {
|
||||
|
||||
if(ThreadManager::getInstance()->stopAll() > 0){
|
||||
$logger->debug("Some threads could not be stopped, performing a force-kill");
|
||||
Process::kill(getmypid());
|
||||
Process::kill(Process::pid());
|
||||
}
|
||||
}while(false);
|
||||
|
||||
@ -300,7 +313,5 @@ namespace pocketmine {
|
||||
exit($exitCode);
|
||||
}
|
||||
|
||||
if(!defined('pocketmine\_PHPSTAN_ANALYSIS')){
|
||||
\pocketmine\server();
|
||||
}
|
||||
\pocketmine\server();
|
||||
}
|
||||
|
@ -126,7 +126,6 @@ use function file_put_contents;
|
||||
use function filemtime;
|
||||
use function function_exists;
|
||||
use function get_class;
|
||||
use function getmypid;
|
||||
use function getopt;
|
||||
use function gettype;
|
||||
use function implode;
|
||||
@ -1939,7 +1938,7 @@ class Server{
|
||||
}catch(\Throwable $e){
|
||||
$this->logger->logException($e);
|
||||
$this->logger->emergency("Crashed while crashing, killing process");
|
||||
@Process::kill(getmypid());
|
||||
@Process::kill(Process::pid());
|
||||
}
|
||||
|
||||
}
|
||||
@ -2132,7 +2131,7 @@ class Server{
|
||||
echo "--- Waiting $spacing seconds to throttle automatic restart (you can kill the process safely now) ---" . PHP_EOL;
|
||||
sleep($spacing);
|
||||
}
|
||||
@Process::kill(getmypid());
|
||||
@Process::kill(Process::pid());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,6 @@ if(defined('pocketmine\_VERSION_INFO_INCLUDED')){
|
||||
const _VERSION_INFO_INCLUDED = true;
|
||||
|
||||
const NAME = "PocketMine-MP";
|
||||
const BASE_VERSION = "3.15.4";
|
||||
const BASE_VERSION = "3.17.3";
|
||||
const IS_DEVELOPMENT_BUILD = false;
|
||||
const BUILD_NUMBER = 0;
|
||||
|
@ -35,5 +35,6 @@ interface BlockToolType{
|
||||
public const TYPE_PICKAXE = 1 << 2;
|
||||
public const TYPE_AXE = 1 << 3;
|
||||
public const TYPE_SHEARS = 1 << 4;
|
||||
public const TYPE_HOE = 1 << 5;
|
||||
|
||||
}
|
||||
|
@ -31,6 +31,10 @@ class Sponge extends Solid{
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_HOE;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.6;
|
||||
}
|
||||
|
@ -77,7 +77,6 @@ use function abs;
|
||||
use function assert;
|
||||
use function cos;
|
||||
use function count;
|
||||
use function current;
|
||||
use function deg2rad;
|
||||
use function floor;
|
||||
use function fmod;
|
||||
@ -334,8 +333,8 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
*/
|
||||
private static $knownEntities = [];
|
||||
/**
|
||||
* @var string[][]
|
||||
* @phpstan-var array<class-string<Entity>, list<string>>
|
||||
* @var string[]
|
||||
* @phpstan-var array<class-string<Entity>, string>
|
||||
*/
|
||||
private static $saveNames = [];
|
||||
|
||||
@ -414,7 +413,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
self::$knownEntities[$name] = $className;
|
||||
}
|
||||
|
||||
self::$saveNames[$className] = $saveNames;
|
||||
self::$saveNames[$className] = reset($saveNames);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -872,8 +871,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
if(!isset(self::$saveNames[static::class])){
|
||||
throw new \InvalidStateException("Entity " . static::class . " is not registered");
|
||||
}
|
||||
reset(self::$saveNames[static::class]);
|
||||
return current(self::$saveNames[static::class]);
|
||||
return self::$saveNames[static::class];
|
||||
}
|
||||
|
||||
public function saveNBT() : void{
|
||||
|
@ -300,17 +300,20 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
if($consumable instanceof MaybeConsumable and !$consumable->canBeConsumed()){
|
||||
return false;
|
||||
}
|
||||
if($consumable instanceof FoodSource && $consumable->requiresHunger() and !$this->isHungry()){
|
||||
return false;
|
||||
}
|
||||
|
||||
return parent::consumeObject($consumable);
|
||||
}
|
||||
|
||||
protected function applyConsumptionResults(Consumable $consumable) : void{
|
||||
if($consumable instanceof FoodSource){
|
||||
if($consumable->requiresHunger() and !$this->isHungry()){
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->addFood($consumable->getFoodRestore());
|
||||
$this->addSaturation($consumable->getSaturationRestore());
|
||||
}
|
||||
|
||||
return parent::consumeObject($consumable);
|
||||
parent::applyConsumptionResults($consumable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -363,13 +363,20 @@ abstract class Living extends Entity implements Damageable{
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->applyConsumptionResults($consumable);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies effects from consuming the object. This shouldn't do any can-consume checks (those are expected to be
|
||||
* handled by the caller).
|
||||
*/
|
||||
protected function applyConsumptionResults(Consumable $consumable) : void{
|
||||
foreach($consumable->getAdditionalEffects() as $effect){
|
||||
$this->addEffect($effect);
|
||||
}
|
||||
|
||||
$consumable->onConsume($this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,14 +39,22 @@ class PlayerCreationEvent extends Event{
|
||||
/** @var int */
|
||||
private $port;
|
||||
|
||||
/** @var string */
|
||||
/**
|
||||
* @var string
|
||||
* @phpstan-var class-string<Player>
|
||||
*/
|
||||
private $baseClass;
|
||||
/** @var string */
|
||||
/**
|
||||
* @var string
|
||||
* @phpstan-var class-string<Player>
|
||||
*/
|
||||
private $playerClass;
|
||||
|
||||
/**
|
||||
* @param string $baseClass
|
||||
* @param string $playerClass
|
||||
* @phpstan-param class-string<Player> $baseClass
|
||||
* @phpstan-param class-string<Player> $playerClass
|
||||
*/
|
||||
public function __construct(SourceInterface $interface, $baseClass, $playerClass, string $address, int $port){
|
||||
$this->interface = $interface;
|
||||
@ -80,6 +88,7 @@ class PlayerCreationEvent extends Event{
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @phpstan-return class-string<Player>
|
||||
*/
|
||||
public function getBaseClass(){
|
||||
return $this->baseClass;
|
||||
@ -87,6 +96,7 @@ class PlayerCreationEvent extends Event{
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @phpstan-param class-string<Player> $class
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@ -100,6 +110,7 @@ class PlayerCreationEvent extends Event{
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @phpstan-return class-string<Player>
|
||||
*/
|
||||
public function getPlayerClass(){
|
||||
return $this->playerClass;
|
||||
@ -107,6 +118,7 @@ class PlayerCreationEvent extends Event{
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @phpstan-param class-string<Player> $class
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
@ -64,6 +64,7 @@ abstract class ContainerInventory extends BaseInventory{
|
||||
public function onClose(Player $who) : void{
|
||||
$pk = new ContainerClosePacket();
|
||||
$pk->windowId = $who->getWindowId($this);
|
||||
$pk->server = $who->getClosingWindowId() !== $pk->windowId;
|
||||
$who->dataPacket($pk);
|
||||
parent::onClose($who);
|
||||
}
|
||||
|
@ -163,6 +163,7 @@ class CraftingTransaction extends InventoryTransaction{
|
||||
*/
|
||||
$pk = new ContainerClosePacket();
|
||||
$pk->windowId = Player::HARDCODED_CRAFTING_GRID_WINDOW_ID;
|
||||
$pk->server = true;
|
||||
$this->source->dataPacket($pk);
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,14 @@ class Bucket extends Item implements MaybeConsumable{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getFuelResidue() : Item{
|
||||
if($this->meta === Block::LAVA or $this->meta === Block::FLOWING_LAVA){
|
||||
return ItemFactory::get(Item::BUCKET);
|
||||
}
|
||||
|
||||
return parent::getFuelResidue();
|
||||
}
|
||||
|
||||
public function onActivate(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector) : bool{
|
||||
$resultBlock = BlockFactory::get($this->meta);
|
||||
|
||||
|
@ -23,11 +23,24 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\item;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\BlockToolType;
|
||||
use pocketmine\entity\Entity;
|
||||
|
||||
class Hoe extends TieredTool{
|
||||
|
||||
public function getBlockToolType() : int{
|
||||
return BlockToolType::TYPE_HOE;
|
||||
}
|
||||
|
||||
public function onAttackEntity(Entity $victim) : bool{
|
||||
return $this->applyDamage(1);
|
||||
}
|
||||
|
||||
public function onDestroyBlock(Block $block) : bool{
|
||||
if($block->getHardness() > 0){
|
||||
return $this->applyDamage(1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -655,6 +655,16 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an item after burning fuel
|
||||
*/
|
||||
public function getFuelResidue() : Item{
|
||||
$item = clone $this;
|
||||
$item->pop();
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how many points of damage this item will deal to an entity when used as a weapon.
|
||||
*/
|
||||
|
@ -99,6 +99,8 @@ abstract class Biome{
|
||||
self::register(self::SWAMP, new SwampBiome());
|
||||
self::register(self::RIVER, new RiverBiome());
|
||||
|
||||
self::register(self::HELL, new HellBiome());
|
||||
|
||||
self::register(self::ICE_PLAINS, new IcePlainsBiome());
|
||||
|
||||
self::register(self::SMALL_MOUNTAINS, new SmallMountainsBiome());
|
||||
|
@ -921,7 +921,9 @@ class Chunk{
|
||||
|
||||
$biomeIds = $stream->get(256);
|
||||
if($lightPopulated){
|
||||
$heightMap = array_values(unpack("v*", $stream->get(512)));
|
||||
/** @var int[] $unpackedHeightMap */
|
||||
$unpackedHeightMap = unpack("v*", $stream->get(512)); //unpack() will never fail here
|
||||
$heightMap = array_values($unpackedHeightMap);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,6 @@ abstract class LevelProviderManager{
|
||||
throw new \InvalidArgumentException("Class $class cannot be constructed");
|
||||
}
|
||||
|
||||
/** @var LevelProvider $class */
|
||||
self::$providers[strtolower($class::getProviderName())] = $class;
|
||||
}
|
||||
|
||||
|
@ -368,7 +368,9 @@ class LevelDB extends BaseLevelProvider{
|
||||
if(($maps2d = $this->db->get($index . self::TAG_DATA_2D)) !== false){
|
||||
$binaryStream->setBuffer($maps2d, 0);
|
||||
|
||||
$heightMap = array_values(unpack("v*", $binaryStream->get(512)));
|
||||
/** @var int[] $unpackedHeightMap */
|
||||
$unpackedHeightMap = unpack("v*", $binaryStream->get(512)); //unpack() will never fail here
|
||||
$heightMap = array_values($unpackedHeightMap);
|
||||
$biomeIds = $binaryStream->get(256);
|
||||
}
|
||||
break;
|
||||
@ -411,8 +413,13 @@ class LevelDB extends BaseLevelProvider{
|
||||
$subChunks[$yy] = new SubChunk($ids, $data, $skyLight, $blockLight);
|
||||
}
|
||||
|
||||
$heightMap = array_values(unpack("C*", $binaryStream->get(256)));
|
||||
$biomeIds = ChunkUtils::convertBiomeColors(array_values(unpack("N*", $binaryStream->get(1024))));
|
||||
/** @var int[] $unpackedHeightMap */
|
||||
$unpackedHeightMap = unpack("C*", $binaryStream->get(256)); //unpack() will never fail here, but static analysers don't know that
|
||||
$heightMap = array_values($unpackedHeightMap);
|
||||
|
||||
/** @var int[] $unpackedBiomeIds */
|
||||
$unpackedBiomeIds = unpack("N*", $binaryStream->get(1024)); //nor here
|
||||
$biomeIds = ChunkUtils::convertBiomeColors(array_values($unpackedBiomeIds));
|
||||
break;
|
||||
default:
|
||||
//TODO: set chunks read-only so the version on disk doesn't get overwritten
|
||||
|
@ -182,7 +182,9 @@ class McRegion extends BaseLevelProvider{
|
||||
|
||||
$heightMap = [];
|
||||
if($chunk->hasTag("HeightMap", ByteArrayTag::class)){
|
||||
$heightMap = array_values(unpack("C*", $chunk->getByteArray("HeightMap")));
|
||||
/** @var int[] $unpackedHeightMap */
|
||||
$unpackedHeightMap = unpack("C*", $chunk->getByteArray("HeightMap")); //unpack() will never fail here
|
||||
$heightMap = array_values($unpackedHeightMap);
|
||||
}elseif($chunk->hasTag("HeightMap", IntArrayTag::class)){
|
||||
$heightMap = $chunk->getIntArray("HeightMap"); #blameshoghicp
|
||||
}
|
||||
@ -391,6 +393,9 @@ class McRegion extends BaseLevelProvider{
|
||||
self::getRegionIndex($chunkX, $chunkZ, $regionX, $regionZ);
|
||||
assert(is_int($regionX) and is_int($regionZ));
|
||||
|
||||
if(!file_exists($this->pathToRegion($regionX, $regionZ))){
|
||||
return null;
|
||||
}
|
||||
$this->loadRegion($regionX, $regionZ);
|
||||
|
||||
$chunkData = $this->getRegion($regionX, $regionZ)->readChunk($chunkX & 0x1f, $chunkZ & 0x1f);
|
||||
|
@ -27,7 +27,8 @@ use pocketmine\level\format\ChunkException;
|
||||
use pocketmine\level\format\io\exception\CorruptedChunkException;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\BinaryDataException;
|
||||
use pocketmine\utils\BinaryStream;
|
||||
use function assert;
|
||||
use function ceil;
|
||||
use function chr;
|
||||
@ -146,37 +147,34 @@ class RegionLoader{
|
||||
|
||||
fseek($this->filePointer, $this->locationTable[$index]->getFirstSector() << 12);
|
||||
|
||||
$prefix = fread($this->filePointer, 4);
|
||||
if($prefix === false or strlen($prefix) !== 4){
|
||||
throw new CorruptedChunkException("Corrupted chunk header detected (unexpected end of file reading length prefix)");
|
||||
}
|
||||
$length = Binary::readInt($prefix);
|
||||
/*
|
||||
* this might cause us to read some junk, but under normal circumstances it won't be any more than 4096 bytes wasted.
|
||||
* doing this in a single call is faster than making two seeks and reads to fetch the chunk.
|
||||
* this relies on the assumption that the end of the file is always padded to a multiple of 4096 bytes.
|
||||
*/
|
||||
$bytesToRead = $this->locationTable[$index]->getSectorCount() << 12;
|
||||
$payload = fread($this->filePointer, $bytesToRead);
|
||||
|
||||
if($length <= 0){ //TODO: if we reached here, the locationTable probably needs updating
|
||||
return null;
|
||||
}
|
||||
if($length > self::MAX_SECTOR_LENGTH){ //corrupted
|
||||
throw new CorruptedChunkException("Length for chunk x=$x,z=$z ($length) is larger than maximum " . self::MAX_SECTOR_LENGTH);
|
||||
if($payload === false || strlen($payload) !== $bytesToRead){
|
||||
throw new CorruptedChunkException("Corrupted chunk detected (unexpected EOF, truncated or non-padded chunk found)");
|
||||
}
|
||||
$stream = new BinaryStream($payload);
|
||||
|
||||
if($length > ($this->locationTable[$index]->getSectorCount() << 12)){ //Invalid chunk, bigger than defined number of sectors
|
||||
MainLogger::getLogger()->error("Chunk x=$x,z=$z length mismatch (expected " . ($this->locationTable[$index]->getSectorCount() << 12) . " sectors, got $length sectors)");
|
||||
$old = $this->locationTable[$index];
|
||||
$this->locationTable[$index] = new RegionLocationTableEntry($old->getFirstSector(), $length >> 12, time());
|
||||
$this->writeLocationIndex($index);
|
||||
}
|
||||
try{
|
||||
$length = $stream->getInt();
|
||||
if($length <= 0){ //TODO: if we reached here, the locationTable probably needs updating
|
||||
return null;
|
||||
}
|
||||
|
||||
$chunkData = fread($this->filePointer, $length);
|
||||
if($chunkData === false or strlen($chunkData) !== $length){
|
||||
throw new CorruptedChunkException("Corrupted chunk detected (unexpected end of file reading chunk data)");
|
||||
}
|
||||
$compression = $stream->getByte();
|
||||
if($compression !== self::COMPRESSION_ZLIB and $compression !== self::COMPRESSION_GZIP){
|
||||
throw new CorruptedChunkException("Invalid compression type (got $compression, expected " . self::COMPRESSION_ZLIB . " or " . self::COMPRESSION_GZIP . ")");
|
||||
}
|
||||
|
||||
$compression = ord($chunkData[0]);
|
||||
if($compression !== self::COMPRESSION_ZLIB and $compression !== self::COMPRESSION_GZIP){
|
||||
throw new CorruptedChunkException("Invalid compression type (got $compression, expected " . self::COMPRESSION_ZLIB . " or " . self::COMPRESSION_GZIP . ")");
|
||||
return $stream->get($length - 1); //length prefix includes the compression byte
|
||||
}catch(BinaryDataException $e){
|
||||
throw new CorruptedChunkException("Corrupted chunk detected: " . $e->getMessage(), 0, $e);
|
||||
}
|
||||
|
||||
return substr($chunkData, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -186,6 +184,23 @@ class RegionLoader{
|
||||
return $this->isChunkGenerated(self::getChunkOffset($x, $z));
|
||||
}
|
||||
|
||||
private function disposeGarbageArea(RegionLocationTableEntry $oldLocation) : void{
|
||||
/* release the area containing the old copy to the garbage pool */
|
||||
$this->garbageTable->add($oldLocation);
|
||||
|
||||
$endGarbage = $this->garbageTable->end();
|
||||
$nextSector = $this->nextSector;
|
||||
for(; $endGarbage !== null and $endGarbage->getLastSector() + 1 === $nextSector; $endGarbage = $this->garbageTable->end()){
|
||||
$nextSector = $endGarbage->getFirstSector();
|
||||
$this->garbageTable->remove($endGarbage);
|
||||
}
|
||||
|
||||
if($nextSector !== $this->nextSector){
|
||||
$this->nextSector = $nextSector;
|
||||
ftruncate($this->filePointer, $this->nextSector << 12);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @throws ChunkException
|
||||
@ -230,20 +245,7 @@ class RegionLoader{
|
||||
$this->writeLocationIndex($index);
|
||||
|
||||
if($oldLocation !== null){
|
||||
/* release the area containing the old copy to the garbage pool */
|
||||
$this->garbageTable->add($oldLocation);
|
||||
|
||||
$endGarbage = $this->garbageTable->end();
|
||||
$nextSector = $this->nextSector;
|
||||
for(; $endGarbage !== null and $endGarbage->getLastSector() + 1 === $nextSector; $endGarbage = $this->garbageTable->end()){
|
||||
$nextSector = $endGarbage->getFirstSector();
|
||||
$this->garbageTable->remove($endGarbage);
|
||||
}
|
||||
|
||||
if($nextSector !== $this->nextSector){
|
||||
$this->nextSector = $nextSector;
|
||||
ftruncate($this->filePointer, $this->nextSector << 12);
|
||||
}
|
||||
$this->disposeGarbageArea($oldLocation);
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,8 +255,12 @@ class RegionLoader{
|
||||
*/
|
||||
public function removeChunk(int $x, int $z){
|
||||
$index = self::getChunkOffset($x, $z);
|
||||
$oldLocation = $this->locationTable[$index];
|
||||
$this->locationTable[$index] = null;
|
||||
$this->writeLocationIndex($index);
|
||||
if($oldLocation !== null){
|
||||
$this->disposeGarbageArea($oldLocation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -336,6 +342,8 @@ class RegionLoader{
|
||||
/** @var int[] $usedOffsets */
|
||||
$usedOffsets = [];
|
||||
|
||||
$fileSize = filesize($this->filePath);
|
||||
if($fileSize === false) throw new AssumptionFailedError("filesize() should not return false here");
|
||||
for($i = 0; $i < 1024; ++$i){
|
||||
$entry = $this->locationTable[$i];
|
||||
if($entry === null){
|
||||
@ -348,8 +356,7 @@ class RegionLoader{
|
||||
|
||||
//TODO: more validity checks
|
||||
|
||||
fseek($this->filePointer, $fileOffset);
|
||||
if(feof($this->filePointer)){
|
||||
if($fileOffset >= $fileSize){
|
||||
throw new CorruptedRegionException("Region file location offset x=$x,z=$z points to invalid file location $fileOffset");
|
||||
}
|
||||
if(isset($usedOffsets[$offset])){
|
||||
|
@ -29,7 +29,10 @@ namespace pocketmine\metadata;
|
||||
use pocketmine\plugin\Plugin;
|
||||
|
||||
abstract class MetadataStore{
|
||||
/** @var \SplObjectStorage[]|MetadataValue[][] */
|
||||
/**
|
||||
* @var \SplObjectStorage[]|MetadataValue[][]
|
||||
* @phpstan-var array<string, \SplObjectStorage<Plugin, MetadataValue>>
|
||||
*/
|
||||
private $metadataMap;
|
||||
|
||||
/**
|
||||
@ -41,6 +44,7 @@ abstract class MetadataStore{
|
||||
$owningPlugin = $newMetadataValue->getOwningPlugin();
|
||||
|
||||
if(!isset($this->metadataMap[$key])){
|
||||
/** @phpstan-var \SplObjectStorage<Plugin, MetadataValue> $entry */
|
||||
$entry = new \SplObjectStorage();
|
||||
$this->metadataMap[$key] = $entry;
|
||||
}else{
|
||||
@ -92,7 +96,6 @@ abstract class MetadataStore{
|
||||
* @return void
|
||||
*/
|
||||
public function invalidateAll(Plugin $owningPlugin){
|
||||
/** @var \SplObjectStorage|MetadataValue[] $values */
|
||||
foreach($this->metadataMap as $values){
|
||||
if(isset($values[$owningPlugin])){
|
||||
$values[$owningPlugin]->invalidate();
|
||||
|
@ -35,6 +35,9 @@ use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\NetworkLittleEndianNBTStream;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\NamedTag;
|
||||
use pocketmine\network\mcpe\convert\ItemTranslator;
|
||||
use pocketmine\network\mcpe\convert\ItemTypeDictionary;
|
||||
use pocketmine\network\mcpe\protocol\types\CommandOriginData;
|
||||
use pocketmine\network\mcpe\protocol\types\EntityLink;
|
||||
use pocketmine\network\mcpe\protocol\types\GameRuleType;
|
||||
@ -47,6 +50,7 @@ use pocketmine\network\mcpe\protocol\types\StructureEditorData;
|
||||
use pocketmine\network\mcpe\protocol\types\StructureSettings;
|
||||
use pocketmine\utils\BinaryStream;
|
||||
use pocketmine\utils\UUID;
|
||||
use function assert;
|
||||
use function count;
|
||||
use function strlen;
|
||||
|
||||
@ -91,7 +95,8 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
$skinImage = $this->getSkinImage();
|
||||
$animationType = $this->getLInt();
|
||||
$animationFrames = $this->getLFloat();
|
||||
$animations[] = new SkinAnimation($skinImage, $animationType, $animationFrames);
|
||||
$expressionType = $this->getLInt();
|
||||
$animations[] = new SkinAnimation($skinImage, $animationType, $animationFrames, $expressionType);
|
||||
}
|
||||
$capeData = $this->getSkinImage();
|
||||
$geometryData = $this->getString();
|
||||
@ -143,6 +148,7 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
$this->putSkinImage($animation->getImage());
|
||||
$this->putLInt($animation->getType());
|
||||
$this->putLFloat($animation->getFrames());
|
||||
$this->putLInt($animation->getExpressionType());
|
||||
}
|
||||
$this->putSkinImage($skin->getCapeImage());
|
||||
$this->putString($skin->getGeometryData());
|
||||
@ -186,15 +192,17 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
}
|
||||
|
||||
public function getSlot() : Item{
|
||||
$id = $this->getVarInt();
|
||||
if($id === 0){
|
||||
$netId = $this->getVarInt();
|
||||
if($netId === 0){
|
||||
return ItemFactory::get(0, 0, 0);
|
||||
}
|
||||
|
||||
$auxValue = $this->getVarInt();
|
||||
$data = $auxValue >> 8;
|
||||
$netData = $auxValue >> 8;
|
||||
$cnt = $auxValue & 0xff;
|
||||
|
||||
[$id, $meta] = ItemTranslator::getInstance()->fromNetworkId($netId, $netData);
|
||||
|
||||
$nbtLen = $this->getLShort();
|
||||
|
||||
/** @var CompoundTag|null $nbt */
|
||||
@ -223,26 +231,23 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
$this->getString();
|
||||
}
|
||||
|
||||
if($id === ItemIds::SHIELD){
|
||||
if($netId === ItemTypeDictionary::getInstance()->fromStringId("minecraft:shield")){
|
||||
$this->getVarLong(); //"blocking tick" (ffs mojang)
|
||||
}
|
||||
if($nbt !== null){
|
||||
if($nbt->hasTag(self::DAMAGE_TAG, IntTag::class)){
|
||||
$data = $nbt->getInt(self::DAMAGE_TAG);
|
||||
$meta = $nbt->getInt(self::DAMAGE_TAG);
|
||||
$nbt->removeTag(self::DAMAGE_TAG);
|
||||
if($nbt->count() === 0){
|
||||
if(($conflicted = $nbt->getTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION)) !== null){
|
||||
$nbt->removeTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION);
|
||||
$conflicted->setName(self::DAMAGE_TAG);
|
||||
$nbt->setTag($conflicted);
|
||||
}elseif($nbt->count() === 0){
|
||||
$nbt = null;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if(($conflicted = $nbt->getTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION)) !== null){
|
||||
$nbt->removeTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION);
|
||||
$conflicted->setName(self::DAMAGE_TAG);
|
||||
$nbt->setTag($conflicted);
|
||||
}
|
||||
}
|
||||
end:
|
||||
return ItemFactory::get($id, $data, $cnt, $nbt);
|
||||
return ItemFactory::get($id, $meta, $cnt, $nbt);
|
||||
}
|
||||
|
||||
public function putSlot(Item $item) : void{
|
||||
@ -252,8 +257,10 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
return;
|
||||
}
|
||||
|
||||
$this->putVarInt($item->getId());
|
||||
$auxValue = (($item->getDamage() & 0x7fff) << 8) | $item->getCount();
|
||||
[$netId, $netData] = ItemTranslator::getInstance()->toNetworkId($item->getId(), $item->getDamage());
|
||||
|
||||
$this->putVarInt($netId);
|
||||
$auxValue = (($netData & 0x7fff) << 8) | $item->getCount();
|
||||
$this->putVarInt($auxValue);
|
||||
|
||||
$nbt = null;
|
||||
@ -284,20 +291,18 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
$this->putVarInt(0); //CanPlaceOn entry count (TODO)
|
||||
$this->putVarInt(0); //CanDestroy entry count (TODO)
|
||||
|
||||
if($item->getId() === ItemIds::SHIELD){
|
||||
if($netId === ItemTypeDictionary::getInstance()->fromStringId("minecraft:shield")){
|
||||
$this->putVarLong(0); //"blocking tick" (ffs mojang)
|
||||
}
|
||||
}
|
||||
|
||||
public function getRecipeIngredient() : Item{
|
||||
$id = $this->getVarInt();
|
||||
if($id === 0){
|
||||
$netId = $this->getVarInt();
|
||||
if($netId === 0){
|
||||
return ItemFactory::get(ItemIds::AIR, 0, 0);
|
||||
}
|
||||
$meta = $this->getVarInt();
|
||||
if($meta === 0x7fff){
|
||||
$meta = -1;
|
||||
}
|
||||
$netData = $this->getVarInt();
|
||||
[$id, $meta] = ItemTranslator::getInstance()->fromNetworkIdWithWildcardHandling($netId, $netData);
|
||||
$count = $this->getVarInt();
|
||||
return ItemFactory::get($id, $meta, $count);
|
||||
}
|
||||
@ -306,8 +311,14 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
if($item->isNull()){
|
||||
$this->putVarInt(0);
|
||||
}else{
|
||||
$this->putVarInt($item->getId());
|
||||
$this->putVarInt($item->getDamage() & 0x7fff);
|
||||
if($item->hasAnyDamageValue()){
|
||||
[$netId, ] = ItemTranslator::getInstance()->toNetworkId($item->getId(), 0);
|
||||
$netData = 0x7fff;
|
||||
}else{
|
||||
[$netId, $netData] = ItemTranslator::getInstance()->toNetworkId($item->getId(), $item->getDamage());
|
||||
}
|
||||
$this->putVarInt($netId);
|
||||
$this->putVarInt($netData);
|
||||
$this->putVarInt($item->getCount());
|
||||
}
|
||||
}
|
||||
@ -750,6 +761,25 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
$this->putVarInt($structureEditorData->structureRedstoneSaveMove);
|
||||
}
|
||||
|
||||
public function getNbtRoot() : NamedTag{
|
||||
$offset = $this->getOffset();
|
||||
try{
|
||||
$result = (new NetworkLittleEndianNBTStream())->read($this->getBuffer(), false, $offset, 512);
|
||||
assert($result instanceof NamedTag, "doMultiple is false so we should definitely have a NamedTag here");
|
||||
return $result;
|
||||
}finally{
|
||||
$this->setOffset($offset);
|
||||
}
|
||||
}
|
||||
|
||||
public function getNbtCompoundRoot() : CompoundTag{
|
||||
$root = $this->getNbtRoot();
|
||||
if(!($root instanceof CompoundTag)){
|
||||
throw new \UnexpectedValueException("Expected TAG_Compound root");
|
||||
}
|
||||
return $root;
|
||||
}
|
||||
|
||||
public function readGenericTypeNetworkId() : int{
|
||||
return $this->getVarInt();
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
||||
namespace pocketmine\network\mcpe;
|
||||
|
||||
use pocketmine\network\mcpe\protocol\ActorEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\ActorFallPacket;
|
||||
use pocketmine\network\mcpe\protocol\ActorPickRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\AddActorPacket;
|
||||
use pocketmine\network\mcpe\protocol\AddBehaviorTreePacket;
|
||||
@ -33,6 +32,7 @@ use pocketmine\network\mcpe\protocol\AddItemActorPacket;
|
||||
use pocketmine\network\mcpe\protocol\AddPaintingPacket;
|
||||
use pocketmine\network\mcpe\protocol\AddPlayerPacket;
|
||||
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
|
||||
use pocketmine\network\mcpe\protocol\AnimateEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\AnimatePacket;
|
||||
use pocketmine\network\mcpe\protocol\AnvilDamagePacket;
|
||||
use pocketmine\network\mcpe\protocol\AutomationClientConnectPacket;
|
||||
@ -45,6 +45,7 @@ use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\BookEditPacket;
|
||||
use pocketmine\network\mcpe\protocol\BossEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\CameraPacket;
|
||||
use pocketmine\network\mcpe\protocol\CameraShakePacket;
|
||||
use pocketmine\network\mcpe\protocol\ChangeDimensionPacket;
|
||||
use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket;
|
||||
use pocketmine\network\mcpe\protocol\ClientboundMapItemDataPacket;
|
||||
@ -60,6 +61,7 @@ use pocketmine\network\mcpe\protocol\CompletedUsingItemPacket;
|
||||
use pocketmine\network\mcpe\protocol\ContainerClosePacket;
|
||||
use pocketmine\network\mcpe\protocol\ContainerOpenPacket;
|
||||
use pocketmine\network\mcpe\protocol\ContainerSetDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\CorrectPlayerMovePredictionPacket;
|
||||
use pocketmine\network\mcpe\protocol\CraftingDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\CraftingEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\CreativeContentPacket;
|
||||
@ -70,6 +72,7 @@ use pocketmine\network\mcpe\protocol\EducationSettingsPacket;
|
||||
use pocketmine\network\mcpe\protocol\EmoteListPacket;
|
||||
use pocketmine\network\mcpe\protocol\EmotePacket;
|
||||
use pocketmine\network\mcpe\protocol\EventPacket;
|
||||
use pocketmine\network\mcpe\protocol\FilterTextPacket;
|
||||
use pocketmine\network\mcpe\protocol\GameRulesChangedPacket;
|
||||
use pocketmine\network\mcpe\protocol\GuiDataPickItemPacket;
|
||||
use pocketmine\network\mcpe\protocol\HurtArmorPacket;
|
||||
@ -77,6 +80,7 @@ use pocketmine\network\mcpe\protocol\InteractPacket;
|
||||
use pocketmine\network\mcpe\protocol\InventoryContentPacket;
|
||||
use pocketmine\network\mcpe\protocol\InventorySlotPacket;
|
||||
use pocketmine\network\mcpe\protocol\InventoryTransactionPacket;
|
||||
use pocketmine\network\mcpe\protocol\ItemComponentPacket;
|
||||
use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket;
|
||||
use pocketmine\network\mcpe\protocol\ItemStackRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\ItemStackResponsePacket;
|
||||
@ -96,6 +100,7 @@ use pocketmine\network\mcpe\protocol\MobEffectPacket;
|
||||
use pocketmine\network\mcpe\protocol\MobEquipmentPacket;
|
||||
use pocketmine\network\mcpe\protocol\ModalFormRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\ModalFormResponsePacket;
|
||||
use pocketmine\network\mcpe\protocol\MotionPredictionHintsPacket;
|
||||
use pocketmine\network\mcpe\protocol\MoveActorAbsolutePacket;
|
||||
use pocketmine\network\mcpe\protocol\MoveActorDeltaPacket;
|
||||
use pocketmine\network\mcpe\protocol\MovePlayerPacket;
|
||||
@ -111,6 +116,7 @@ use pocketmine\network\mcpe\protocol\PlayerActionPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerArmorDamagePacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerAuthInputPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerEnchantOptionsPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerFogPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerHotbarPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerInputPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerListPacket;
|
||||
@ -171,7 +177,6 @@ use pocketmine\network\mcpe\protocol\TickSyncPacket;
|
||||
use pocketmine\network\mcpe\protocol\TransferPacket;
|
||||
use pocketmine\network\mcpe\protocol\UpdateAttributesPacket;
|
||||
use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
|
||||
use pocketmine\network\mcpe\protocol\UpdateBlockPropertiesPacket;
|
||||
use pocketmine\network\mcpe\protocol\UpdateBlockSyncedPacket;
|
||||
use pocketmine\network\mcpe\protocol\UpdateEquipPacket;
|
||||
use pocketmine\network\mcpe\protocol\UpdatePlayerGameTypePacket;
|
||||
@ -325,10 +330,6 @@ abstract class NetworkSession{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleActorFall(ActorFallPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleHurtArmor(HurtArmorPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
@ -705,10 +706,6 @@ abstract class NetworkSession{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleUpdateBlockProperties(UpdateBlockPropertiesPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleClientCacheBlobStatus(ClientCacheBlobStatusPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
@ -796,4 +793,32 @@ abstract class NetworkSession{
|
||||
public function handlePacketViolationWarning(PacketViolationWarningPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleMotionPredictionHints(MotionPredictionHintsPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleAnimateEntity(AnimateEntityPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleCameraShake(CameraShakePacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handlePlayerFog(PlayerFogPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleCorrectPlayerMovePrediction(CorrectPlayerMovePredictionPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleItemComponent(ItemComponentPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleFilterText(FilterTextPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ namespace pocketmine\network\mcpe;
|
||||
|
||||
use pocketmine\event\server\DataPacketReceiveEvent;
|
||||
use pocketmine\network\mcpe\protocol\ActorEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\ActorFallPacket;
|
||||
use pocketmine\network\mcpe\protocol\ActorPickRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
|
||||
use pocketmine\network\mcpe\protocol\AnimatePacket;
|
||||
@ -174,10 +173,6 @@ class PlayerNetworkSessionAdapter extends NetworkSession{
|
||||
return $this->player->handlePlayerAction($packet);
|
||||
}
|
||||
|
||||
public function handleActorFall(ActorFallPacket $packet) : bool{
|
||||
return true; //Not used
|
||||
}
|
||||
|
||||
public function handleAnimate(AnimatePacket $packet) : bool{
|
||||
return $this->player->handleAnimate($packet);
|
||||
}
|
||||
|
183
src/pocketmine/network/mcpe/convert/ItemTranslator.php
Normal file
183
src/pocketmine/network/mcpe/convert/ItemTranslator.php
Normal file
@ -0,0 +1,183 @@
|
||||
<?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\network\mcpe\convert;
|
||||
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\SingletonTrait;
|
||||
use function array_key_exists;
|
||||
use function file_get_contents;
|
||||
use function is_array;
|
||||
use function is_numeric;
|
||||
use function is_string;
|
||||
use function json_decode;
|
||||
|
||||
/**
|
||||
* This class handles translation between network item ID+metadata to PocketMine-MP internal ID+metadata and vice versa.
|
||||
*/
|
||||
final class ItemTranslator{
|
||||
use SingletonTrait;
|
||||
|
||||
/**
|
||||
* @var int[]
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
private $simpleCoreToNetMapping = [];
|
||||
/**
|
||||
* @var int[]
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
private $simpleNetToCoreMapping = [];
|
||||
|
||||
/**
|
||||
* runtimeId = array[internalId][metadata]
|
||||
* @var int[][]
|
||||
* @phpstan-var array<int, array<int, int>>
|
||||
*/
|
||||
private $complexCoreToNetMapping = [];
|
||||
/**
|
||||
* [internalId, metadata] = array[runtimeId]
|
||||
* @var int[][]
|
||||
* @phpstan-var array<int, array{int, int}>
|
||||
*/
|
||||
private $complexNetToCoreMapping = [];
|
||||
|
||||
private static function make() : self{
|
||||
$data = file_get_contents(\pocketmine\RESOURCE_PATH . '/vanilla/r16_to_current_item_map.json');
|
||||
if($data === false) throw new AssumptionFailedError("Missing required resource file");
|
||||
$json = json_decode($data, true);
|
||||
if(!is_array($json) or !isset($json["simple"], $json["complex"]) || !is_array($json["simple"]) || !is_array($json["complex"])){
|
||||
throw new AssumptionFailedError("Invalid item table format");
|
||||
}
|
||||
|
||||
$legacyStringToIntMapRaw = file_get_contents(\pocketmine\RESOURCE_PATH . '/vanilla/item_id_map.json');
|
||||
if($legacyStringToIntMapRaw === false){
|
||||
throw new AssumptionFailedError("Missing required resource file");
|
||||
}
|
||||
$legacyStringToIntMap = json_decode($legacyStringToIntMapRaw, true);
|
||||
if(!is_array($legacyStringToIntMap)){
|
||||
throw new AssumptionFailedError("Invalid mapping table format");
|
||||
}
|
||||
|
||||
/** @phpstan-var array<string, int> $simpleMappings */
|
||||
$simpleMappings = [];
|
||||
foreach($json["simple"] as $oldId => $newId){
|
||||
if(!is_string($oldId) || !is_string($newId)){
|
||||
throw new AssumptionFailedError("Invalid item table format");
|
||||
}
|
||||
$simpleMappings[$newId] = $legacyStringToIntMap[$oldId];
|
||||
}
|
||||
foreach($legacyStringToIntMap as $stringId => $intId){
|
||||
if(isset($simpleMappings[$stringId])){
|
||||
throw new \UnexpectedValueException("Old ID $stringId collides with new ID");
|
||||
}
|
||||
$simpleMappings[$stringId] = $intId;
|
||||
}
|
||||
|
||||
/** @phpstan-var array<string, array{int, int}> $complexMappings */
|
||||
$complexMappings = [];
|
||||
foreach($json["complex"] as $oldId => $map){
|
||||
if(!is_string($oldId) || !is_array($map)){
|
||||
throw new AssumptionFailedError("Invalid item table format");
|
||||
}
|
||||
foreach($map as $meta => $newId){
|
||||
if(!is_numeric($meta) || !is_string($newId)){
|
||||
throw new AssumptionFailedError("Invalid item table format");
|
||||
}
|
||||
$complexMappings[$newId] = [$legacyStringToIntMap[$oldId], (int) $meta];
|
||||
}
|
||||
}
|
||||
|
||||
return new self(ItemTypeDictionary::getInstance(), $simpleMappings, $complexMappings);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $simpleMappings
|
||||
* @param int[][] $complexMappings
|
||||
* @phpstan-param array<string, int> $simpleMappings
|
||||
* @phpstan-param array<string, array<int, int>> $complexMappings
|
||||
*/
|
||||
public function __construct(ItemTypeDictionary $dictionary, array $simpleMappings, array $complexMappings){
|
||||
foreach($dictionary->getEntries() as $entry){
|
||||
$stringId = $entry->getStringId();
|
||||
$netId = $entry->getNumericId();
|
||||
if(isset($complexMappings[$stringId])){
|
||||
[$id, $meta] = $complexMappings[$stringId];
|
||||
$this->complexCoreToNetMapping[$id][$meta] = $netId;
|
||||
$this->complexNetToCoreMapping[$netId] = [$id, $meta];
|
||||
}elseif(isset($simpleMappings[$stringId])){
|
||||
$this->simpleCoreToNetMapping[$simpleMappings[$stringId]] = $netId;
|
||||
$this->simpleNetToCoreMapping[$netId] = $simpleMappings[$stringId];
|
||||
}elseif($stringId !== "minecraft:unknown"){
|
||||
throw new \InvalidArgumentException("Unmapped entry " . $stringId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
* @phpstan-return array{int, int}
|
||||
*/
|
||||
public function toNetworkId(int $internalId, int $internalMeta) : array{
|
||||
if(isset($this->complexCoreToNetMapping[$internalId][$internalMeta])){
|
||||
return [$this->complexCoreToNetMapping[$internalId][$internalMeta], 0];
|
||||
}
|
||||
if(array_key_exists($internalId, $this->simpleCoreToNetMapping)){
|
||||
return [$this->simpleCoreToNetMapping[$internalId], $internalMeta];
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException("Unmapped ID/metadata combination $internalId:$internalMeta");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
* @phpstan-return array{int, int}
|
||||
*/
|
||||
public function fromNetworkId(int $networkId, int $networkMeta, ?bool &$isComplexMapping = null) : array{
|
||||
if(isset($this->complexNetToCoreMapping[$networkId])){
|
||||
if($networkMeta !== 0){
|
||||
throw new \UnexpectedValueException("Unexpected non-zero network meta on complex item mapping");
|
||||
}
|
||||
$isComplexMapping = true;
|
||||
return $this->complexNetToCoreMapping[$networkId];
|
||||
}
|
||||
$isComplexMapping = false;
|
||||
if(isset($this->simpleNetToCoreMapping[$networkId])){
|
||||
return [$this->simpleNetToCoreMapping[$networkId], $networkMeta];
|
||||
}
|
||||
throw new \UnexpectedValueException("Unmapped network ID/metadata combination $networkId:$networkMeta");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
* @phpstan-return array{int, int}
|
||||
*/
|
||||
public function fromNetworkIdWithWildcardHandling(int $networkId, int $networkMeta) : array{
|
||||
$isComplexMapping = false;
|
||||
if($networkMeta !== 0x7fff){
|
||||
return $this->fromNetworkId($networkId, $networkMeta);
|
||||
}
|
||||
[$id, $meta] = $this->fromNetworkId($networkId, 0, $isComplexMapping);
|
||||
return [$id, $isComplexMapping ? $meta : -1];
|
||||
}
|
||||
}
|
106
src/pocketmine/network/mcpe/convert/ItemTypeDictionary.php
Normal file
106
src/pocketmine/network/mcpe/convert/ItemTypeDictionary.php
Normal file
@ -0,0 +1,106 @@
|
||||
<?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\network\mcpe\convert;
|
||||
|
||||
use pocketmine\network\mcpe\protocol\types\ItemTypeEntry;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\SingletonTrait;
|
||||
use function array_key_exists;
|
||||
use function file_get_contents;
|
||||
use function is_array;
|
||||
use function is_bool;
|
||||
use function is_int;
|
||||
use function is_string;
|
||||
use function json_decode;
|
||||
|
||||
final class ItemTypeDictionary{
|
||||
use SingletonTrait;
|
||||
|
||||
/**
|
||||
* @var ItemTypeEntry[]
|
||||
* @phpstan-var list<ItemTypeEntry>
|
||||
*/
|
||||
private $itemTypes;
|
||||
/**
|
||||
* @var string[]
|
||||
* @phpstan-var array<int, string>
|
||||
*/
|
||||
private $intToStringIdMap = [];
|
||||
/**
|
||||
* @var int[]
|
||||
* @phpstan-var array<string, int>
|
||||
*/
|
||||
private $stringToIntMap = [];
|
||||
|
||||
private static function make() : self{
|
||||
$data = file_get_contents(\pocketmine\RESOURCE_PATH . '/vanilla/required_item_list.json');
|
||||
if($data === false) throw new AssumptionFailedError("Missing required resource file");
|
||||
$table = json_decode($data, true);
|
||||
if(!is_array($table)){
|
||||
throw new AssumptionFailedError("Invalid item list format");
|
||||
}
|
||||
|
||||
$params = [];
|
||||
foreach($table as $name => $entry){
|
||||
if(!is_array($entry) || !is_string($name) || !isset($entry["component_based"], $entry["runtime_id"]) || !is_bool($entry["component_based"]) || !is_int($entry["runtime_id"])){
|
||||
throw new AssumptionFailedError("Invalid item list format");
|
||||
}
|
||||
$params[] = new ItemTypeEntry($name, $entry["runtime_id"], $entry["component_based"]);
|
||||
}
|
||||
return new self($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ItemTypeEntry[] $itemTypes
|
||||
*/
|
||||
public function __construct(array $itemTypes){
|
||||
$this->itemTypes = $itemTypes;
|
||||
foreach($this->itemTypes as $type){
|
||||
$this->stringToIntMap[$type->getStringId()] = $type->getNumericId();
|
||||
$this->intToStringIdMap[$type->getNumericId()] = $type->getStringId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ItemTypeEntry[]
|
||||
* @phpstan-return list<ItemTypeEntry>
|
||||
*/
|
||||
public function getEntries() : array{
|
||||
return $this->itemTypes;
|
||||
}
|
||||
|
||||
public function fromStringId(string $stringId) : int{
|
||||
if(!array_key_exists($stringId, $this->stringToIntMap)){
|
||||
throw new \InvalidArgumentException("Unmapped string ID \"$stringId\"");
|
||||
}
|
||||
return $this->stringToIntMap[$stringId];
|
||||
}
|
||||
|
||||
public function fromIntId(int $intId) : string{
|
||||
if(!array_key_exists($intId, $this->intToStringIdMap)){
|
||||
throw new \InvalidArgumentException("Unmapped int ID $intId");
|
||||
}
|
||||
return $this->intToStringIdMap[$intId];
|
||||
}
|
||||
}
|
@ -27,14 +27,10 @@ use pocketmine\block\BlockIds;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\NetworkLittleEndianNBTStream;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\network\mcpe\NetworkBinaryStream;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use function file_get_contents;
|
||||
use function getmypid;
|
||||
use function json_decode;
|
||||
use function mt_rand;
|
||||
use function mt_srand;
|
||||
use function shuffle;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -53,14 +49,16 @@ final class RuntimeBlockMapping{
|
||||
}
|
||||
|
||||
public static function init() : void{
|
||||
$tag = (new NetworkLittleEndianNBTStream())->read(file_get_contents(\pocketmine\RESOURCE_PATH . "vanilla/required_block_states.nbt"));
|
||||
if(!($tag instanceof ListTag) or $tag->getTagType() !== NBT::TAG_Compound){ //this is a little redundant currently, but good for auto complete and makes phpstan happy
|
||||
throw new \RuntimeException("Invalid blockstates table, expected TAG_List<TAG_Compound> root");
|
||||
$canonicalBlockStatesFile = file_get_contents(\pocketmine\RESOURCE_PATH . "vanilla/canonical_block_states.nbt");
|
||||
if($canonicalBlockStatesFile === false){
|
||||
throw new AssumptionFailedError("Missing required resource file");
|
||||
}
|
||||
|
||||
/** @var CompoundTag[] $list */
|
||||
$list = $tag->getValue();
|
||||
self::$bedrockKnownStates = self::randomizeTable($list);
|
||||
$stream = new NetworkBinaryStream($canonicalBlockStatesFile);
|
||||
$list = [];
|
||||
while(!$stream->feof()){
|
||||
$list[] = $stream->getNbtCompoundRoot();
|
||||
}
|
||||
self::$bedrockKnownStates = $list;
|
||||
|
||||
self::setupLegacyMappings();
|
||||
}
|
||||
@ -90,7 +88,7 @@ final class RuntimeBlockMapping{
|
||||
*/
|
||||
$idToStatesMap = [];
|
||||
foreach(self::$bedrockKnownStates as $k => $state){
|
||||
$idToStatesMap[$state->getCompoundTag("block")->getString("name")][] = $k;
|
||||
$idToStatesMap[$state->getString("name")][] = $k;
|
||||
}
|
||||
foreach($legacyStateMap as $pair){
|
||||
$id = $legacyIdMap[$pair->getId()] ?? null;
|
||||
@ -105,14 +103,14 @@ final class RuntimeBlockMapping{
|
||||
$mappedState = $pair->getBlockState();
|
||||
|
||||
//TODO HACK: idiotic NBT compare behaviour on 3.x compares keys which are stored by values
|
||||
$mappedState->setName("block");
|
||||
$mappedState->setName("");
|
||||
$mappedName = $mappedState->getString("name");
|
||||
if(!isset($idToStatesMap[$mappedName])){
|
||||
throw new \RuntimeException("Mapped new state does not appear in network table");
|
||||
}
|
||||
foreach($idToStatesMap[$mappedName] as $k){
|
||||
$networkState = self::$bedrockKnownStates[$k];
|
||||
if($mappedState->equals($networkState->getCompoundTag("block"))){
|
||||
if($mappedState->equals($networkState)){
|
||||
self::registerMapping($k, $id, $data);
|
||||
continue 2;
|
||||
}
|
||||
@ -127,23 +125,6 @@ final class RuntimeBlockMapping{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Randomizes the order of the runtimeID table to prevent plugins relying on them.
|
||||
* Plugins shouldn't use this stuff anyway, but plugin devs have an irritating habit of ignoring what they
|
||||
* aren't supposed to do, so we have to deliberately break it to make them stop.
|
||||
*
|
||||
* @param CompoundTag[] $table
|
||||
*
|
||||
* @return CompoundTag[]
|
||||
*/
|
||||
private static function randomizeTable(array $table) : array{
|
||||
$postSeed = mt_rand(); //save a seed to set afterwards, to avoid poor quality randoms
|
||||
mt_srand(getmypid()); //Use a seed which is the same on all threads. This isn't a secure seed, but we don't care.
|
||||
shuffle($table);
|
||||
mt_srand($postSeed); //restore a good quality seed that isn't dependent on PID
|
||||
return $table;
|
||||
}
|
||||
|
||||
public static function toStaticRuntimeId(int $id, int $meta = 0) : int{
|
||||
self::lazyInit();
|
||||
/*
|
||||
|
108
src/pocketmine/network/mcpe/protocol/AnimateEntityPacket.php
Normal file
108
src/pocketmine/network/mcpe/protocol/AnimateEntityPacket.php
Normal file
@ -0,0 +1,108 @@
|
||||
<?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\network\mcpe\protocol;
|
||||
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use function count;
|
||||
|
||||
class AnimateEntityPacket extends DataPacket/* implements ClientboundPacket*/{
|
||||
public const NETWORK_ID = ProtocolInfo::ANIMATE_ENTITY_PACKET;
|
||||
|
||||
/** @var string */
|
||||
private $animation;
|
||||
/** @var string */
|
||||
private $nextState;
|
||||
/** @var string */
|
||||
private $stopExpression;
|
||||
/** @var string */
|
||||
private $controller;
|
||||
/** @var float */
|
||||
private $blendOutTime;
|
||||
/**
|
||||
* @var int[]
|
||||
* @phpstan-var list<int>
|
||||
*/
|
||||
private $actorRuntimeIds;
|
||||
|
||||
/**
|
||||
* @param int[] $actorRuntimeIds
|
||||
* @phpstan-param list<int> $actorRuntimeIds
|
||||
*/
|
||||
public static function create(string $animation, string $nextState, string $stopExpression, string $controller, float $blendOutTime, array $actorRuntimeIds) : self{
|
||||
$result = new self;
|
||||
$result->animation = $animation;
|
||||
$result->nextState = $nextState;
|
||||
$result->stopExpression = $stopExpression;
|
||||
$result->controller = $controller;
|
||||
$result->blendOutTime = $blendOutTime;
|
||||
$result->actorRuntimeIds = $actorRuntimeIds;
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getAnimation() : string{ return $this->animation; }
|
||||
|
||||
public function getNextState() : string{ return $this->nextState; }
|
||||
|
||||
public function getStopExpression() : string{ return $this->stopExpression; }
|
||||
|
||||
public function getController() : string{ return $this->controller; }
|
||||
|
||||
public function getBlendOutTime() : float{ return $this->blendOutTime; }
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
* @phpstan-return list<int>
|
||||
*/
|
||||
public function getActorRuntimeIds() : array{ return $this->actorRuntimeIds; }
|
||||
|
||||
protected function decodePayload() : void{
|
||||
$this->animation = $this->getString();
|
||||
$this->nextState = $this->getString();
|
||||
$this->stopExpression = $this->getString();
|
||||
$this->controller = $this->getString();
|
||||
$this->blendOutTime = $this->getLFloat();
|
||||
$this->actorRuntimeIds = [];
|
||||
for($i = 0, $len = $this->getUnsignedVarInt(); $i < $len; ++$i){
|
||||
$this->actorRuntimeIds[] = $this->getEntityRuntimeId();
|
||||
}
|
||||
}
|
||||
|
||||
protected function encodePayload() : void{
|
||||
$this->putString($this->animation);
|
||||
$this->putString($this->nextState);
|
||||
$this->putString($this->stopExpression);
|
||||
$this->putString($this->controller);
|
||||
$this->putLFloat($this->blendOutTime);
|
||||
$this->putUnsignedVarInt(count($this->actorRuntimeIds));
|
||||
foreach($this->actorRuntimeIds as $id){
|
||||
$this->putEntityRuntimeId($id);
|
||||
}
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $handler) : bool{
|
||||
return $handler->handleAnimateEntity($this);
|
||||
}
|
||||
}
|
@ -27,6 +27,7 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
use pocketmine\network\mcpe\NetworkBinaryStream;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use function assert;
|
||||
use function get_class;
|
||||
use function strlen;
|
||||
@ -72,7 +73,9 @@ class BatchPacket extends DataPacket{
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
$this->put(zlib_encode($this->payload, ZLIB_ENCODING_RAW, $this->compressionLevel));
|
||||
$encoded = zlib_encode($this->payload, ZLIB_ENCODING_RAW, $this->compressionLevel);
|
||||
if($encoded === false) throw new AssumptionFailedError("ZLIB compression failed");
|
||||
$this->put($encoded);
|
||||
}
|
||||
|
||||
/**
|
||||
|
72
src/pocketmine/network/mcpe/protocol/CameraShakePacket.php
Normal file
72
src/pocketmine/network/mcpe/protocol/CameraShakePacket.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?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\network\mcpe\protocol;
|
||||
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class CameraShakePacket extends DataPacket/* implements ClientboundPacket*/{
|
||||
public const NETWORK_ID = ProtocolInfo::CAMERA_SHAKE_PACKET;
|
||||
|
||||
public const TYPE_POSITIONAL = 0;
|
||||
public const TYPE_ROTATIONAL = 1;
|
||||
|
||||
/** @var float */
|
||||
private $intensity;
|
||||
/** @var float */
|
||||
private $duration;
|
||||
/** @var int */
|
||||
private $shakeType;
|
||||
|
||||
public static function create(float $intensity, float $duration, int $shakeType) : self{
|
||||
$result = new self;
|
||||
$result->intensity = $intensity;
|
||||
$result->duration = $duration;
|
||||
$result->shakeType = $shakeType;
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getIntensity() : float{ return $this->intensity; }
|
||||
|
||||
public function getDuration() : float{ return $this->duration; }
|
||||
|
||||
public function getShakeType() : int{ return $this->shakeType; }
|
||||
|
||||
protected function decodePayload() : void{
|
||||
$this->intensity = $this->getLFloat();
|
||||
$this->duration = $this->getLFloat();
|
||||
$this->shakeType = $this->getByte();
|
||||
}
|
||||
|
||||
protected function encodePayload() : void{
|
||||
$this->putLFloat($this->intensity);
|
||||
$this->putLFloat($this->duration);
|
||||
$this->putByte($this->shakeType);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $handler) : bool{
|
||||
return $handler->handleCameraShake($this);
|
||||
}
|
||||
}
|
@ -32,13 +32,17 @@ class ContainerClosePacket extends DataPacket{
|
||||
|
||||
/** @var int */
|
||||
public $windowId;
|
||||
/** @var bool */
|
||||
public $server = false;
|
||||
|
||||
protected function decodePayload(){
|
||||
$this->windowId = $this->getByte();
|
||||
$this->server = $this->getBool();
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
$this->putByte($this->windowId);
|
||||
$this->putBool($this->server);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
|
@ -0,0 +1,77 @@
|
||||
<?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\network\mcpe\protocol;
|
||||
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class CorrectPlayerMovePredictionPacket extends DataPacket/* implements ClientboundPacket*/{
|
||||
public const NETWORK_ID = ProtocolInfo::CORRECT_PLAYER_MOVE_PREDICTION_PACKET;
|
||||
|
||||
/** @var Vector3 */
|
||||
private $position;
|
||||
/** @var Vector3 */
|
||||
private $delta;
|
||||
/** @var bool */
|
||||
private $onGround;
|
||||
/** @var int */
|
||||
private $tick;
|
||||
|
||||
public static function create(Vector3 $position, Vector3 $delta, bool $onGround, int $tick) : self{
|
||||
$result = new self;
|
||||
$result->position = $position;
|
||||
$result->delta = $delta;
|
||||
$result->onGround = $onGround;
|
||||
$result->tick = $tick;
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getPosition() : Vector3{ return $this->position; }
|
||||
|
||||
public function getDelta() : Vector3{ return $this->delta; }
|
||||
|
||||
public function isOnGround() : bool{ return $this->onGround; }
|
||||
|
||||
public function getTick() : int{ return $this->tick; }
|
||||
|
||||
protected function decodePayload() : void{
|
||||
$this->position = $this->getVector3();
|
||||
$this->delta = $this->getVector3();
|
||||
$this->onGround = $this->getBool();
|
||||
$this->tick = $this->getUnsignedVarLong();
|
||||
}
|
||||
|
||||
protected function encodePayload() : void{
|
||||
$this->putVector3($this->position);
|
||||
$this->putVector3($this->delta);
|
||||
$this->putBool($this->onGround);
|
||||
$this->putUnsignedVarLong($this->tick);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $handler) : bool{
|
||||
return $handler->handleCorrectPlayerMovePrediction($this);
|
||||
}
|
||||
}
|
@ -30,6 +30,7 @@ use pocketmine\inventory\ShapedRecipe;
|
||||
use pocketmine\inventory\ShapelessRecipe;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\network\mcpe\convert\ItemTranslator;
|
||||
use pocketmine\network\mcpe\NetworkBinaryStream;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\network\mcpe\protocol\types\PotionContainerChangeRecipe;
|
||||
@ -124,13 +125,12 @@ class CraftingDataPacket extends DataPacket{
|
||||
break;
|
||||
case self::ENTRY_FURNACE:
|
||||
case self::ENTRY_FURNACE_DATA:
|
||||
$inputId = $this->getVarInt();
|
||||
$inputData = -1;
|
||||
if($recipeType === self::ENTRY_FURNACE_DATA){
|
||||
$inputData = $this->getVarInt();
|
||||
if($inputData === 0x7fff){
|
||||
$inputData = -1;
|
||||
}
|
||||
$inputIdNet = $this->getVarInt();
|
||||
if($recipeType === self::ENTRY_FURNACE){
|
||||
[$inputId, $inputData] = ItemTranslator::getInstance()->fromNetworkIdWithWildcardHandling($inputIdNet, 0x7fff);
|
||||
}else{
|
||||
$inputMetaNet = $this->getVarInt();
|
||||
[$inputId, $inputData] = ItemTranslator::getInstance()->fromNetworkIdWithWildcardHandling($inputIdNet, $inputMetaNet);
|
||||
}
|
||||
$entry["input"] = ItemFactory::get($inputId, $inputData);
|
||||
$entry["output"] = $out = $this->getSlot();
|
||||
@ -150,18 +150,25 @@ class CraftingDataPacket extends DataPacket{
|
||||
$this->decodedEntries[] = $entry;
|
||||
}
|
||||
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
||||
$input = $this->getVarInt();
|
||||
$inputMeta = $this->getVarInt();
|
||||
$ingredient = $this->getVarInt();
|
||||
$ingredientMeta = $this->getVarInt();
|
||||
$output = $this->getVarInt();
|
||||
$outputMeta = $this->getVarInt();
|
||||
$inputIdNet = $this->getVarInt();
|
||||
$inputMetaNet = $this->getVarInt();
|
||||
[$input, $inputMeta] = ItemTranslator::getInstance()->fromNetworkId($inputIdNet, $inputMetaNet);
|
||||
$ingredientIdNet = $this->getVarInt();
|
||||
$ingredientMetaNet = $this->getVarInt();
|
||||
[$ingredient, $ingredientMeta] = ItemTranslator::getInstance()->fromNetworkId($ingredientIdNet, $ingredientMetaNet);
|
||||
$outputIdNet = $this->getVarInt();
|
||||
$outputMetaNet = $this->getVarInt();
|
||||
[$output, $outputMeta] = ItemTranslator::getInstance()->fromNetworkId($outputIdNet, $outputMetaNet);
|
||||
$this->potionTypeRecipes[] = new PotionTypeRecipe($input, $inputMeta, $ingredient, $ingredientMeta, $output, $outputMeta);
|
||||
}
|
||||
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
||||
$input = $this->getVarInt();
|
||||
$ingredient = $this->getVarInt();
|
||||
$output = $this->getVarInt();
|
||||
//TODO: we discard inbound ID here, not safe because netID on its own might map to internalID+internalMeta for us
|
||||
$inputIdNet = $this->getVarInt();
|
||||
[$input, ] = ItemTranslator::getInstance()->fromNetworkId($inputIdNet, 0);
|
||||
$ingredientIdNet = $this->getVarInt();
|
||||
[$ingredient, ] = ItemTranslator::getInstance()->fromNetworkId($ingredientIdNet, 0);
|
||||
$outputIdNet = $this->getVarInt();
|
||||
[$output, ] = ItemTranslator::getInstance()->fromNetworkId($outputIdNet, 0);
|
||||
$this->potionContainerRecipes[] = new PotionContainerChangeRecipe($input, $ingredient, $output);
|
||||
}
|
||||
$this->cleanRecipes = $this->getBool();
|
||||
@ -230,15 +237,18 @@ class CraftingDataPacket extends DataPacket{
|
||||
}
|
||||
|
||||
private static function writeFurnaceRecipe(FurnaceRecipe $recipe, NetworkBinaryStream $stream) : int{
|
||||
$stream->putVarInt($recipe->getInput()->getId());
|
||||
$result = CraftingDataPacket::ENTRY_FURNACE;
|
||||
if(!$recipe->getInput()->hasAnyDamageValue()){ //Data recipe
|
||||
$stream->putVarInt($recipe->getInput()->getDamage());
|
||||
$result = CraftingDataPacket::ENTRY_FURNACE_DATA;
|
||||
$input = $recipe->getInput();
|
||||
if($input->hasAnyDamageValue()){
|
||||
[$netId, ] = ItemTranslator::getInstance()->toNetworkId($input->getId(), 0);
|
||||
$netData = 0x7fff;
|
||||
}else{
|
||||
[$netId, $netData] = ItemTranslator::getInstance()->toNetworkId($input->getId(), $input->getDamage());
|
||||
}
|
||||
$stream->putVarInt($netId);
|
||||
$stream->putVarInt($netData);
|
||||
$stream->putSlot($recipe->getResult());
|
||||
$stream->putString("furnace"); //TODO: blocktype (no prefix) (this might require internal API breaks)
|
||||
return $result;
|
||||
return CraftingDataPacket::ENTRY_FURNACE_DATA;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -174,7 +174,7 @@ abstract class DataPacket extends NetworkBinaryStream{
|
||||
public function __debugInfo(){
|
||||
$data = [];
|
||||
foreach((array) $this as $k => $v){
|
||||
if($k === "buffer" and is_string($v)){
|
||||
if($k === "buffer"){
|
||||
$data[$k] = bin2hex($v);
|
||||
}elseif(is_string($v) or (is_object($v) and method_exists($v, "__toString"))){
|
||||
$data[$k] = Utils::printable((string) $v);
|
||||
|
@ -25,31 +25,38 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
use pocketmine\nbt\NetworkLittleEndianNBTStream;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class UpdateBlockPropertiesPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::UPDATE_BLOCK_PROPERTIES_PACKET;
|
||||
class FilterTextPacket extends DataPacket/* implements ClientboundPacket, ServerboundPacket*/{
|
||||
public const NETWORK_ID = ProtocolInfo::FILTER_TEXT_PACKET;
|
||||
|
||||
/** @var string */
|
||||
private $nbt;
|
||||
private $text;
|
||||
/** @var bool */
|
||||
private $fromServer;
|
||||
|
||||
public static function create(CompoundTag $data) : self{
|
||||
public static function create(string $text, bool $server) : self{
|
||||
$result = new self;
|
||||
$result->nbt = (new NetworkLittleEndianNBTStream())->write($data);
|
||||
$result->text = $text;
|
||||
$result->fromServer = $server;
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getText() : string{ return $this->text; }
|
||||
|
||||
public function isFromServer() : bool{ return $this->fromServer; }
|
||||
|
||||
protected function decodePayload() : void{
|
||||
$this->nbt = $this->getRemaining();
|
||||
$this->text = $this->getString();
|
||||
$this->fromServer = $this->getBool();
|
||||
}
|
||||
|
||||
protected function encodePayload() : void{
|
||||
$this->put($this->nbt);
|
||||
$this->putString($this->text);
|
||||
$this->putBool($this->fromServer);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $handler) : bool{
|
||||
return $handler->handleUpdateBlockProperties($this);
|
||||
return $handler->handleFilterText($this);
|
||||
}
|
||||
}
|
78
src/pocketmine/network/mcpe/protocol/ItemComponentPacket.php
Normal file
78
src/pocketmine/network/mcpe/protocol/ItemComponentPacket.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
use pocketmine\nbt\NetworkLittleEndianNBTStream;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\network\mcpe\protocol\types\ItemComponentPacketEntry;
|
||||
use function count;
|
||||
|
||||
class ItemComponentPacket extends DataPacket/* implements ClientboundPacket*/{
|
||||
public const NETWORK_ID = ProtocolInfo::ITEM_COMPONENT_PACKET;
|
||||
|
||||
/**
|
||||
* @var ItemComponentPacketEntry[]
|
||||
* @phpstan-var list<ItemComponentPacketEntry>
|
||||
*/
|
||||
private $entries;
|
||||
|
||||
/**
|
||||
* @param ItemComponentPacketEntry[] $entries
|
||||
* @phpstan-param list<ItemComponentPacketEntry> $entries
|
||||
*/
|
||||
public static function create(array $entries) : self{
|
||||
$result = new self;
|
||||
$result->entries = $entries;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ItemComponentPacketEntry[]
|
||||
* @phpstan-return list<ItemComponentPacketEntry>
|
||||
*/
|
||||
public function getEntries() : array{ return $this->entries; }
|
||||
|
||||
protected function decodePayload() : void{
|
||||
$this->entries = [];
|
||||
for($i = 0, $len = $this->getUnsignedVarInt(); $i < $len; ++$i){
|
||||
$name = $this->getString();
|
||||
$nbt = $this->getNbtCompoundRoot();
|
||||
$this->entries[] = new ItemComponentPacketEntry($name, $nbt);
|
||||
}
|
||||
}
|
||||
|
||||
protected function encodePayload() : void{
|
||||
$this->putUnsignedVarInt(count($this->entries));
|
||||
foreach($this->entries as $entry){
|
||||
$this->putString($entry->getName());
|
||||
$this->put((new NetworkLittleEndianNBTStream())->write($entry->getComponentNbt()));
|
||||
}
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $handler) : bool{
|
||||
return $handler->handleItemComponent($this);
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
<?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\network\mcpe\protocol;
|
||||
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class MotionPredictionHintsPacket extends DataPacket/* implements ClientboundPacket*/{
|
||||
public const NETWORK_ID = ProtocolInfo::MOTION_PREDICTION_HINTS_PACKET;
|
||||
|
||||
/** @var int */
|
||||
private $entityRuntimeId;
|
||||
/** @var Vector3 */
|
||||
private $motion;
|
||||
/** @var bool */
|
||||
private $onGround;
|
||||
|
||||
public static function create(int $entityRuntimeId, Vector3 $motion, bool $onGround) : self{
|
||||
$result = new self;
|
||||
$result->entityRuntimeId = $entityRuntimeId;
|
||||
$result->motion = $motion;
|
||||
$result->onGround = $onGround;
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getEntityRuntimeIdField() : int{ return $this->entityRuntimeId; } //TODO: rename this on PM4 (crap architecture, thanks shoghi)
|
||||
|
||||
public function getMotion() : Vector3{ return $this->motion; }
|
||||
|
||||
public function isOnGround() : bool{ return $this->onGround; }
|
||||
|
||||
protected function decodePayload() : void{
|
||||
$this->entityRuntimeId = $this->getEntityRuntimeId();
|
||||
$this->motion = $this->getVector3();
|
||||
$this->onGround = $this->getBool();
|
||||
}
|
||||
|
||||
protected function encodePayload() : void{
|
||||
$this->putEntityRuntimeId($this->entityRuntimeId);
|
||||
$this->putVector3($this->motion);
|
||||
$this->putBool($this->onGround);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $handler) : bool{
|
||||
return $handler->handleMotionPredictionHints($this);
|
||||
}
|
||||
}
|
@ -44,12 +44,12 @@ class MoveActorDeltaPacket extends DataPacket{
|
||||
public $entityRuntimeId;
|
||||
/** @var int */
|
||||
public $flags;
|
||||
/** @var int */
|
||||
public $xDiff = 0;
|
||||
/** @var int */
|
||||
public $yDiff = 0;
|
||||
/** @var int */
|
||||
public $zDiff = 0;
|
||||
/** @var float */
|
||||
public $xPos = 0;
|
||||
/** @var float */
|
||||
public $yPos = 0;
|
||||
/** @var float */
|
||||
public $zPos = 0;
|
||||
/** @var float */
|
||||
public $xRot = 0.0;
|
||||
/** @var float */
|
||||
@ -57,9 +57,9 @@ class MoveActorDeltaPacket extends DataPacket{
|
||||
/** @var float */
|
||||
public $zRot = 0.0;
|
||||
|
||||
private function maybeReadCoord(int $flag) : int{
|
||||
private function maybeReadCoord(int $flag) : float{
|
||||
if(($this->flags & $flag) !== 0){
|
||||
return $this->getVarInt();
|
||||
return $this->getLFloat();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -74,17 +74,17 @@ class MoveActorDeltaPacket extends DataPacket{
|
||||
protected function decodePayload(){
|
||||
$this->entityRuntimeId = $this->getEntityRuntimeId();
|
||||
$this->flags = $this->getLShort();
|
||||
$this->xDiff = $this->maybeReadCoord(self::FLAG_HAS_X);
|
||||
$this->yDiff = $this->maybeReadCoord(self::FLAG_HAS_Y);
|
||||
$this->zDiff = $this->maybeReadCoord(self::FLAG_HAS_Z);
|
||||
$this->xPos = $this->maybeReadCoord(self::FLAG_HAS_X);
|
||||
$this->yPos = $this->maybeReadCoord(self::FLAG_HAS_Y);
|
||||
$this->zPos = $this->maybeReadCoord(self::FLAG_HAS_Z);
|
||||
$this->xRot = $this->maybeReadRotation(self::FLAG_HAS_ROT_X);
|
||||
$this->yRot = $this->maybeReadRotation(self::FLAG_HAS_ROT_Y);
|
||||
$this->zRot = $this->maybeReadRotation(self::FLAG_HAS_ROT_Z);
|
||||
}
|
||||
|
||||
private function maybeWriteCoord(int $flag, int $val) : void{
|
||||
private function maybeWriteCoord(int $flag, float $val) : void{
|
||||
if(($this->flags & $flag) !== 0){
|
||||
$this->putVarInt($val);
|
||||
$this->putLFloat($val);
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,9 +97,9 @@ class MoveActorDeltaPacket extends DataPacket{
|
||||
protected function encodePayload(){
|
||||
$this->putEntityRuntimeId($this->entityRuntimeId);
|
||||
$this->putLShort($this->flags);
|
||||
$this->maybeWriteCoord(self::FLAG_HAS_X, $this->xDiff);
|
||||
$this->maybeWriteCoord(self::FLAG_HAS_Y, $this->yDiff);
|
||||
$this->maybeWriteCoord(self::FLAG_HAS_Z, $this->zDiff);
|
||||
$this->maybeWriteCoord(self::FLAG_HAS_X, $this->xPos);
|
||||
$this->maybeWriteCoord(self::FLAG_HAS_Y, $this->yPos);
|
||||
$this->maybeWriteCoord(self::FLAG_HAS_Z, $this->zPos);
|
||||
$this->maybeWriteRotation(self::FLAG_HAS_ROT_X, $this->xRot);
|
||||
$this->maybeWriteRotation(self::FLAG_HAS_ROT_Y, $this->yRot);
|
||||
$this->maybeWriteRotation(self::FLAG_HAS_ROT_Z, $this->zRot);
|
||||
|
@ -56,6 +56,8 @@ class MovePlayerPacket extends DataPacket{
|
||||
public $teleportCause = 0;
|
||||
/** @var int */
|
||||
public $teleportItem = 0;
|
||||
/** @var int */
|
||||
public $tick = 0;
|
||||
|
||||
protected function decodePayload(){
|
||||
$this->entityRuntimeId = $this->getEntityRuntimeId();
|
||||
@ -70,6 +72,7 @@ class MovePlayerPacket extends DataPacket{
|
||||
$this->teleportCause = $this->getLInt();
|
||||
$this->teleportItem = $this->getLInt();
|
||||
}
|
||||
$this->tick = $this->getUnsignedVarLong();
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
@ -85,6 +88,7 @@ class MovePlayerPacket extends DataPacket{
|
||||
$this->putLInt($this->teleportCause);
|
||||
$this->putLInt($this->teleportItem);
|
||||
}
|
||||
$this->putUnsignedVarLong($this->tick);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
|
@ -71,7 +71,6 @@ class PacketPool{
|
||||
static::registerPacket(new BlockPickRequestPacket());
|
||||
static::registerPacket(new ActorPickRequestPacket());
|
||||
static::registerPacket(new PlayerActionPacket());
|
||||
static::registerPacket(new ActorFallPacket());
|
||||
static::registerPacket(new HurtArmorPacket());
|
||||
static::registerPacket(new SetActorDataPacket());
|
||||
static::registerPacket(new SetActorMotionPacket());
|
||||
@ -166,7 +165,6 @@ class PacketPool{
|
||||
static::registerPacket(new MapCreateLockedCopyPacket());
|
||||
static::registerPacket(new StructureTemplateDataRequestPacket());
|
||||
static::registerPacket(new StructureTemplateDataResponsePacket());
|
||||
static::registerPacket(new UpdateBlockPropertiesPacket());
|
||||
static::registerPacket(new ClientCacheBlobStatusPacket());
|
||||
static::registerPacket(new ClientCacheMissResponsePacket());
|
||||
static::registerPacket(new EducationSettingsPacket());
|
||||
@ -189,6 +187,13 @@ class PacketPool{
|
||||
static::registerPacket(new PositionTrackingDBClientRequestPacket());
|
||||
static::registerPacket(new DebugInfoPacket());
|
||||
static::registerPacket(new PacketViolationWarningPacket());
|
||||
static::registerPacket(new MotionPredictionHintsPacket());
|
||||
static::registerPacket(new AnimateEntityPacket());
|
||||
static::registerPacket(new CameraShakePacket());
|
||||
static::registerPacket(new PlayerFogPacket());
|
||||
static::registerPacket(new CorrectPlayerMovePredictionPacket());
|
||||
static::registerPacket(new ItemComponentPacket());
|
||||
static::registerPacket(new FilterTextPacket());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,7 +43,7 @@ class PlayerActionPacket extends DataPacket{
|
||||
public const ACTION_STOP_SPRINT = 10;
|
||||
public const ACTION_START_SNEAK = 11;
|
||||
public const ACTION_STOP_SNEAK = 12;
|
||||
public const ACTION_DIMENSION_CHANGE_REQUEST = 13; //sent when dying in different dimension
|
||||
public const ACTION_CREATIVE_PLAYER_DESTROY_BLOCK = 13;
|
||||
public const ACTION_DIMENSION_CHANGE_ACK = 14; //sent when spawning in a different dimension to tell the server we spawned
|
||||
public const ACTION_START_GLIDE = 15;
|
||||
public const ACTION_STOP_GLIDE = 16;
|
||||
|
@ -54,13 +54,17 @@ class PlayerAuthInputPacket extends DataPacket/* implements ServerboundPacket*/{
|
||||
private $playMode;
|
||||
/** @var Vector3|null */
|
||||
private $vrGazeDirection = null;
|
||||
/** @var int */
|
||||
private $tick;
|
||||
/** @var Vector3 */
|
||||
private $delta;
|
||||
|
||||
/**
|
||||
* @param int $inputMode @see InputMode
|
||||
* @param int $playMode @see PlayMode
|
||||
* @param Vector3|null $vrGazeDirection only used when PlayMode::VR
|
||||
*/
|
||||
public static function create(Vector3 $position, float $pitch, float $yaw, float $headYaw, float $moveVecX, float $moveVecZ, int $inputFlags, int $inputMode, int $playMode, ?Vector3 $vrGazeDirection = null) : self{
|
||||
public static function create(Vector3 $position, float $pitch, float $yaw, float $headYaw, float $moveVecX, float $moveVecZ, int $inputFlags, int $inputMode, int $playMode, ?Vector3 $vrGazeDirection, int $tick, Vector3 $delta) : self{
|
||||
if($playMode === PlayMode::VR and $vrGazeDirection === null){
|
||||
//yuck, can we get a properly written packet just once? ...
|
||||
throw new \InvalidArgumentException("Gaze direction must be provided for VR play mode");
|
||||
@ -78,6 +82,8 @@ class PlayerAuthInputPacket extends DataPacket/* implements ServerboundPacket*/{
|
||||
if($vrGazeDirection !== null){
|
||||
$result->vrGazeDirection = $vrGazeDirection->asVector3();
|
||||
}
|
||||
$result->tick = $tick;
|
||||
$result->delta = $delta;
|
||||
return $result;
|
||||
}
|
||||
|
||||
@ -127,6 +133,10 @@ class PlayerAuthInputPacket extends DataPacket/* implements ServerboundPacket*/{
|
||||
return $this->vrGazeDirection;
|
||||
}
|
||||
|
||||
public function getTick() : int{ return $this->tick; }
|
||||
|
||||
public function getDelta() : Vector3{ return $this->delta; }
|
||||
|
||||
protected function decodePayload() : void{
|
||||
$this->pitch = $this->getLFloat();
|
||||
$this->yaw = $this->getLFloat();
|
||||
@ -140,6 +150,8 @@ class PlayerAuthInputPacket extends DataPacket/* implements ServerboundPacket*/{
|
||||
if($this->playMode === PlayMode::VR){
|
||||
$this->vrGazeDirection = $this->getVector3();
|
||||
}
|
||||
$this->tick = $this->getUnsignedVarLong();
|
||||
$this->delta = $this->getVector3();
|
||||
}
|
||||
|
||||
protected function encodePayload() : void{
|
||||
@ -156,6 +168,8 @@ class PlayerAuthInputPacket extends DataPacket/* implements ServerboundPacket*/{
|
||||
assert($this->vrGazeDirection !== null);
|
||||
$this->putVector3($this->vrGazeDirection);
|
||||
}
|
||||
$this->putUnsignedVarLong($this->tick);
|
||||
$this->putVector3($this->delta);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $handler) : bool{
|
||||
|
73
src/pocketmine/network/mcpe/protocol/PlayerFogPacket.php
Normal file
73
src/pocketmine/network/mcpe/protocol/PlayerFogPacket.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?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\network\mcpe\protocol;
|
||||
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use function count;
|
||||
|
||||
class PlayerFogPacket extends DataPacket/* implements ClientboundPacket*/{
|
||||
public const NETWORK_ID = ProtocolInfo::PLAYER_FOG_PACKET;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
* @phpstan-var list<string>
|
||||
*/
|
||||
private $fogLayers;
|
||||
|
||||
/**
|
||||
* @param string[] $fogLayers
|
||||
* @phpstan-param list<string> $fogLayers
|
||||
*/
|
||||
public static function create(array $fogLayers) : self{
|
||||
$result = new self;
|
||||
$result->fogLayers = $fogLayers;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
* @phpstan-return list<string>
|
||||
*/
|
||||
public function getFogLayers() : array{ return $this->fogLayers; }
|
||||
|
||||
protected function decodePayload() : void{
|
||||
$this->fogLayers = [];
|
||||
for($i = 0, $len = $this->getUnsignedVarInt(); $i < $len; ++$i){
|
||||
$this->fogLayers[] = $this->getString();
|
||||
}
|
||||
}
|
||||
|
||||
protected function encodePayload() : void{
|
||||
$this->putUnsignedVarInt(count($this->fogLayers));
|
||||
foreach($this->fogLayers as $fogLayer){
|
||||
$this->putString($fogLayer);
|
||||
}
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $handler) : bool{
|
||||
return $handler->handlePlayerFog($this);
|
||||
}
|
||||
}
|
@ -37,11 +37,11 @@ interface ProtocolInfo{
|
||||
*/
|
||||
|
||||
/** Actual Minecraft: PE protocol version */
|
||||
public const CURRENT_PROTOCOL = 408;
|
||||
public const CURRENT_PROTOCOL = 422;
|
||||
/** Current Minecraft PE version reported by the server. This is usually the earliest currently supported version. */
|
||||
public const MINECRAFT_VERSION = 'v1.16.20';
|
||||
public const MINECRAFT_VERSION = 'v1.16.200';
|
||||
/** Version number sent to clients in ping responses. */
|
||||
public const MINECRAFT_VERSION_NETWORK = '1.16.20';
|
||||
public const MINECRAFT_VERSION_NETWORK = '1.16.200';
|
||||
|
||||
public const LOGIN_PACKET = 0x01;
|
||||
public const PLAY_STATUS_PACKET = 0x02;
|
||||
@ -79,7 +79,7 @@ interface ProtocolInfo{
|
||||
public const BLOCK_PICK_REQUEST_PACKET = 0x22;
|
||||
public const ACTOR_PICK_REQUEST_PACKET = 0x23;
|
||||
public const PLAYER_ACTION_PACKET = 0x24;
|
||||
public const ACTOR_FALL_PACKET = 0x25;
|
||||
|
||||
public const HURT_ARMOR_PACKET = 0x26;
|
||||
public const SET_ACTOR_DATA_PACKET = 0x27;
|
||||
public const SET_ACTOR_MOTION_PACKET = 0x28;
|
||||
@ -176,7 +176,7 @@ interface ProtocolInfo{
|
||||
public const MAP_CREATE_LOCKED_COPY_PACKET = 0x83;
|
||||
public const STRUCTURE_TEMPLATE_DATA_REQUEST_PACKET = 0x84;
|
||||
public const STRUCTURE_TEMPLATE_DATA_RESPONSE_PACKET = 0x85;
|
||||
public const UPDATE_BLOCK_PROPERTIES_PACKET = 0x86;
|
||||
|
||||
public const CLIENT_CACHE_BLOB_STATUS_PACKET = 0x87;
|
||||
public const CLIENT_CACHE_MISS_RESPONSE_PACKET = 0x88;
|
||||
public const EDUCATION_SETTINGS_PACKET = 0x89;
|
||||
@ -199,5 +199,12 @@ interface ProtocolInfo{
|
||||
public const POSITION_TRACKING_D_B_CLIENT_REQUEST_PACKET = 0x9a;
|
||||
public const DEBUG_INFO_PACKET = 0x9b;
|
||||
public const PACKET_VIOLATION_WARNING_PACKET = 0x9c;
|
||||
public const MOTION_PREDICTION_HINTS_PACKET = 0x9d;
|
||||
public const ANIMATE_ENTITY_PACKET = 0x9e;
|
||||
public const CAMERA_SHAKE_PACKET = 0x9f;
|
||||
public const PLAYER_FOG_PACKET = 0xa0;
|
||||
public const CORRECT_PLAYER_MOVE_PREDICTION_PACKET = 0xa1;
|
||||
public const ITEM_COMPONENT_PACKET = 0xa2;
|
||||
public const FILTER_TEXT_PACKET = 0xa3;
|
||||
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\network\mcpe\protocol\types\Experiments;
|
||||
use pocketmine\resourcepacks\ResourcePack;
|
||||
use function count;
|
||||
|
||||
@ -40,11 +41,12 @@ class ResourcePackStackPacket extends DataPacket{
|
||||
/** @var ResourcePack[] */
|
||||
public $resourcePackStack = [];
|
||||
|
||||
/** @var bool */
|
||||
public $isExperimental = false;
|
||||
/** @var string */
|
||||
public $baseGameVersion = ProtocolInfo::MINECRAFT_VERSION_NETWORK;
|
||||
|
||||
/** @var Experiments */
|
||||
public $experiments;
|
||||
|
||||
protected function decodePayload(){
|
||||
$this->mustAccept = $this->getBool();
|
||||
$behaviorPackCount = $this->getUnsignedVarInt();
|
||||
@ -61,8 +63,8 @@ class ResourcePackStackPacket extends DataPacket{
|
||||
$this->getString();
|
||||
}
|
||||
|
||||
$this->isExperimental = $this->getBool();
|
||||
$this->baseGameVersion = $this->getString();
|
||||
$this->experiments = Experiments::read($this);
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
@ -82,8 +84,8 @@ class ResourcePackStackPacket extends DataPacket{
|
||||
$this->putString(""); //TODO: subpack name
|
||||
}
|
||||
|
||||
$this->putBool($this->isExperimental);
|
||||
$this->putString($this->baseGameVersion);
|
||||
$this->experiments->write($this);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
|
@ -64,6 +64,7 @@ class ResourcePacksInfoPacket extends DataPacket{
|
||||
$this->getString();
|
||||
$this->getString();
|
||||
$this->getBool();
|
||||
$this->getBool();
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,6 +90,7 @@ class ResourcePacksInfoPacket extends DataPacket{
|
||||
$this->putString(""); //TODO: subpack name
|
||||
$this->putString(""); //TODO: content identity
|
||||
$this->putBool(false); //TODO: seems useless for resource packs
|
||||
$this->putBool(false); //TODO: supports RTX
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,14 +38,19 @@ class SetActorDataPacket extends DataPacket{
|
||||
*/
|
||||
public $metadata;
|
||||
|
||||
/** @var int */
|
||||
public $tick = 0;
|
||||
|
||||
protected function decodePayload(){
|
||||
$this->entityRuntimeId = $this->getEntityRuntimeId();
|
||||
$this->metadata = $this->getEntityMetadata();
|
||||
$this->tick = $this->getUnsignedVarLong();
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
$this->putEntityRuntimeId($this->entityRuntimeId);
|
||||
$this->putEntityMetadata($this->metadata);
|
||||
$this->putUnsignedVarLong($this->tick);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
|
@ -27,29 +27,22 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\NetworkLittleEndianNBTStream;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\network\mcpe\convert\RuntimeBlockMapping;
|
||||
use pocketmine\network\mcpe\NetworkBinaryStream;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\network\mcpe\protocol\types\BlockPaletteEntry;
|
||||
use pocketmine\network\mcpe\protocol\types\EducationEditionOffer;
|
||||
use pocketmine\network\mcpe\protocol\types\Experiments;
|
||||
use pocketmine\network\mcpe\protocol\types\GameRuleType;
|
||||
use pocketmine\network\mcpe\protocol\types\GeneratorType;
|
||||
use pocketmine\network\mcpe\protocol\types\ItemTypeEntry;
|
||||
use pocketmine\network\mcpe\protocol\types\MultiplayerGameVisibility;
|
||||
use pocketmine\network\mcpe\protocol\types\PlayerMovementType;
|
||||
use pocketmine\network\mcpe\protocol\types\PlayerPermissions;
|
||||
use pocketmine\network\mcpe\protocol\types\SpawnSettings;
|
||||
use function count;
|
||||
use function file_get_contents;
|
||||
use function json_decode;
|
||||
use const pocketmine\RESOURCE_PATH;
|
||||
|
||||
class StartGamePacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::START_GAME_PACKET;
|
||||
|
||||
/** @var string|null */
|
||||
private static $blockTableCache = null;
|
||||
/** @var string|null */
|
||||
private static $itemTableCache = null;
|
||||
|
||||
/** @var int */
|
||||
public $entityUniqueId;
|
||||
/** @var int */
|
||||
@ -116,6 +109,8 @@ class StartGamePacket extends DataPacket{
|
||||
public $gameRules = [ //TODO: implement this
|
||||
"naturalregeneration" => [GameRuleType::BOOL, false] //Hack for client side regeneration
|
||||
];
|
||||
/** @var Experiments */
|
||||
public $experiments;
|
||||
/** @var bool */
|
||||
public $hasBonusChestEnabled = false;
|
||||
/** @var bool */
|
||||
@ -159,8 +154,8 @@ class StartGamePacket extends DataPacket{
|
||||
public $premiumWorldTemplateId = "";
|
||||
/** @var bool */
|
||||
public $isTrial = false;
|
||||
/** @var bool */
|
||||
public $isMovementServerAuthoritative = false;
|
||||
/** @var int */
|
||||
public $playerMovementType = PlayerMovementType::LEGACY;
|
||||
/** @var int */
|
||||
public $currentTick = 0; //only used if isTrial is true
|
||||
/** @var int */
|
||||
@ -168,13 +163,17 @@ class StartGamePacket extends DataPacket{
|
||||
/** @var string */
|
||||
public $multiplayerCorrelationId = ""; //TODO: this should be filled with a UUID of some sort
|
||||
|
||||
/** @var ListTag|null */
|
||||
public $blockTable = null;
|
||||
/**
|
||||
* @var int[]|null string (name) => int16 (legacyID)
|
||||
* @phpstan-var array<string, int>|null
|
||||
* @var BlockPaletteEntry[]
|
||||
* @phpstan-var list<BlockPaletteEntry>
|
||||
*/
|
||||
public $itemTable = null;
|
||||
public $blockPalette = [];
|
||||
|
||||
/**
|
||||
* @var ItemTypeEntry[]
|
||||
* @phpstan-var list<ItemTypeEntry>
|
||||
*/
|
||||
public $itemTable;
|
||||
/** @var bool */
|
||||
public $enableNewInventorySystem = false; //TODO
|
||||
|
||||
@ -210,6 +209,7 @@ class StartGamePacket extends DataPacket{
|
||||
$this->commandsEnabled = $this->getBool();
|
||||
$this->isTexturePacksRequired = $this->getBool();
|
||||
$this->gameRules = $this->getGameRules();
|
||||
$this->experiments = Experiments::read($this);
|
||||
$this->hasBonusChestEnabled = $this->getBool();
|
||||
$this->hasStartWithMapEnabled = $this->getBool();
|
||||
$this->defaultPlayerPermission = $this->getVarInt();
|
||||
@ -235,23 +235,25 @@ class StartGamePacket extends DataPacket{
|
||||
$this->worldName = $this->getString();
|
||||
$this->premiumWorldTemplateId = $this->getString();
|
||||
$this->isTrial = $this->getBool();
|
||||
$this->isMovementServerAuthoritative = $this->getBool();
|
||||
$this->playerMovementType = $this->getVarInt();
|
||||
$this->currentTick = $this->getLLong();
|
||||
|
||||
$this->enchantmentSeed = $this->getVarInt();
|
||||
|
||||
$blockTable = (new NetworkLittleEndianNBTStream())->read($this->buffer, false, $this->offset, 512);
|
||||
if(!($blockTable instanceof ListTag)){
|
||||
throw new \UnexpectedValueException("Wrong block table root NBT tag type");
|
||||
$this->blockPalette = [];
|
||||
for($i = 0, $len = $this->getUnsignedVarInt(); $i < $len; ++$i){
|
||||
$blockName = $this->getString();
|
||||
$state = $this->getNbtCompoundRoot();
|
||||
$this->blockPalette[] = new BlockPaletteEntry($blockName, $state);
|
||||
}
|
||||
$this->blockTable = $blockTable;
|
||||
|
||||
$this->itemTable = [];
|
||||
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
||||
$id = $this->getString();
|
||||
$legacyId = $this->getSignedLShort();
|
||||
$stringId = $this->getString();
|
||||
$numericId = $this->getSignedLShort();
|
||||
$isComponentBased = $this->getBool();
|
||||
|
||||
$this->itemTable[$id] = $legacyId;
|
||||
$this->itemTable[] = new ItemTypeEntry($stringId, $numericId, $isComponentBased);
|
||||
}
|
||||
|
||||
$this->multiplayerCorrelationId = $this->getString();
|
||||
@ -290,6 +292,7 @@ class StartGamePacket extends DataPacket{
|
||||
$this->putBool($this->commandsEnabled);
|
||||
$this->putBool($this->isTexturePacksRequired);
|
||||
$this->putGameRules($this->gameRules);
|
||||
$this->experiments->write($this);
|
||||
$this->putBool($this->hasBonusChestEnabled);
|
||||
$this->putBool($this->hasStartWithMapEnabled);
|
||||
$this->putVarInt($this->defaultPlayerPermission);
|
||||
@ -314,47 +317,28 @@ class StartGamePacket extends DataPacket{
|
||||
$this->putString($this->worldName);
|
||||
$this->putString($this->premiumWorldTemplateId);
|
||||
$this->putBool($this->isTrial);
|
||||
$this->putBool($this->isMovementServerAuthoritative);
|
||||
$this->putVarInt($this->playerMovementType);
|
||||
$this->putLLong($this->currentTick);
|
||||
|
||||
$this->putVarInt($this->enchantmentSeed);
|
||||
|
||||
if($this->blockTable === null){
|
||||
if(self::$blockTableCache === null){
|
||||
//this is a really nasty hack, but it'll do for now
|
||||
self::$blockTableCache = (new NetworkLittleEndianNBTStream())->write(new ListTag("", RuntimeBlockMapping::getBedrockKnownStates()));
|
||||
}
|
||||
$this->put(self::$blockTableCache);
|
||||
}else{
|
||||
$this->put((new NetworkLittleEndianNBTStream())->write($this->blockTable));
|
||||
$this->putUnsignedVarInt(count($this->blockPalette));
|
||||
$nbtWriter = new NetworkLittleEndianNBTStream();
|
||||
foreach($this->blockPalette as $entry){
|
||||
$this->putString($entry->getName());
|
||||
$this->put($nbtWriter->write($entry->getStates()));
|
||||
}
|
||||
if($this->itemTable === null){
|
||||
if(self::$itemTableCache === null){
|
||||
self::$itemTableCache = self::serializeItemTable(json_decode(file_get_contents(RESOURCE_PATH . '/vanilla/item_id_map.json'), true));
|
||||
}
|
||||
$this->put(self::$itemTableCache);
|
||||
}else{
|
||||
$this->put(self::serializeItemTable($this->itemTable));
|
||||
$this->putUnsignedVarInt(count($this->itemTable));
|
||||
foreach($this->itemTable as $entry){
|
||||
$this->putString($entry->getStringId());
|
||||
$this->putLShort($entry->getNumericId());
|
||||
$this->putBool($entry->isComponentBased());
|
||||
}
|
||||
|
||||
$this->putString($this->multiplayerCorrelationId);
|
||||
$this->putBool($this->enableNewInventorySystem);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $table
|
||||
* @phpstan-param array<string, int> $table
|
||||
*/
|
||||
private static function serializeItemTable(array $table) : string{
|
||||
$stream = new NetworkBinaryStream();
|
||||
$stream->putUnsignedVarInt(count($table));
|
||||
foreach($table as $name => $legacyId){
|
||||
$stream->putString($name);
|
||||
$stream->putLShort($legacyId);
|
||||
}
|
||||
return $stream->getBuffer();
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
return $session->handleStartGame($this);
|
||||
}
|
||||
|
@ -35,15 +35,19 @@ class UpdateAttributesPacket extends DataPacket{
|
||||
public $entityRuntimeId;
|
||||
/** @var Attribute[] */
|
||||
public $entries = [];
|
||||
/** @var int */
|
||||
public $tick = 0;
|
||||
|
||||
protected function decodePayload(){
|
||||
$this->entityRuntimeId = $this->getEntityRuntimeId();
|
||||
$this->entries = $this->getAttributeList();
|
||||
$this->tick = $this->getUnsignedVarLong();
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
$this->putEntityRuntimeId($this->entityRuntimeId);
|
||||
$this->putAttributeList(...$this->entries);
|
||||
$this->putUnsignedVarLong($this->tick);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
|
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\protocol\types;
|
||||
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
|
||||
final class BlockPaletteEntry{
|
||||
|
||||
/** @var string */
|
||||
private $name;
|
||||
/** @var CompoundTag */
|
||||
private $states;
|
||||
|
||||
public function __construct(string $name, CompoundTag $states){
|
||||
$this->name = $name;
|
||||
$this->states = $states;
|
||||
}
|
||||
|
||||
public function getName() : string{ return $this->name; }
|
||||
|
||||
public function getStates() : CompoundTag{ return $this->states; }
|
||||
}
|
72
src/pocketmine/network/mcpe/protocol/types/Experiments.php
Normal file
72
src/pocketmine/network/mcpe/protocol/types/Experiments.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?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\network\mcpe\protocol\types;
|
||||
|
||||
use pocketmine\network\mcpe\NetworkBinaryStream;
|
||||
use function count;
|
||||
|
||||
final class Experiments{
|
||||
|
||||
/**
|
||||
* @var bool[]
|
||||
* @phpstan-var array<string, bool>
|
||||
*/
|
||||
private $experiments;
|
||||
/** @var bool */
|
||||
private $hasPreviouslyUsedExperiments;
|
||||
|
||||
/**
|
||||
* @param bool[] $experiments
|
||||
* @phpstan-param array<string, bool> $experiments
|
||||
*/
|
||||
public function __construct(array $experiments, bool $hasPreviouslyUsedExperiments){
|
||||
$this->experiments = $experiments;
|
||||
$this->hasPreviouslyUsedExperiments = $hasPreviouslyUsedExperiments;
|
||||
}
|
||||
|
||||
/** @return bool[] */
|
||||
public function getExperiments() : array{ return $this->experiments; }
|
||||
|
||||
public function hasPreviouslyUsedExperiments() : bool{ return $this->hasPreviouslyUsedExperiments; }
|
||||
|
||||
public static function read(NetworkBinaryStream $in) : self{
|
||||
$experiments = [];
|
||||
for($i = 0, $len = $in->getLInt(); $i < $len; ++$i){
|
||||
$experimentName = $in->getString();
|
||||
$enabled = $in->getBool();
|
||||
$experiments[$experimentName] = $enabled;
|
||||
}
|
||||
$hasPreviouslyUsedExperiments = $in->getBool();
|
||||
return new self($experiments, $hasPreviouslyUsedExperiments);
|
||||
}
|
||||
|
||||
public function write(NetworkBinaryStream $out) : void{
|
||||
$out->putLInt(count($this->experiments));
|
||||
foreach($this->experiments as $experimentName => $enabled){
|
||||
$out->putString($experimentName);
|
||||
$out->putBool($enabled);
|
||||
}
|
||||
$out->putBool($this->hasPreviouslyUsedExperiments);
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\protocol\types;
|
||||
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
|
||||
final class ItemComponentPacketEntry{
|
||||
|
||||
/** @var string */
|
||||
private $name;
|
||||
/** @var CompoundTag */
|
||||
private $componentNbt;
|
||||
|
||||
public function __construct(string $name, CompoundTag $componentNbt){
|
||||
$this->name = $name;
|
||||
$this->componentNbt = $componentNbt;
|
||||
}
|
||||
|
||||
public function getName() : string{ return $this->name; }
|
||||
|
||||
public function getComponentNbt() : CompoundTag{ return $this->componentNbt; }
|
||||
}
|
@ -21,35 +21,26 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\protocol;
|
||||
namespace pocketmine\network\mcpe\protocol\types;
|
||||
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class ActorFallPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::ACTOR_FALL_PACKET;
|
||||
final class ItemTypeEntry{
|
||||
|
||||
/** @var string */
|
||||
private $stringId;
|
||||
/** @var int */
|
||||
public $entityRuntimeId;
|
||||
/** @var float */
|
||||
public $fallDistance;
|
||||
private $numericId;
|
||||
/** @var bool */
|
||||
public $isInVoid;
|
||||
private $componentBased;
|
||||
|
||||
protected function decodePayload(){
|
||||
$this->entityRuntimeId = $this->getEntityRuntimeId();
|
||||
$this->fallDistance = $this->getLFloat();
|
||||
$this->isInVoid = $this->getBool();
|
||||
public function __construct(string $stringId, int $numericId, bool $componentBased){
|
||||
$this->stringId = $stringId;
|
||||
$this->numericId = $numericId;
|
||||
$this->componentBased = $componentBased;
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
$this->putEntityRuntimeId($this->entityRuntimeId);
|
||||
$this->putLFloat($this->fallDistance);
|
||||
$this->putBool($this->isInVoid);
|
||||
}
|
||||
public function getStringId() : string{ return $this->stringId; }
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
return $session->handleActorFall($this);
|
||||
}
|
||||
public function getNumericId() : int{ return $this->numericId; }
|
||||
|
||||
public function isComponentBased() : bool{ return $this->componentBased; }
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
<?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\network\mcpe\protocol\types;
|
||||
|
||||
final class PlayerMovementType{
|
||||
|
||||
public const LEGACY = 0; //MovePlayerPacket
|
||||
public const SERVER_AUTHORITATIVE_V1 = 1; //PlayerAuthInputPacket
|
||||
public const SERVER_AUTHORITATIVE_V2_REWIND = 2; //PlayerAuthInputPacket + a bunch of junk that solves a nonexisting problem
|
||||
}
|
@ -29,17 +29,23 @@ class SkinAnimation{
|
||||
public const TYPE_BODY_32 = 2;
|
||||
public const TYPE_BODY_64 = 3;
|
||||
|
||||
public const EXPRESSION_LINEAR = 0; //???
|
||||
public const EXPRESSION_BLINKING = 1;
|
||||
|
||||
/** @var SkinImage */
|
||||
private $image;
|
||||
/** @var int */
|
||||
private $type;
|
||||
/** @var float */
|
||||
private $frames;
|
||||
/** @var int */
|
||||
private $expressionType;
|
||||
|
||||
public function __construct(SkinImage $image, int $type, float $frames){
|
||||
public function __construct(SkinImage $image, int $type, float $frames, int $expressionType){
|
||||
$this->image = $image;
|
||||
$this->type = $type;
|
||||
$this->frames = $frames;
|
||||
$this->expressionType = $expressionType;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -62,4 +68,6 @@ class SkinAnimation{
|
||||
public function getFrames() : float{
|
||||
return $this->frames;
|
||||
}
|
||||
|
||||
public function getExpressionType() : int{ return $this->expressionType; }
|
||||
}
|
||||
|
@ -28,8 +28,13 @@ use function count;
|
||||
|
||||
final class ItemStackResponse{
|
||||
|
||||
/** @var bool */
|
||||
private $ok;
|
||||
public const RESULT_OK = 0;
|
||||
public const RESULT_ERROR = 1;
|
||||
//TODO: there are a ton more possible result types but we don't need them yet and they are wayyyyyy too many for me
|
||||
//to waste my time on right now...
|
||||
|
||||
/** @var int */
|
||||
private $result;
|
||||
/** @var int */
|
||||
private $requestId;
|
||||
/** @var ItemStackResponseContainerInfo[] */
|
||||
@ -38,13 +43,13 @@ final class ItemStackResponse{
|
||||
/**
|
||||
* @param ItemStackResponseContainerInfo[] $containerInfos
|
||||
*/
|
||||
public function __construct(bool $ok, int $requestId, array $containerInfos){
|
||||
$this->ok = $ok;
|
||||
public function __construct(int $result, int $requestId, array $containerInfos){
|
||||
$this->result = $result;
|
||||
$this->requestId = $requestId;
|
||||
$this->containerInfos = $containerInfos;
|
||||
}
|
||||
|
||||
public function isOk() : bool{ return $this->ok; }
|
||||
public function getResult() : int{ return $this->result; }
|
||||
|
||||
public function getRequestId() : int{ return $this->requestId; }
|
||||
|
||||
@ -52,17 +57,17 @@ final class ItemStackResponse{
|
||||
public function getContainerInfos() : array{ return $this->containerInfos; }
|
||||
|
||||
public static function read(NetworkBinaryStream $in) : self{
|
||||
$ok = $in->getBool();
|
||||
$result = $in->getByte();
|
||||
$requestId = $in->readGenericTypeNetworkId();
|
||||
$containerInfos = [];
|
||||
for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){
|
||||
$containerInfos[] = ItemStackResponseContainerInfo::read($in);
|
||||
}
|
||||
return new self($ok, $requestId, $containerInfos);
|
||||
return new self($result, $requestId, $containerInfos);
|
||||
}
|
||||
|
||||
public function write(NetworkBinaryStream $out) : void{
|
||||
$out->putBool($this->ok);
|
||||
$out->putByte($this->result);
|
||||
$out->writeGenericTypeNetworkId($this->requestId);
|
||||
$out->putUnsignedVarInt(count($this->containerInfos));
|
||||
foreach($this->containerInfos as $containerInfo){
|
||||
|
@ -35,12 +35,15 @@ final class ItemStackResponseSlotInfo{
|
||||
private $count;
|
||||
/** @var int */
|
||||
private $itemStackId;
|
||||
/** @var string */
|
||||
private $customName;
|
||||
|
||||
public function __construct(int $slot, int $hotbarSlot, int $count, int $itemStackId){
|
||||
public function __construct(int $slot, int $hotbarSlot, int $count, int $itemStackId, string $customName){
|
||||
$this->slot = $slot;
|
||||
$this->hotbarSlot = $hotbarSlot;
|
||||
$this->count = $count;
|
||||
$this->itemStackId = $itemStackId;
|
||||
$this->customName = $customName;
|
||||
}
|
||||
|
||||
public function getSlot() : int{ return $this->slot; }
|
||||
@ -51,12 +54,15 @@ final class ItemStackResponseSlotInfo{
|
||||
|
||||
public function getItemStackId() : int{ return $this->itemStackId; }
|
||||
|
||||
public function getCustomName() : string{ return $this->customName; }
|
||||
|
||||
public static function read(NetworkBinaryStream $in) : self{
|
||||
$slot = $in->getByte();
|
||||
$hotbarSlot = $in->getByte();
|
||||
$count = $in->getByte();
|
||||
$itemStackId = $in->readGenericTypeNetworkId();
|
||||
return new self($slot, $hotbarSlot, $count, $itemStackId);
|
||||
$customName = $in->getString();
|
||||
return new self($slot, $hotbarSlot, $count, $itemStackId, $customName);
|
||||
}
|
||||
|
||||
public function write(NetworkBinaryStream $out) : void{
|
||||
@ -64,5 +70,6 @@ final class ItemStackResponseSlotInfo{
|
||||
$out->putByte($this->hotbarSlot);
|
||||
$out->putByte($this->count);
|
||||
$out->writeGenericTypeNetworkId($this->itemStackId);
|
||||
$out->putString($this->customName);
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\permission;
|
||||
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function explode;
|
||||
@ -145,7 +146,9 @@ class BanEntry{
|
||||
private static function parseDate(string $date) : \DateTime{
|
||||
$datetime = \DateTime::createFromFormat(self::$format, $date);
|
||||
if(!($datetime instanceof \DateTime)){
|
||||
throw new \RuntimeException("Error parsing date for BanEntry: " . implode(", ", \DateTime::getLastErrors()["errors"]));
|
||||
$lastErrors = \DateTime::getLastErrors();
|
||||
if($lastErrors === false) throw new AssumptionFailedError("DateTime::getLastErrors() should not be returning false in here");
|
||||
throw new \RuntimeException("Error parsing date for BanEntry: " . implode(", ", $lastErrors["errors"]));
|
||||
}
|
||||
|
||||
return $datetime;
|
||||
|
@ -123,7 +123,16 @@ class PermissionAttachment{
|
||||
if($this->permissions[$name] === $value){
|
||||
return;
|
||||
}
|
||||
unset($this->permissions[$name]); //Fixes children getting overwritten
|
||||
/* Because of the way child permissions are calculated, permissions which were set later in time are
|
||||
* preferred over earlier ones when conflicts in inherited permission values occur.
|
||||
* Here's the kicker: This behaviour depends on PHP's internal array ordering, which maintains insertion
|
||||
* order -- BUT -- assigning to an existing index replaces the old value WITHOUT changing the order.
|
||||
* (what crazy person thought relying on this this was a good idea?!?!?!?!?!)
|
||||
*
|
||||
* This removes the old value so that the new value will be added at the end of the array's internal order
|
||||
* instead of directly taking the place of the older value.
|
||||
*/
|
||||
unset($this->permissions[$name]);
|
||||
}
|
||||
$this->permissions[$name] = $value;
|
||||
$this->permissible->recalculatePermissions();
|
||||
|
@ -36,9 +36,6 @@ class PermissionAttachmentInfo{
|
||||
/** @var bool */
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* @throws \InvalidStateException
|
||||
*/
|
||||
public function __construct(Permissible $permissible, string $permission, PermissionAttachment $attachment = null, bool $value){
|
||||
$this->permissible = $permissible;
|
||||
$this->permission = $permission;
|
||||
|
@ -157,7 +157,7 @@ class PermissionManager{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|Permissible[]
|
||||
* @return Permissible[]
|
||||
*/
|
||||
public function getPermissionSubscriptions(string $permission) : array{
|
||||
return $this->permSubs[$permission] ?? [];
|
||||
|
@ -156,7 +156,11 @@ class PluginDescription{
|
||||
}
|
||||
$this->authors = [];
|
||||
if(isset($plugin["author"])){
|
||||
$this->authors[] = $plugin["author"];
|
||||
if(is_array($plugin["author"])){
|
||||
$this->authors = $plugin["author"];
|
||||
}else{
|
||||
$this->authors[] = $plugin["author"];
|
||||
}
|
||||
}
|
||||
if(isset($plugin["authors"])){
|
||||
foreach($plugin["authors"] as $author){
|
||||
|
@ -701,9 +701,18 @@ class PluginManager{
|
||||
}
|
||||
|
||||
$handlerClosure = $method->getClosure($listener);
|
||||
if($handlerClosure === null) throw new AssumptionFailedError("This should never happen");
|
||||
|
||||
try{
|
||||
$eventClass = $parameters[0]->getClass();
|
||||
$paramType = $parameters[0]->getType();
|
||||
//isBuiltin() returns false for builtin classes ..................
|
||||
if($paramType instanceof \ReflectionNamedType && !$paramType->isBuiltin()){
|
||||
/** @phpstan-var class-string $paramClass */
|
||||
$paramClass = $paramType->getName();
|
||||
$eventClass = new \ReflectionClass($paramClass);
|
||||
}else{
|
||||
$eventClass = null;
|
||||
}
|
||||
}catch(\ReflectionException $e){ //class doesn't exist
|
||||
if(isset($tags["softDepend"]) && !isset($this->plugins[$tags["softDepend"]])){
|
||||
$this->server->getLogger()->debug("Not registering @softDepend listener " . Utils::getNiceClosureName($handlerClosure) . "() because plugin \"" . $tags["softDepend"] . "\" not found");
|
||||
|
Submodule src/pocketmine/resources/vanilla updated: afc885ccca...4e58a3c67d
@ -51,6 +51,7 @@ use function unserialize;
|
||||
abstract class AsyncTask extends Collectable{
|
||||
/**
|
||||
* @var \SplObjectStorage|null
|
||||
* @phpstan-var \SplObjectStorage<AsyncTask, mixed>
|
||||
* Used to store objects on the main thread which should not be serialized.
|
||||
*/
|
||||
private static $threadLocalStorage;
|
||||
@ -258,7 +259,9 @@ abstract class AsyncTask extends Collectable{
|
||||
}
|
||||
|
||||
if(self::$threadLocalStorage === null){
|
||||
self::$threadLocalStorage = new \SplObjectStorage(); //lazy init
|
||||
/** @phpstan-var \SplObjectStorage<AsyncTask, mixed> $storage */
|
||||
$storage = new \SplObjectStorage();
|
||||
self::$threadLocalStorage = $storage; //lazy init
|
||||
}
|
||||
|
||||
if(isset(self::$threadLocalStorage[$this])){
|
||||
|
@ -152,8 +152,7 @@ class Furnace extends Spawnable implements InventoryHolder, Container, Nameable{
|
||||
}
|
||||
|
||||
if($this->burnTime > 0 and $ev->isBurning()){
|
||||
$fuel->pop();
|
||||
$this->inventory->setFuel($fuel);
|
||||
$this->inventory->setFuel($fuel->getFuelResidue());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,6 @@ use pocketmine\Player;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\timings\TimingsHandler;
|
||||
use function current;
|
||||
use function get_class;
|
||||
use function in_array;
|
||||
use function is_a;
|
||||
@ -74,8 +73,8 @@ abstract class Tile extends Position{
|
||||
*/
|
||||
private static $knownTiles = [];
|
||||
/**
|
||||
* @var string[][]
|
||||
* @phpstan-var array<class-string<Tile>, list<string>>
|
||||
* @var string[]
|
||||
* @phpstan-var array<class-string<Tile>, string>
|
||||
*/
|
||||
private static $saveNames = [];
|
||||
|
||||
@ -138,7 +137,7 @@ abstract class Tile extends Position{
|
||||
self::$knownTiles[$name] = $className;
|
||||
}
|
||||
|
||||
self::$saveNames[$className] = $saveNames;
|
||||
self::$saveNames[$className] = reset($saveNames);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -154,8 +153,7 @@ abstract class Tile extends Position{
|
||||
throw new \InvalidStateException("Tile is not registered");
|
||||
}
|
||||
|
||||
reset(self::$saveNames[static::class]);
|
||||
return current(self::$saveNames[static::class]);
|
||||
return self::$saveNames[static::class];
|
||||
}
|
||||
|
||||
public function __construct(Level $level, CompoundTag $nbt){
|
||||
|
@ -30,6 +30,8 @@ use function fclose;
|
||||
use function file;
|
||||
use function file_get_contents;
|
||||
use function function_exists;
|
||||
use function getmypid;
|
||||
use function getmyuid;
|
||||
use function hexdec;
|
||||
use function memory_get_usage;
|
||||
use function posix_kill;
|
||||
@ -175,4 +177,20 @@ final class Process{
|
||||
|
||||
return proc_close($process);
|
||||
}
|
||||
|
||||
public static function pid() : int{
|
||||
$result = getmypid();
|
||||
if($result === false){
|
||||
throw new \LogicException("getmypid() doesn't work on this platform");
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function uid() : int{
|
||||
$result = getmyuid();
|
||||
if($result === false){
|
||||
throw new \LogicException("getmyuid() doesn't work on this platform");
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
||||
namespace pocketmine\utils;
|
||||
|
||||
use pocketmine\Thread;
|
||||
use function getmypid;
|
||||
use function time;
|
||||
|
||||
class ServerKiller extends Thread{
|
||||
@ -55,7 +54,7 @@ class ServerKiller extends Thread{
|
||||
});
|
||||
if(time() - $start >= $this->time){
|
||||
echo "\nTook too long to stop, server was killed forcefully!\n";
|
||||
@Process::kill(getmypid());
|
||||
@Process::kill(Process::pid());
|
||||
}
|
||||
}
|
||||
|
||||
|
48
src/pocketmine/utils/SingletonTrait.php
Normal file
48
src/pocketmine/utils/SingletonTrait.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?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\utils;
|
||||
|
||||
trait SingletonTrait{
|
||||
/** @var self|null */
|
||||
private static $instance = null;
|
||||
|
||||
private static function make() : self{
|
||||
return new self;
|
||||
}
|
||||
|
||||
public static function getInstance() : self{
|
||||
if(self::$instance === null){
|
||||
self::$instance = self::make();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public static function setInstance(self $instance) : void{
|
||||
self::$instance = $instance;
|
||||
}
|
||||
|
||||
public static function reset() : void{
|
||||
self::$instance = null;
|
||||
}
|
||||
}
|
@ -94,7 +94,7 @@ class UUID{
|
||||
}
|
||||
|
||||
public static function fromRandom() : UUID{
|
||||
return self::fromData(Binary::writeInt(time()), Binary::writeShort(getmypid()), Binary::writeShort(getmyuid()), Binary::writeInt(mt_rand(-0x7fffffff, 0x7fffffff)), Binary::writeInt(mt_rand(-0x7fffffff, 0x7fffffff)));
|
||||
return self::fromData(Binary::writeInt(time()), Binary::writeShort(($pid = getmypid()) !== false ? $pid : 0), Binary::writeShort(($uid = getmyuid()) !== false ? $uid : 0), Binary::writeInt(mt_rand(-0x7fffffff, 0x7fffffff)), Binary::writeInt(mt_rand(-0x7fffffff, 0x7fffffff)));
|
||||
}
|
||||
|
||||
public function toBinary() : string{
|
||||
|
@ -106,6 +106,9 @@ class Utils{
|
||||
public const OS_BSD = "bsd";
|
||||
public const OS_UNKNOWN = "other";
|
||||
|
||||
public const CLEAN_PATH_SRC_PREFIX = "pmsrc";
|
||||
public const CLEAN_PATH_PLUGINS_PREFIX = "plugins";
|
||||
|
||||
/** @var string|null */
|
||||
public static $os;
|
||||
/** @var UUID|null */
|
||||
@ -114,6 +117,8 @@ class Utils{
|
||||
/**
|
||||
* Generates an unique identifier to a callable
|
||||
*
|
||||
* @phpstan-param callable(mixed...) : mixed $variable
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getCallableIdentifier(callable $variable){
|
||||
@ -129,6 +134,7 @@ class Utils{
|
||||
/**
|
||||
* Returns a readable identifier for the given Closure, including file and line.
|
||||
*
|
||||
* @phpstan-param \Closure(mixed...) : mixed $closure
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public static function getNiceClosureName(\Closure $closure) : string{
|
||||
@ -189,7 +195,14 @@ class Utils{
|
||||
}
|
||||
|
||||
$machine = php_uname("a");
|
||||
$machine .= ($cpuinfo = @file("/proc/cpuinfo")) !== false ? implode(preg_grep("/(model name|Processor|Serial)/", $cpuinfo)) : "";
|
||||
$cpuinfo = @file("/proc/cpuinfo");
|
||||
if($cpuinfo !== false){
|
||||
$cpuinfoLines = preg_grep("/(model name|Processor|Serial)/", $cpuinfo);
|
||||
if($cpuinfoLines === false){
|
||||
throw new AssumptionFailedError("Pattern is valid, so this shouldn't fail ...");
|
||||
}
|
||||
$machine .= implode("", $cpuinfoLines);
|
||||
}
|
||||
$machine .= sys_get_temp_dir();
|
||||
$machine .= $extra;
|
||||
$os = Utils::getOS();
|
||||
@ -604,8 +617,8 @@ class Utils{
|
||||
//remove relative paths
|
||||
//TODO: make these paths dynamic so they can be unit-tested against
|
||||
static $cleanPaths = [
|
||||
\pocketmine\PLUGIN_PATH => "plugins", //this has to come BEFORE \pocketmine\PATH because it's inside that by default on src installations
|
||||
\pocketmine\PATH => ""
|
||||
\pocketmine\PLUGIN_PATH => self::CLEAN_PATH_PLUGINS_PREFIX, //this has to come BEFORE \pocketmine\PATH because it's inside that by default on src installations
|
||||
\pocketmine\PATH => self::CLEAN_PATH_SRC_PREFIX
|
||||
];
|
||||
foreach($cleanPaths as $cleanPath => $replacement){
|
||||
$cleanPath = rtrim(str_replace([DIRECTORY_SEPARATOR, "phar://"], ["/", ""], $cleanPath), "/");
|
||||
@ -675,6 +688,8 @@ class Utils{
|
||||
*
|
||||
* @param callable $signature Dummy callable with the required parameters and return type
|
||||
* @param callable $subject Callable to check the signature of
|
||||
* @phpstan-param callable(mixed...) : mixed $signature
|
||||
* @phpstan-param callable(mixed...) : mixed $subject
|
||||
*
|
||||
* @throws \DaveRandom\CallbackValidator\InvalidCallbackException
|
||||
* @throws \TypeError
|
||||
|
25
tests/gh-actions/build.sh
Executable file
25
tests/gh-actions/build.sh
Executable file
@ -0,0 +1,25 @@
|
||||
VERSION="$1"
|
||||
|
||||
sudo apt update && sudo apt install -y \
|
||||
re2c \
|
||||
libtool \
|
||||
libtool-bin \
|
||||
zlib1g-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libxml2-dev \
|
||||
libyaml-dev \
|
||||
libgmp-dev \
|
||||
libzip-dev \
|
||||
libssl-dev
|
||||
|
||||
INSTALL_DIR="$(pwd)/bin/php7"
|
||||
|
||||
export CFLAGS="$CFLAGS -march=x86-64"
|
||||
export CXXFLAGS="$CXXFLAGS -march=x86-64"
|
||||
|
||||
git clone https://github.com/php-build/php-build.git
|
||||
cd php-build
|
||||
./install-dependencies.sh
|
||||
echo '"pthreads",,"https://github.com/pmmp/pthreads.git",,,"extension",' >> share/php-build/extension/definition
|
||||
PHP_BUILD_INSTALL_EXTENSION='pthreads=@2bcd8b8c10395d58b8a9bc013e3a5328080c867f yaml=2.2.0' PHP_BUILD_ZTS_ENABLE=on ./bin/php-build "$VERSION" "$INSTALL_DIR"
|
||||
rm "$INSTALL_DIR/etc/conf.d/xdebug.ini" || true
|
@ -21,8 +21,6 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
define('pocketmine\_PHPSTAN_ANALYSIS', true);
|
||||
|
||||
if(!defined('LEVELDB_ZLIB_RAW_COMPRESSION')){
|
||||
//leveldb might not be loaded
|
||||
define('LEVELDB_ZLIB_RAW_COMPRESSION', 4);
|
||||
|
@ -745,6 +745,11 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/level/generator/normal/Normal.php
|
||||
|
||||
-
|
||||
message: "#^Method pocketmine\\\\metadata\\\\MetadataStore\\:\\:getMetadataInternal\\(\\) should return array\\<pocketmine\\\\metadata\\\\MetadataValue\\> but returns SplObjectStorage\\<pocketmine\\\\plugin\\\\Plugin, pocketmine\\\\metadata\\\\MetadataValue\\>\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/metadata/MetadataStore.php
|
||||
|
||||
-
|
||||
message: "#^Variable method call on pocketmine\\\\event\\\\Listener\\.$#"
|
||||
count: 1
|
||||
|
@ -45,6 +45,31 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/Player.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$str of function base64_decode expects string, mixed given\\.$#"
|
||||
count: 5
|
||||
path: ../../../src/pocketmine/Player.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$height of class pocketmine\\\\network\\\\mcpe\\\\protocol\\\\types\\\\SkinImage constructor expects int, mixed given\\.$#"
|
||||
count: 2
|
||||
path: ../../../src/pocketmine/Player.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$width of class pocketmine\\\\network\\\\mcpe\\\\protocol\\\\types\\\\SkinImage constructor expects int, mixed given\\.$#"
|
||||
count: 2
|
||||
path: ../../../src/pocketmine/Player.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#8 \\$premium of class pocketmine\\\\network\\\\mcpe\\\\protocol\\\\types\\\\SkinData constructor expects bool, mixed given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/Player.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#9 \\$persona of class pocketmine\\\\network\\\\mcpe\\\\protocol\\\\types\\\\SkinData constructor expects bool, mixed given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/Player.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#10 \\$personaCapeOnClassic of class pocketmine\\\\network\\\\mcpe\\\\protocol\\\\types\\\\SkinData constructor expects bool, mixed given\\.$#"
|
||||
count: 1
|
||||
@ -65,31 +90,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/Player.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#8 \\$premium of class pocketmine\\\\network\\\\mcpe\\\\protocol\\\\types\\\\SkinData constructor expects bool, mixed given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/Player.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#9 \\$persona of class pocketmine\\\\network\\\\mcpe\\\\protocol\\\\types\\\\SkinData constructor expects bool, mixed given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/Player.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$str of function base64_decode expects string, mixed given\\.$#"
|
||||
count: 5
|
||||
path: ../../../src/pocketmine/Player.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$height of class pocketmine\\\\network\\\\mcpe\\\\protocol\\\\types\\\\SkinImage constructor expects int, mixed given\\.$#"
|
||||
count: 2
|
||||
path: ../../../src/pocketmine/Player.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$width of class pocketmine\\\\network\\\\mcpe\\\\protocol\\\\types\\\\SkinImage constructor expects int, mixed given\\.$#"
|
||||
count: 2
|
||||
path: ../../../src/pocketmine/Player.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\.\\.\\.\\$slots of method pocketmine\\\\inventory\\\\BaseInventory\\:\\:addItem\\(\\) expects pocketmine\\\\item\\\\Item, mixed given\\.$#"
|
||||
count: 1
|
||||
@ -185,11 +185,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/entity/Effect.php
|
||||
|
||||
-
|
||||
message: "#^Method pocketmine\\\\entity\\\\Entity\\:\\:getSaveId\\(\\) should return string but returns mixed\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/entity/Entity.php
|
||||
|
||||
-
|
||||
message: "#^Cannot cast mixed to int\\.$#"
|
||||
count: 2
|
||||
@ -280,11 +275,6 @@ parameters:
|
||||
count: 6
|
||||
path: ../../../src/pocketmine/level/generator/noise/Noise.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method invalidate\\(\\) on mixed\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/metadata/MetadataStore.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$buffer of class pocketmine\\\\network\\\\mcpe\\\\protocol\\\\BatchPacket constructor expects string, mixed given\\.$#"
|
||||
count: 1
|
||||
@ -455,11 +445,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/network/mcpe/protocol/SetActorDataPacket.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$table of static method pocketmine\\\\network\\\\mcpe\\\\protocol\\\\StartGamePacket\\:\\:serializeItemTable\\(\\) expects array\\<string, int\\>, mixed given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/network/mcpe/protocol/StartGamePacket.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$value of static method pocketmine\\\\permission\\\\Permission\\:\\:getByName\\(\\) expects bool\\|string, mixed given\\.$#"
|
||||
count: 1
|
||||
@ -560,11 +545,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/scheduler/AsyncTask.php
|
||||
|
||||
-
|
||||
message: "#^Method pocketmine\\\\tile\\\\Tile\\:\\:getSaveId\\(\\) should return string but returns mixed\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/tile/Tile.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$timestamp of function date expects int, mixed given\\.$#"
|
||||
count: 1
|
||||
|
@ -60,16 +60,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/PocketMine.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$filename of function is_file expects string, array\\<int, mixed\\>\\|string given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/PocketMine.php
|
||||
|
||||
-
|
||||
message: "#^Binary operation \"\\.\" between 'Composer autoloader…' and array\\<int, mixed\\>\\|string\\|false results in an error\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/PocketMine.php
|
||||
|
||||
-
|
||||
message: "#^Binary operation \"\\.\" between array\\<int, mixed\\>\\|string\\|false and '/'\\|'\\\\\\\\' results in an error\\.$#"
|
||||
count: 2
|
||||
@ -155,51 +145,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Cactus.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x of method pocketmine\\\\level\\\\Level\\:\\:getBlockIdAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Farmland.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$y of method pocketmine\\\\level\\\\Level\\:\\:getBlockIdAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Farmland.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$z of method pocketmine\\\\level\\\\Level\\:\\:getBlockIdAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Farmland.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x of method pocketmine\\\\level\\\\Level\\:\\:getFullLightAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Grass.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$y of method pocketmine\\\\level\\\\Level\\:\\:getFullLightAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Grass.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$z of method pocketmine\\\\level\\\\Level\\:\\:getFullLightAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Grass.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x of method pocketmine\\\\level\\\\Level\\:\\:getBlockIdAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Grass.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$y of method pocketmine\\\\level\\\\Level\\:\\:getBlockIdAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Grass.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$z of method pocketmine\\\\level\\\\Level\\:\\:getBlockIdAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Grass.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$min of function mt_rand expects int, float\\|int given\\.$#"
|
||||
count: 3
|
||||
@ -210,36 +155,6 @@ parameters:
|
||||
count: 3
|
||||
path: ../../../src/pocketmine/block/Grass.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x of method pocketmine\\\\level\\\\Level\\:\\:getHighestAdjacentBlockLight\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Ice.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$y of method pocketmine\\\\level\\\\Level\\:\\:getHighestAdjacentBlockLight\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Ice.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$z of method pocketmine\\\\level\\\\Level\\:\\:getHighestAdjacentBlockLight\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Ice.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x of method pocketmine\\\\level\\\\Level\\:\\:getBlockAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 23
|
||||
path: ../../../src/pocketmine/block/Liquid.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$y of method pocketmine\\\\level\\\\Level\\:\\:getBlockAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 23
|
||||
path: ../../../src/pocketmine/block/Liquid.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$z of method pocketmine\\\\level\\\\Level\\:\\:getBlockAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 23
|
||||
path: ../../../src/pocketmine/block/Liquid.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x of static method pocketmine\\\\level\\\\Level\\:\\:blockHash\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 3
|
||||
@ -295,36 +210,6 @@ parameters:
|
||||
count: 2
|
||||
path: ../../../src/pocketmine/block/Sapling.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x of method pocketmine\\\\level\\\\Level\\:\\:getFullLightAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Sapling.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$y of method pocketmine\\\\level\\\\Level\\:\\:getFullLightAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Sapling.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$z of method pocketmine\\\\level\\\\Level\\:\\:getFullLightAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/Sapling.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x of method pocketmine\\\\level\\\\Level\\:\\:getBlockLightAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/SnowLayer.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$y of method pocketmine\\\\level\\\\Level\\:\\:getBlockLightAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/SnowLayer.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$z of method pocketmine\\\\level\\\\Level\\:\\:getBlockLightAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/block/SnowLayer.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x of method pocketmine\\\\level\\\\Level\\:\\:getBlockAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 2
|
||||
@ -390,26 +275,16 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/command/defaults/TimingsCommand.php
|
||||
|
||||
-
|
||||
message: "#^Array \\(array\\<class\\-string\\<pocketmine\\\\entity\\\\Entity\\>, string\\>\\) does not accept string\\|false\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/entity/Entity.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$index of method pocketmine\\\\inventory\\\\BaseInventory\\:\\:setItem\\(\\) expects int, int\\|string given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/entity/Human.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x of method pocketmine\\\\level\\\\Level\\:\\:getBlockAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/entity/Living.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$y of method pocketmine\\\\level\\\\Level\\:\\:getBlockAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/entity/Living.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$z of method pocketmine\\\\level\\\\Level\\:\\:getBlockAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/entity/Living.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x of method pocketmine\\\\level\\\\Level\\:\\:getBlockAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
@ -430,21 +305,6 @@ parameters:
|
||||
count: 3
|
||||
path: ../../../src/pocketmine/entity/projectile/Projectile.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x of method pocketmine\\\\level\\\\Level\\:\\:getBlockAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 2
|
||||
path: ../../../src/pocketmine/entity/projectile/Projectile.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$y of method pocketmine\\\\level\\\\Level\\:\\:getBlockAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 2
|
||||
path: ../../../src/pocketmine/entity/projectile/Projectile.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$z of method pocketmine\\\\level\\\\Level\\:\\:getBlockAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 2
|
||||
path: ../../../src/pocketmine/entity/projectile/Projectile.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$argument of class ReflectionClass constructor expects class\\-string\\<T of object\\>\\|T of object, string given\\.$#"
|
||||
count: 1
|
||||
@ -680,11 +540,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/level/Level.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$y of method pocketmine\\\\level\\\\format\\\\Chunk\\:\\:setBlock\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/level/Level.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x of static method pocketmine\\\\level\\\\Level\\:\\:chunkBlockHash\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
@ -765,16 +620,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/level/generator/object/TallGrass.php
|
||||
|
||||
-
|
||||
message: "#^Method pocketmine\\\\metadata\\\\MetadataStore\\:\\:getMetadataInternal\\(\\) should return array\\<pocketmine\\\\metadata\\\\MetadataValue\\> but returns array\\<pocketmine\\\\metadata\\\\MetadataValue\\>\\|SplObjectStorage\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/metadata/MetadataStore.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method count\\(\\) on array\\<pocketmine\\\\metadata\\\\MetadataValue\\>\\|SplObjectStorage\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/metadata/MetadataStore.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$str of method pocketmine\\\\utils\\\\BinaryStream\\:\\:put\\(\\) expects string, string\\|false given\\.$#"
|
||||
count: 2
|
||||
@ -820,11 +665,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/network/mcpe/VerifyLoginTask.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$buffer of method pocketmine\\\\nbt\\\\NBTStream\\:\\:read\\(\\) expects string, string\\|false given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/network/mcpe/convert/RuntimeBlockMapping.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$json of function json_decode expects string, string\\|false given\\.$#"
|
||||
count: 1
|
||||
@ -860,6 +700,11 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/network/mcpe/protocol/BiomeDefinitionListPacket.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$str of method pocketmine\\\\utils\\\\BinaryStream\\:\\:put\\(\\) expects string, string\\|false given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/network/mcpe/protocol/ItemComponentPacket.php
|
||||
|
||||
-
|
||||
message: "#^Property pocketmine\\\\network\\\\mcpe\\\\protocol\\\\LevelEventGenericPacket\\:\\:\\$eventData \\(string\\) does not accept string\\|false\\.$#"
|
||||
count: 1
|
||||
@ -870,26 +715,11 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/network/mcpe/protocol/PositionTrackingDBServerBroadcastPacket.php
|
||||
|
||||
-
|
||||
message: "#^Static property pocketmine\\\\network\\\\mcpe\\\\protocol\\\\StartGamePacket\\:\\:\\$blockTableCache \\(string\\|null\\) does not accept string\\|false\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/network/mcpe/protocol/StartGamePacket.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$str of method pocketmine\\\\utils\\\\BinaryStream\\:\\:put\\(\\) expects string, string\\|false given\\.$#"
|
||||
count: 2
|
||||
path: ../../../src/pocketmine/network/mcpe/protocol/StartGamePacket.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$json of function json_decode expects string, string\\|false given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/network/mcpe/protocol/StartGamePacket.php
|
||||
|
||||
-
|
||||
message: "#^Property pocketmine\\\\network\\\\mcpe\\\\protocol\\\\UpdateBlockPropertiesPacket\\:\\:\\$nbt \\(string\\) does not accept string\\|false\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/network/mcpe/protocol/UpdateBlockPropertiesPacket.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$resourcePatch of class pocketmine\\\\network\\\\mcpe\\\\protocol\\\\types\\\\SkinData constructor expects string, string\\|false given\\.$#"
|
||||
count: 1
|
||||
@ -985,23 +815,13 @@ parameters:
|
||||
count: 3
|
||||
path: ../../../src/pocketmine/tile/Spawnable.php
|
||||
|
||||
-
|
||||
message: "#^Array \\(array\\<class\\-string\\<pocketmine\\\\tile\\\\Tile\\>, string\\>\\) does not accept string\\|false\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/tile/Tile.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$value of method pocketmine\\\\nbt\\\\tag\\\\CompoundTag\\:\\:setInt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 3
|
||||
path: ../../../src/pocketmine/tile/Tile.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x of method pocketmine\\\\level\\\\Level\\:\\:getBlockAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/tile/Tile.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$y of method pocketmine\\\\level\\\\Level\\:\\:getBlockAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/tile/Tile.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$z of method pocketmine\\\\level\\\\Level\\:\\:getBlockAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/tile/Tile.php
|
||||
|
||||
|
@ -1440,31 +1440,11 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/level/light/SkyLightUpdate.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getTag\\(\\) on pocketmine\\\\nbt\\\\tag\\\\CompoundTag\\|null\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/network/mcpe/NetworkBinaryStream.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method removeTag\\(\\) on pocketmine\\\\nbt\\\\tag\\\\CompoundTag\\|null\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/network/mcpe/NetworkBinaryStream.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method setTag\\(\\) on pocketmine\\\\nbt\\\\tag\\\\CompoundTag\\|null\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/network/mcpe/NetworkBinaryStream.php
|
||||
|
||||
-
|
||||
message: "#^Argument of an invalid type array\\<pocketmine\\\\nbt\\\\tag\\\\CompoundTag\\>\\|null supplied for foreach, only iterables are supported\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/network/mcpe/convert/RuntimeBlockMapping.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$that of method pocketmine\\\\nbt\\\\tag\\\\NamedTag\\:\\:equals\\(\\) expects pocketmine\\\\nbt\\\\tag\\\\NamedTag, pocketmine\\\\nbt\\\\tag\\\\CompoundTag\\|null given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/network/mcpe/convert/RuntimeBlockMapping.php
|
||||
|
||||
-
|
||||
message: "#^Method pocketmine\\\\network\\\\mcpe\\\\convert\\\\RuntimeBlockMapping\\:\\:getBedrockKnownStates\\(\\) should return array\\<pocketmine\\\\nbt\\\\tag\\\\CompoundTag\\> but returns array\\<pocketmine\\\\nbt\\\\tag\\\\CompoundTag\\>\\|null\\.$#"
|
||||
count: 1
|
||||
@ -1500,11 +1480,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/pocketmine/plugin/PluginBase.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$closure of static method pocketmine\\\\utils\\\\Utils\\:\\:getNiceClosureName\\(\\) expects Closure, Closure\\|null given\\.$#"
|
||||
count: 3
|
||||
path: ../../../src/pocketmine/plugin/PluginManager.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method handleException\\(\\) on pocketmine\\\\scheduler\\\\AsyncWorker\\|null\\.$#"
|
||||
count: 1
|
||||
|
Submodule tests/plugins/DevTools updated: 9a43721a2f...1606a4307b
@ -11,17 +11,19 @@ while getopts "t:" OPTION 2> /dev/null; do
|
||||
done
|
||||
|
||||
#Run-the-server tests
|
||||
DATA_DIR="test_data"
|
||||
DATA_DIR="$(pwd)/test_data"
|
||||
PLUGINS_DIR="$DATA_DIR/plugins"
|
||||
|
||||
rm -rf "$DATA_DIR"
|
||||
rm PocketMine-MP.phar 2> /dev/null
|
||||
mkdir "$DATA_DIR"
|
||||
mkdir "$PLUGINS_DIR"
|
||||
|
||||
cd tests/plugins/DevTools
|
||||
php -dphar.readonly=0 ./src/DevTools/ConsoleScript.php --make ./ --relative ./ --out ../../../DevTools.phar
|
||||
php -dphar.readonly=0 ./src/DevTools/ConsoleScript.php --make ./ --relative ./ --out "$PLUGINS_DIR/DevTools.phar"
|
||||
cd ../../..
|
||||
composer make-server
|
||||
|
||||
php -dphar.readonly=0 ./build/server-phar.php ./PocketMine-MP.phar
|
||||
if [ -f PocketMine-MP.phar ]; then
|
||||
echo Server phar created successfully.
|
||||
else
|
||||
@ -29,9 +31,6 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir "$DATA_DIR"
|
||||
mkdir "$PLUGINS_DIR"
|
||||
mv DevTools.phar "$PLUGINS_DIR"
|
||||
cp -r tests/plugins/TesterPlugin "$PLUGINS_DIR"
|
||||
echo -e "stop\n" | php PocketMine-MP.phar --no-wizard --disable-ansi --disable-readline --debug.level=2 --data="$DATA_DIR" --plugins="$PLUGINS_DIR" --anonymous-statistics.enabled=0 --settings.async-workers="$PM_WORKERS" --settings.enable-dev-builds=1
|
||||
|
||||
|
@ -1,18 +0,0 @@
|
||||
language: php
|
||||
php:
|
||||
- 7.3
|
||||
- 7.4
|
||||
|
||||
before_script:
|
||||
- phpenv config-rm xdebug.ini
|
||||
- echo | pecl install channel://pecl.php.net/yaml-2.1.0
|
||||
- git clone https://github.com/pmmp/pthreads.git
|
||||
- cd pthreads
|
||||
- git checkout b81ab29df58fa0fb239a9d5ca1c2380a0d087feb
|
||||
- phpize
|
||||
- ./configure
|
||||
- make
|
||||
- make install
|
||||
- cd ..
|
||||
- echo "extension=pthreads.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
|
||||
- composer self-update --2
|
Reference in New Issue
Block a user