Compare commits

..

49 Commits

Author SHA1 Message Date
61391b6e23 Release 3.17.6 2021-03-10 20:48:57 +00:00
fbb6f1f81c Workaround for cursor sync in 1.13+, closes #4059 2021-03-07 21:17:52 +00:00
712df04bc4 Updated NBT dependency to 0.2.17 2021-03-07 21:06:08 +00:00
1563e25378 Updated composer dependencies 2021-03-07 19:57:16 +00:00
ed84252942 Player: Improved XUID verification
we check if an existing player is online with a matching XUID first; if there isn't, we don't bother loading the playerdata, since that other player couldn't have joined unless they had a match or were allowed to bypass.
2021-03-07 19:53:19 +00:00
3d90625020 Revert "Revert "Use PHP 7.4.16 for Actions""
This reverts commit 9f6b914925.
2021-03-07 16:37:33 +00:00
9f6b914925 Revert "Use PHP 7.4.16 for Actions"
This reverts commit 0e614ea8fd.

apparently php-build doesn't have 7.4.16 yet ...
2021-03-06 00:41:19 +00:00
0e614ea8fd Use PHP 7.4.16 for Actions 2021-03-06 00:32:56 +00:00
401bd09d60 Bump phpstan/phpstan from 0.12.79 to 0.12.80 (#4054) 2021-03-01 16:56:23 +00:00
649671cc69 Bump phpstan/phpstan from 0.12.78 to 0.12.79 (#4051) 2021-02-27 17:42:19 +00:00
e755e1dc23 ResourcePackClientResponsePacket: fixed non-deterministic decoding 2021-02-27 01:08:18 +00:00
e34a444dde Bump phpstan/phpstan from 0.12.77 to 0.12.78 (#4046) 2021-02-26 00:34:38 +00:00
78f9985377 Player: fixed PlayerMoveEvent->getFrom() returning unexpected results on movement reversion
fixes #4043
2021-02-26 00:30:42 +00:00
fac2bd3379 Liquid: mark getSmallestFlowDecay() as impure
this fixes two bogus PHPStan warnings.
2021-02-25 22:41:07 +00:00
fcfd51dfc7 CrashDump: do not put FALSE into crashdumps in case file_get_contents() failed 2021-02-23 19:39:21 +00:00
ccc76cf338 Make less noise about XBL being enabled
this has been in force for years now, it's expected by now.
2021-02-23 19:25:22 +00:00
10a73488ed Merge branch 'stable' of https://github.com/pmmp/pocketmine-mp into stable 2021-02-22 16:43:51 +00:00
9c5114084b Updated Snooze to fix race conditions 2021-02-22 16:42:54 +00:00
11630ab1aa Bump phpstan/phpstan from 0.12.76 to 0.12.77 (#4041) 2021-02-18 11:34:42 +00:00
a3068b39a2 Update composer dependencies 2021-02-16 22:31:01 +00:00
edbc73a72c 3.17.6 is next 2021-02-16 22:13:05 +00:00
3a0c8dd594 Release 3.17.5 2021-02-16 22:13:05 +00:00
16fa26405a Remove remaining usages of LevelDB::close()
this is handled by the object destructor.

closes #4035
2021-02-15 20:10:11 +00:00
57423540f0 BUILDING.md: Document server-phar.php's compression bug (#4037)
This bug is not fixable on PM's side because the fault lies with php-src. It was fixed recently in 1bb2a4f91c.
2021-02-15 19:53:44 +00:00
8f8821c904 Bump phpstan/phpstan from 0.12.75 to 0.12.76 (#4038) 2021-02-15 11:25:36 +00:00
094102fe92 fopen() might return FALSE if permission was denied to read/write the file 2021-02-12 16:16:36 +00:00
2aef83e7d7 MainLogger: fix type ambiguity 2021-02-12 15:05:24 +00:00
5c3e78e1d3 Bump phpstan/phpstan from 0.12.74 to 0.12.75 (#4033) 2021-02-12 14:58:01 +00:00
18666e5a60 Be compatible with newest versions of php-leveldb 2021-02-11 22:33:29 +00:00
f72163c173 Fixed build not failing when PHP build gets borked 2021-02-11 17:06:03 +00:00
7407e504b6 actions: bump PHP versions to 7.3.27 and 7.4.15 2021-02-11 16:35:19 +00:00
0e396dc47d actions: update PHP extension versions 2021-02-11 16:24:09 +00:00
d2204da1d5 [ci skip] center the build badges 2021-02-11 16:05:55 +00:00
2a51269305 Merge branch 'stable' of https://github.com/pmmp/pocketmine-mp into stable 2021-02-11 16:05:24 +00:00
928041ddf1 Bump phpstan/phpstan from 0.12.71 to 0.12.74 (#4028)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 0.12.71 to 0.12.74.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Commits](https://github.com/phpstan/phpstan/compare/0.12.71...0.12.74)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2021-02-08 21:42:08 +00:00
007f4f9350 CraftingDataPacket: Remove useless @var comment 2021-02-08 11:53:50 +00:00
46e9f0cec6 Player: fixed verify-xuid not kicking in by default on old configs 2021-02-07 21:10:23 +00:00
606d56b55d Composer: lock in PHP at ^7.3 || ^8.0, don't leave it unbounded 2021-02-07 17:31:32 +00:00
78a62a8b27 Remember and verify player XUIDs (controlled by player.verify-xuid in pocketmine.yml) 2021-02-05 14:42:57 +00:00
c5bdd7dd64 Added a unit test to ensure valid format of MINECRAFT_VERSION_NETWORK 2021-02-04 22:36:40 +00:00
8ee37a3033 Bump phpunit/phpunit from 9.5.1 to 9.5.2 (#4023) 2021-02-04 16:46:22 +00:00
7e3e63f342 Fixed race condition in MainLogger shutdown
this resulted in a deadlock in https://github.com/pmmp/PocketMine-MP/runs/1831812620?check_suite_focus=true because the notify() arrived while writeLogStream() was executing.
This ensures that either:
- the notification will occur before the sleep, and therefore no sleeping will occur (this->shutdown = true before the wait)
- the notification will arrive during the sleep.
2021-02-04 16:40:10 +00:00
8ef1e54e20 MainLogger: fixing CPU waste on logger thread
this doesn't need to keep spinning every 25ms; it can just wake up when there's actually log messages to write into the buffer.
2021-02-04 15:07:40 +00:00
eaf3a86981 MainLogger: fixed UB in writeLogStream()
notify() has to be used inside a synchronized block.
2021-02-04 15:03:14 +00:00
317a48d9b0 ItemStackRequest: expose filterStrings 2021-02-03 23:40:34 +00:00
bc14660e55 Added missing ItemStackRequest protocol changes 2021-02-03 23:37:41 +00:00
b1bb9fbd1c Reinstall PHP deps on cache hit
the 20.04 actions image doesn't have libzip5 and who knows what else is missing ...
2021-02-03 17:42:11 +00:00
96181f8cf5 Version PHP build caches by image version
we can't safely use `ubuntu-latest` because the build caches will break if they were built for 18.04 and used on 20.04, or vice versa. Instead, we pin the images (and caches) to a specific version.
2021-02-03 17:24:50 +00:00
4771e3dc28 3.17.5 is next 2021-02-02 14:04:51 +00:00
25 changed files with 329 additions and 158 deletions

View File

@ -8,11 +8,12 @@ on:
jobs:
build-php:
name: Prepare PHP
runs-on: ubuntu-latest
runs-on: ${{ matrix.image }}
strategy:
matrix:
php: [7.3.25, 7.4.13]
image: [ubuntu-20.04]
php: [7.3.27, 7.4.16]
steps:
- uses: actions/checkout@v2 #needed for build.sh
@ -21,7 +22,7 @@ jobs:
uses: actions/cache@v2
with:
path: "./bin"
key: "php-build-generic-${{ matrix.php }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
- name: Compile PHP
if: steps.php-build-cache.outputs.cache-hit != 'true'
@ -30,12 +31,13 @@ jobs:
phpstan:
name: PHPStan analysis
needs: build-php
runs-on: ubuntu-latest
runs-on: ${{ matrix.image }}
strategy:
fail-fast: false
matrix:
php: [7.3.25, 7.4.13]
image: [ubuntu-20.04]
php: [7.3.27, 7.4.16]
steps:
- uses: actions/checkout@v2
@ -45,12 +47,16 @@ jobs:
uses: actions/cache@v2
with:
path: "./bin"
key: "php-build-generic-${{ matrix.php }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
- name: Kill build on PHP build cache miss (should never happen)
if: steps.php-build-cache.outputs.cache-hit != 'true'
run: exit 1
- name: Install cached PHP's dependencies
if: steps.php-build-cache.outputs.cache-hit == 'true'
run: chmod +x ./bin/php7/install-dependencies.sh && ./bin/php7/install-dependencies.sh
- name: Prefix PHP to PATH
run: echo "$(pwd)/bin/php7/bin" >> $GITHUB_PATH
@ -76,11 +82,12 @@ jobs:
phpunit:
name: PHPUnit tests
needs: build-php
runs-on: ubuntu-latest
runs-on: ${{ matrix.image }}
strategy:
fail-fast: false
matrix:
php: [7.3.25, 7.4.13]
image: [ubuntu-20.04]
php: [7.3.27, 7.4.16]
steps:
- uses: actions/checkout@v2
@ -90,12 +97,16 @@ jobs:
uses: actions/cache@v2
with:
path: "./bin"
key: "php-build-generic-${{ matrix.php }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
- name: Kill build on PHP build cache miss (should never happen)
if: steps.php-build-cache.outputs.cache-hit != 'true'
run: exit 1
- name: Install cached PHP's dependencies
if: steps.php-build-cache.outputs.cache-hit == 'true'
run: chmod +x ./bin/php7/install-dependencies.sh && ./bin/php7/install-dependencies.sh
- name: Prefix PHP to PATH
run: echo "$(pwd)/bin/php7/bin" >> $GITHUB_PATH
@ -121,11 +132,12 @@ jobs:
integration:
name: Integration tests
needs: build-php
runs-on: ubuntu-latest
runs-on: ${{ matrix.image }}
strategy:
fail-fast: false
matrix:
php: [7.3.25, 7.4.13]
image: [ubuntu-20.04]
php: [7.3.27, 7.4.16]
steps:
- uses: actions/checkout@v2
@ -137,12 +149,16 @@ jobs:
uses: actions/cache@v2
with:
path: "./bin"
key: "php-build-generic-${{ matrix.php }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
key: "php-build-generic-${{ matrix.php }}-${{ matrix.image }}-${{ hashFiles('./tests/gh-actions/build.sh') }}"
- name: Kill build on PHP build cache miss (should never happen)
if: steps.php-build-cache.outputs.cache-hit != 'true'
run: exit 1
- name: Install cached PHP's dependencies
if: steps.php-build-cache.outputs.cache-hit == 'true'
run: chmod +x ./bin/php7/install-dependencies.sh && ./bin/php7/install-dependencies.sh
- name: Prefix PHP to PATH
run: echo "$(pwd)/bin/php7/bin" >> $GITHUB_PATH

View File

@ -34,5 +34,11 @@ Run `composer make-server` using your preferred PHP binary. It'll drop a `Pocket
You can also use the `--out` option to change the output filename.
There is a bug in PHP that might cause an error which looks like this:
```
Fatal error: Uncaught BadMethodCallException: unable to create temporary file in PocketMine-MP/build/server-phar.php:119
```
You can work around it by setting `ulimit -n` to some bigger number, e.g. `8192`, or by updating your PHP version to at least 7.4.16 or 8.0.3.
## Running PocketMine-MP from source code
Run `src/pocketmine/PocketMine.php` using your preferred PHP binary.

View File

@ -3,10 +3,12 @@
<b>A highly customisable, open source server software for Minecraft: Bedrock Edition written in PHP</b>
</p>
![CI](https://github.com/pmmp/PocketMine-MP/workflows/CI/badge.svg)
[![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/pmmp/PocketMine-MP?label=release&logo=github)](https://github.com/pmmp/PocketMine-MP/releases)
[![Docker Image Version (latest semver)](https://img.shields.io/docker/v/pmmp/pocketmine-mp?logo=docker&label=image)](https://hub.docker.com/r/pmmp/pocketmine-mp)
[![Discord](https://img.shields.io/discord/373199722573201408?label=discord&color=7289DA&logo=discord)](https://discord.gg/bmSAZBG)
<p align="center">
<img src="https://github.com/pmmp/PocketMine-MP/workflows/CI/badge.svg" alt="CI" />
<a href="https://github.com/pmmp/PocketMine-MP/releases"><img src="https://img.shields.io/github/v/tag/pmmp/PocketMine-MP?label=release&logo=github" alt="GitHub tag (latest semver)" /></a>
<a href="https://hub.docker.com/r/pmmp/pocketmine-mp"><img src="https://img.shields.io/docker/v/pmmp/pocketmine-mp?logo=docker&label=image" alt="Docker image version (latest semver)" /></a>
<a href="https://discord.gg/bmSAZBG"><img src="https://img.shields.io/discord/373199722573201408?label=discord&color=7289DA&logo=discord" alt="Discord" /></a>
</p>
## Getting started
- [Documentation](http://pmmp.readthedocs.org/)

View File

@ -41,3 +41,20 @@ Plugin developers should **only** update their required API to this version if y
- `CraftItemEvent->getOutputs()` now returns a list starting at offset 0, instead of random offsets. (Note that the contents still won't be ordered.)
- Fixed a bug that broke synchronized building, bridging, towering and more.
- Objects in memory dumps no longer show inherited properties multiple times.
# 3.17.5
- Reduced CPU wastage by the logger thread.
- Fixed LevelDB deprecation errors on PHP 8.0.
- Added some protocol changes for 1.16.200 which were previously overlooked.
- Player XUIDs are now tracked. If a player's XUID does not match the previously recorded XUID when they next join the server, they will be kicked. This can be disabled by the `player.verify-xuid` setting in `pocketmine.yml`.
- `BUILDING.md` now has a note about `build/server-phar.php`'s compression bug (a bug in PHP).
# 3.17.6
- Fixed core race conditions that could have led to server freezes (race conditions in pmmp/Snooze).
- The log message about Xbox Live authentication being enabled has been reduced to INFO, and the tip on how to turn it off removed (disabling it should usually only be done by power users anyway).
- Fixed `PlayerMoveEvent->getFrom()` returning incorrect results for players who experienced movement reversions.
- Fixed a bug in `ResourcePackClientResponsePacket` decoding that caused unexpected results when decoding the packet twice.
- XUID verification now compares XUIDs against players who are already on the server to detect mismatches to avoid unnecessary loading of playerdata.
- Fixed an inventory duplication bug which could occur when the same player joined with two devices at the same time.
- Fixed cursor item not being synced on inventory transaction rollbacks.
- Fixed items with TAG_Float in their NBT not being able to be moved around in the inventory.

View File

@ -5,10 +5,10 @@
"homepage": "https://pmmp.io",
"license": "LGPL-3.0",
"require": {
"php": ">=7.3.0",
"php": "^7.3 || ^8.0",
"php-64bit": "*",
"ext-curl": "*",
"ext-ctype": "*",
"ext-curl": "*",
"ext-date": "*",
"ext-hash": "*",
"ext-json": "*",
@ -23,21 +23,21 @@
"ext-yaml": ">=2.0.0",
"ext-zip": "*",
"ext-zlib": ">=1.2.11",
"pocketmine/raklib": "^0.12.7",
"pocketmine/spl": "^0.4.0",
"composer-runtime-api": "^2.0",
"adhocore/json-comment": "^0.1.0",
"pocketmine/binaryutils": "^0.1.9",
"pocketmine/nbt": "^0.2.10",
"pocketmine/math": "^0.2.0",
"pocketmine/snooze": "^0.1.0",
"pocketmine/callback-validator": "^1.0.2",
"pocketmine/classloader": "^0.1.0",
"pocketmine/log": "^0.2.0",
"pocketmine/log-pthreads": "^0.1.0",
"pocketmine/callback-validator": "^1.0.2",
"adhocore/json-comment": "^0.1.0",
"composer-runtime-api": "^2.0"
"pocketmine/math": "^0.2.0",
"pocketmine/nbt": "^0.2.10",
"pocketmine/raklib": "^0.12.7",
"pocketmine/snooze": "^0.1.0",
"pocketmine/spl": "^0.4.0"
},
"require-dev": {
"phpstan/phpstan": "0.12.71",
"phpstan/phpstan": "0.12.80",
"phpstan/phpstan-phpunit": "^0.12.6",
"phpstan/phpstan-strict-rules": "^0.12.2",
"phpunit/phpunit": "^9.2"

100
composer.lock generated
View File

@ -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": "e6d407c8e77d6a9305bbeff8c8e2c560",
"content-hash": "4ed24eeab1fdf52c6b9a797a42e10638",
"packages": [
{
"name": "adhocore/json-comment",
@ -315,16 +315,16 @@
},
{
"name": "pocketmine/nbt",
"version": "0.2.16",
"version": "0.2.17",
"source": {
"type": "git",
"url": "https://github.com/pmmp/NBT.git",
"reference": "be6d54a8a314967d938b501eee49d4641e2ab07d"
"reference": "7de6bdfdfbcafe2689aafbde47f6506f265afd19"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/be6d54a8a314967d938b501eee49d4641e2ab07d",
"reference": "be6d54a8a314967d938b501eee49d4641e2ab07d",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/7de6bdfdfbcafe2689aafbde47f6506f265afd19",
"reference": "7de6bdfdfbcafe2689aafbde47f6506f265afd19",
"shasum": ""
},
"require": {
@ -336,7 +336,7 @@
"require-dev": {
"irstea/phpunit-shim": "^7.5 || ^8.0",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "0.12.67",
"phpstan/phpstan": "0.12.80",
"phpstan/phpstan-strict-rules": "^0.12.4"
},
"type": "library",
@ -352,22 +352,22 @@
"description": "PHP library for working with Named Binary Tags",
"support": {
"issues": "https://github.com/pmmp/NBT/issues",
"source": "https://github.com/pmmp/NBT/tree/0.2.16"
"source": "https://github.com/pmmp/NBT/tree/0.2.17"
},
"time": "2021-01-15T15:27:28+00:00"
"time": "2021-03-07T20:51:26+00:00"
},
{
"name": "pocketmine/raklib",
"version": "0.12.10",
"version": "0.12.11",
"source": {
"type": "git",
"url": "https://github.com/pmmp/RakLib.git",
"reference": "48e70551cca6f2409115d3468bed94c2edd08f31"
"reference": "9cce458b8bfde3e4dfdbf70c659fc7b7fe26b5c4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/48e70551cca6f2409115d3468bed94c2edd08f31",
"reference": "48e70551cca6f2409115d3468bed94c2edd08f31",
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/9cce458b8bfde3e4dfdbf70c659fc7b7fe26b5c4",
"reference": "9cce458b8bfde3e4dfdbf70c659fc7b7fe26b5c4",
"shasum": ""
},
"require": {
@ -382,7 +382,7 @@
"pocketmine/snooze": "^0.1.0"
},
"require-dev": {
"phpstan/phpstan": "0.12.67",
"phpstan/phpstan": "0.12.76",
"phpstan/phpstan-strict-rules": "^0.12.2"
},
"type": "library",
@ -398,22 +398,22 @@
"description": "A RakNet server implementation written in PHP",
"support": {
"issues": "https://github.com/pmmp/RakLib/issues",
"source": "https://github.com/pmmp/RakLib/tree/0.12.10"
"source": "https://github.com/pmmp/RakLib/tree/0.12.11"
},
"time": "2021-01-15T16:19:15+00:00"
"time": "2021-02-15T11:21:05+00:00"
},
{
"name": "pocketmine/snooze",
"version": "0.1.4",
"version": "0.1.5",
"source": {
"type": "git",
"url": "https://github.com/pmmp/Snooze.git",
"reference": "382ab149f01ecca0a57f999ff5d7fc9e271c3268"
"reference": "70b5e7937a06878dd321a3182ceb76d56298f2cd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/Snooze/zipball/382ab149f01ecca0a57f999ff5d7fc9e271c3268",
"reference": "382ab149f01ecca0a57f999ff5d7fc9e271c3268",
"url": "https://api.github.com/repos/pmmp/Snooze/zipball/70b5e7937a06878dd321a3182ceb76d56298f2cd",
"reference": "70b5e7937a06878dd321a3182ceb76d56298f2cd",
"shasum": ""
},
"require": {
@ -422,7 +422,7 @@
},
"require-dev": {
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "0.12.67",
"phpstan/phpstan": "0.12.76",
"phpstan/phpstan-strict-rules": "^0.12.4"
},
"type": "library",
@ -438,9 +438,9 @@
"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.4"
"source": "https://github.com/pmmp/Snooze/tree/0.1.5"
},
"time": "2021-01-15T14:44:16+00:00"
"time": "2021-02-22T16:16:12+00:00"
},
{
"name": "pocketmine/spl",
@ -726,16 +726,16 @@
},
{
"name": "phar-io/version",
"version": "3.0.4",
"version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/phar-io/version.git",
"reference": "e4782611070e50613683d2b9a57730e9a3ba5451"
"reference": "bae7c545bef187884426f042434e561ab1ddb182"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phar-io/version/zipball/e4782611070e50613683d2b9a57730e9a3ba5451",
"reference": "e4782611070e50613683d2b9a57730e9a3ba5451",
"url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182",
"reference": "bae7c545bef187884426f042434e561ab1ddb182",
"shasum": ""
},
"require": {
@ -771,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/3.0.4"
"source": "https://github.com/phar-io/version/tree/3.1.0"
},
"time": "2020-12-13T23:18:30+00:00"
"time": "2021-02-23T14:00:09+00:00"
},
{
"name": "phpdocumentor/reflection-common",
@ -1002,16 +1002,16 @@
},
{
"name": "phpstan/phpstan",
"version": "0.12.71",
"version": "0.12.80",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "d508fa3b0ecc5fc91ac70c6c7ac2862f968ba2b5"
"reference": "c6a1b17f22ecf708d434d6bee05092647ec7e686"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/d508fa3b0ecc5fc91ac70c6c7ac2862f968ba2b5",
"reference": "d508fa3b0ecc5fc91ac70c6c7ac2862f968ba2b5",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/c6a1b17f22ecf708d434d6bee05092647ec7e686",
"reference": "c6a1b17f22ecf708d434d6bee05092647ec7e686",
"shasum": ""
},
"require": {
@ -1042,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.71"
"source": "https://github.com/phpstan/phpstan/tree/0.12.80"
},
"funding": [
{
@ -1058,20 +1058,20 @@
"type": "tidelift"
}
],
"time": "2021-02-01T18:24:00+00:00"
"time": "2021-02-28T20:22:43+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
"version": "0.12.17",
"version": "0.12.18",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-phpunit.git",
"reference": "432575b41cf2d4f44e460234acaf56119ed97d36"
"reference": "ab44aec7cfb5cb267b8bc30a8caea86dd50d1f72"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/432575b41cf2d4f44e460234acaf56119ed97d36",
"reference": "432575b41cf2d4f44e460234acaf56119ed97d36",
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/ab44aec7cfb5cb267b8bc30a8caea86dd50d1f72",
"reference": "ab44aec7cfb5cb267b8bc30a8caea86dd50d1f72",
"shasum": ""
},
"require": {
@ -1111,9 +1111,9 @@
"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.17"
"source": "https://github.com/phpstan/phpstan-phpunit/tree/0.12.18"
},
"time": "2020-12-13T12:12:51+00:00"
"time": "2021-03-06T11:51:27+00:00"
},
{
"name": "phpstan/phpstan-strict-rules",
@ -1486,16 +1486,16 @@
},
{
"name": "phpunit/phpunit",
"version": "9.5.1",
"version": "9.5.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "e7bdf4085de85a825f4424eae52c99a1cec2f360"
"reference": "f661659747f2f87f9e72095bb207bceb0f151cb4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e7bdf4085de85a825f4424eae52c99a1cec2f360",
"reference": "e7bdf4085de85a825f4424eae52c99a1cec2f360",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f661659747f2f87f9e72095bb207bceb0f151cb4",
"reference": "f661659747f2f87f9e72095bb207bceb0f151cb4",
"shasum": ""
},
"require": {
@ -1573,7 +1573,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.1"
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.2"
},
"funding": [
{
@ -1585,7 +1585,7 @@
"type": "github"
}
],
"time": "2021-01-17T07:42:25+00:00"
"time": "2021-02-02T14:45:58+00:00"
},
{
"name": "sebastian/cli-parser",
@ -2553,7 +2553,7 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.22.0",
"version": "v1.22.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
@ -2612,7 +2612,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1"
},
"funding": [
{
@ -2740,10 +2740,10 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=7.3.0",
"php": "^7.3 || ^8.0",
"php-64bit": "*",
"ext-curl": "*",
"ext-ctype": "*",
"ext-curl": "*",
"ext-date": "*",
"ext-hash": "*",
"ext-json": "*",

View File

@ -206,9 +206,16 @@ class CrashDump{
if($this->server->getProperty("auto-report.send-settings", true) !== false){
$this->data["parameters"] = (array) $argv;
$this->data["server.properties"] = @file_get_contents($this->server->getDataPath() . "server.properties");
$this->data["server.properties"] = preg_replace("#^rcon\\.password=(.*)$#m", "rcon.password=******", $this->data["server.properties"]);
$this->data["pocketmine.yml"] = @file_get_contents($this->server->getDataPath() . "pocketmine.yml");
if(($serverDotProperties = @file_get_contents($this->server->getDataPath() . "server.properties")) !== false){
$this->data["server.properties"] = preg_replace("#^rcon\\.password=(.*)$#m", "rcon.password=******", $serverDotProperties);
}else{
$this->data["server.properties"] = $serverDotProperties;
}
if(($pocketmineDotYml = @file_get_contents($this->server->getDataPath() . "pocketmine.yml")) !== false){
$this->data["pocketmine.yml"] = $pocketmineDotYml;
}else{
$this->data["pocketmine.yml"] = "";
}
}else{
$this->data["pocketmine.yml"] = "";
$this->data["server.properties"] = "";

View File

@ -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\nbt\tag\StringTag;
use pocketmine\network\mcpe\convert\ItemTypeDictionary;
use pocketmine\network\mcpe\PlayerNetworkSessionAdapter;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
@ -1652,13 +1653,6 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$deltaAngle = abs($this->lastYaw - $to->yaw) + abs($this->lastPitch - $to->pitch);
if($delta > 0.0001 or $deltaAngle > 1.0){
$this->lastX = $to->x;
$this->lastY = $to->y;
$this->lastZ = $to->z;
$this->lastYaw = $to->yaw;
$this->lastPitch = $to->pitch;
$ev = new PlayerMoveEvent($this, $from, $to);
$ev->call();
@ -1673,6 +1667,12 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
return;
}
$this->lastX = $to->x;
$this->lastY = $to->y;
$this->lastZ = $to->z;
$this->lastYaw = $to->yaw;
$this->lastPitch = $to->pitch;
$this->broadcastMovement();
$distance = sqrt((($from->x - $to->x) ** 2) + (($from->z - $to->z) ** 2));
@ -1695,13 +1695,6 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}
protected function revertMovement(Location $from) : void{
$this->lastX = $from->x;
$this->lastY = $from->y;
$this->lastZ = $from->z;
$this->lastYaw = $from->yaw;
$this->lastPitch = $from->pitch;
$this->setPosition($from);
$this->sendPosition($from, $from->yaw, $from->pitch, MovePlayerPacket::MODE_RESET);
}
@ -2080,17 +2073,42 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
* @return void
*/
protected function processLogin(){
$checkXUID = (bool) $this->server->getProperty("player.verify-xuid", true);
$kickForXUIDMismatch = function(string $xuid) use ($checkXUID) : bool{
if($checkXUID && $this->xuid !== $xuid){
if($this->kick("XUID does not match (possible impersonation attempt)", false)){
//TODO: Longer term, we should be identifying playerdata using something more reliable, like XUID or UUID.
//However, that would be a very disruptive change, so this will serve as a stopgap for now.
//Side note: this will also prevent offline players hijacking XBL playerdata on online servers, since their
//XUID will always be empty.
return true;
}
$this->server->getLogger()->debug("XUID mismatch for " . $this->getName() . ", but plugin cancelled event allowing them to join anyway");
}
return false;
};
foreach($this->server->getLoggedInPlayers() as $p){
if($p !== $this and ($p->iusername === $this->iusername or $this->getUniqueId()->equals($p->getUniqueId()))){
if($kickForXUIDMismatch($p->getXuid())){
return;
}
if(!$p->kick("logged in from another location")){
$this->close($this->getLeaveMessage(), "Logged in from another location");
return;
}
}
}
$this->namedtag = $this->server->getOfflinePlayerData($this->username);
if($checkXUID){
$recordedXUID = $this->namedtag->getTag("LastKnownXUID");
if(!($recordedXUID instanceof StringTag)){
$this->server->getLogger()->debug("No previous XUID recorded for " . $this->getName() . ", no choice but to trust this player");
}elseif(!$kickForXUIDMismatch($recordedXUID->getValue())){
$this->server->getLogger()->debug("XUID match for " . $this->getName());
}
}
$this->playedBefore = ($this->getLastPlayed() - $this->getFirstPlayed()) > 1; // microtime(true) - microtime(true) may have less than one millisecond difference
$this->namedtag->setString("NameTag", $this->username);
@ -3756,6 +3774,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
parent::saveNBT();
$this->namedtag->setString("LastKnownXUID", $this->xuid);
if($this->isValid()){
$this->namedtag->setString("Level", $this->level->getFolderName());
}

View File

@ -228,7 +228,12 @@ namespace pocketmine {
mkdir(\pocketmine\DATA, 0777, true);
}
define('pocketmine\LOCK_FILE', fopen(\pocketmine\DATA . 'server.lock', "a+b"));
$lockFile = fopen(\pocketmine\DATA . 'server.lock', "a+b");
if($lockFile === false){
critical_error("Unable to open server.lock file. Please check that the current user has read/write permissions to it.");
exit(1);
}
define('pocketmine\LOCK_FILE', $lockFile);
if(!flock(\pocketmine\LOCK_FILE, LOCK_EX | LOCK_NB)){
//wait for a shared lock to avoid race conditions if two servers started at the same time - this makes sure the
//other server wrote its PID and released exclusive lock before we get our lock

View File

@ -1461,8 +1461,7 @@ class Server{
$this->onlineMode = $this->getConfigBool("xbox-auth", true);
if($this->onlineMode){
$this->logger->notice($this->getLanguage()->translateString("pocketmine.server.auth.enabled"));
$this->logger->notice($this->getLanguage()->translateString("pocketmine.server.authProperty.enabled"));
$this->logger->info($this->getLanguage()->translateString("pocketmine.server.auth.enabled"));
}else{
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.auth.disabled"));
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.authWarning"));

View File

@ -33,6 +33,6 @@ if(defined('pocketmine\_VERSION_INFO_INCLUDED')){
const _VERSION_INFO_INCLUDED = true;
const NAME = "PocketMine-MP";
const BASE_VERSION = "3.17.4";
const BASE_VERSION = "3.17.6";
const IS_DEVELOPMENT_BUILD = false;
const BUILD_NUMBER = 0;

View File

@ -418,6 +418,9 @@ abstract class Liquid extends Transparent{
return $isOptimalFlowDirection;
}
/**
* @phpstan-impure This function modifies the adjacent sources count (premature optimisation)
*/
private function getSmallestFlowDecay(Block $block, int $decay) : int{
$blockDecay = $this->getFlowDecay($block);

View File

@ -53,4 +53,13 @@ class PlayerCursorInventory extends BaseInventory{
public function getHolder(){
return $this->holder;
}
public function sendContents($target) : void{
//TODO: HACK!
//Since 1.13, this is now part of a larger "UI inventory", and sending contents for this larger inventory does
//not work the way it's intended to. Even if it did, it would be necessary to send all 51 slots just to update
//this one, which is just not worth it.
//This workaround isn't great, but it's at least simple.
$this->sendSlot(0, $target);
}
}

View File

@ -183,8 +183,6 @@ class LevelDB extends BaseLevelProvider{
if(!$this->levelData->hasTag("generatorOptions", StringTag::class)){
$this->levelData->setString("generatorOptions", "");
}
$db->close();
}
public static function getProviderName() : string{
@ -269,9 +267,6 @@ class LevelDB extends BaseLevelProvider{
$db->put(self::ENTRY_FLAT_WORLD_LAYERS, $out); //Add vanilla flatworld layers to allow terrain generation by MCPE to continue seamlessly
}
}
$db->close();
}
public function saveLevelData(){
@ -555,6 +550,6 @@ class LevelDB extends BaseLevelProvider{
}
public function close(){
$this->db->close();
unset($this->db);
}
}

View File

@ -84,7 +84,6 @@ class CraftingDataPacket extends DataPacket{
case self::ENTRY_SHAPELESS_CHEMISTRY:
$entry["recipe_id"] = $this->getString();
$ingredientCount = $this->getUnsignedVarInt();
/** @var Item */
$entry["input"] = [];
for($j = 0; $j < $ingredientCount; ++$j){
$entry["input"][] = $in = $this->getRecipeIngredient();

View File

@ -44,6 +44,7 @@ class ResourcePackClientResponsePacket extends DataPacket{
protected function decodePayload(){
$this->status = $this->getByte();
$entryCount = $this->getLShort();
$this->packIds = [];
while($entryCount-- > 0){
$this->packIds[] = $this->getString();
}

View File

@ -0,0 +1,59 @@
<?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\inventory\stackrequest;
use pocketmine\network\mcpe\NetworkBinaryStream;
/**
* Renames an item in an anvil, or map on a cartography table.
*/
final class CraftRecipeOptionalStackRequestAction extends ItemStackRequestAction{
/** @var int */
private $recipeId;
/** @var int */
private $filterStringIndex;
public function __construct(int $type, int $filterStringIndex){
$this->recipeId = $type;
$this->filterStringIndex = $filterStringIndex;
}
public function getRecipeId() : int{ return $this->recipeId; }
public function getFilterStringIndex() : int{ return $this->filterStringIndex; }
public static function getTypeId() : int{ return ItemStackRequestActionType::CRAFTING_RECIPE_OPTIONAL; }
public static function read(NetworkBinaryStream $in) : self{
$recipeId = $in->readGenericTypeNetworkId();
$filterStringIndex = $in->getLInt();
return new self($recipeId, $filterStringIndex);
}
public function write(NetworkBinaryStream $out) : void{
$out->writeGenericTypeNetworkId($this->recipeId);
$out->putLInt($this->filterStringIndex);
}
}

View File

@ -32,13 +32,21 @@ final class ItemStackRequest{
private $requestId;
/** @var ItemStackRequestAction[] */
private $actions;
/**
* @var string[]
* @phpstan-var list<string>
*/
private $filterStrings;
/**
* @param ItemStackRequestAction[] $actions
* @param string[] $filterStrings
* @phpstan-param list<string> $filterStrings
*/
public function __construct(int $requestId, array $actions){
public function __construct(int $requestId, array $actions, array $filterStrings){
$this->requestId = $requestId;
$this->actions = $actions;
$this->filterStrings = $filterStrings;
}
public function getRequestId() : int{ return $this->requestId; }
@ -46,6 +54,12 @@ final class ItemStackRequest{
/** @return ItemStackRequestAction[] */
public function getActions() : array{ return $this->actions; }
/**
* @return string[]
* @phpstan-return list<string>
*/
public function getFilterStrings() : array{ return $this->filterStrings; }
private static function readAction(NetworkBinaryStream $in, int $typeId) : ItemStackRequestAction{
switch($typeId){
case TakeStackRequestAction::getTypeId(): return TakeStackRequestAction::read($in);
@ -60,6 +74,7 @@ final class ItemStackRequest{
case CraftRecipeStackRequestAction::getTypeId(): return CraftRecipeStackRequestAction::read($in);
case CraftRecipeAutoStackRequestAction::getTypeId(): return CraftRecipeAutoStackRequestAction::read($in);
case CreativeCreateStackRequestAction::getTypeId(): return CreativeCreateStackRequestAction::read($in);
case CraftRecipeOptionalStackRequestAction::getTypeId(): return CraftRecipeOptionalStackRequestAction::read($in);
case DeprecatedCraftingNonImplementedStackRequestAction::getTypeId(): return DeprecatedCraftingNonImplementedStackRequestAction::read($in);
case DeprecatedCraftingResultsStackRequestAction::getTypeId(): return DeprecatedCraftingResultsStackRequestAction::read($in);
}
@ -73,7 +88,11 @@ final class ItemStackRequest{
$typeId = $in->getByte();
$actions[] = self::readAction($in, $typeId);
}
return new self($requestId, $actions);
$filterStrings = [];
for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){
$filterStrings[] = $in->getString();
}
return new self($requestId, $actions, $filterStrings);
}
public function write(NetworkBinaryStream $out) : void{
@ -83,5 +102,9 @@ final class ItemStackRequest{
$out->putByte($action::getTypeId());
$action->write($out);
}
$out->putUnsignedVarInt(count($this->filterStrings));
foreach($this->filterStrings as $string){
$out->putString($string);
}
}
}

View File

@ -41,6 +41,7 @@ final class ItemStackRequestActionType{
public const CRAFTING_RECIPE = 9;
public const CRAFTING_RECIPE_AUTO = 10; //recipe book?
public const CREATIVE_CREATE = 11;
public const CRAFTING_NON_IMPLEMENTED_DEPRECATED_ASK_TY_LAING = 12; //anvils aren't fully implemented yet
public const CRAFTING_RESULTS_DEPRECATED_ASK_TY_LAING = 13; //no idea what this is for
public const CRAFTING_RECIPE_OPTIONAL = 12; //anvil/cartography table rename
public const CRAFTING_NON_IMPLEMENTED_DEPRECATED_ASK_TY_LAING = 13;
public const CRAFTING_RESULTS_DEPRECATED_ASK_TY_LAING = 14; //no idea what this is for
}

View File

@ -100,6 +100,9 @@ debug:
player:
#Choose whether to enable player data saving.
save-player-data: true
#If true, checks that joining players' Xbox user ID (XUID) match what was previously recorded.
#This also prevents non-XBL players using XBL players' usernames to steal their data on servers with xbox-auth=off.
verify-xuid: true
anti-cheat:
#If false, will try to prevent speed and noclip cheats. May cause movement issues.
allow-movement-cheats: true

View File

@ -278,8 +278,10 @@ class MainLogger extends \AttachableThreadedLogger{
* @return void
*/
public function shutdown(){
$this->shutdown = true;
$this->notify();
$this->synchronized(function() : void{
$this->shutdown = true;
$this->notify();
});
}
/**
@ -321,6 +323,7 @@ class MainLogger extends \AttachableThreadedLogger{
}
$this->logStream[] = $time->format("Y-m-d") . " " . TextFormat::clean($message) . PHP_EOL;
$this->notify();
});
}
@ -343,14 +346,17 @@ class MainLogger extends \AttachableThreadedLogger{
*/
private function writeLogStream($logResource) : void{
while($this->logStream->count() > 0){
/** @var string $chunk */
$chunk = $this->logStream->shift();
fwrite($logResource, $chunk);
}
if($this->syncFlush){
$this->syncFlush = false;
$this->notify(); //if this was due to a sync flush, tell the caller to stop waiting
}
$this->synchronized(function() : void{
if($this->syncFlush){
$this->syncFlush = false;
$this->notify(); //if this was due to a sync flush, tell the caller to stop waiting
}
});
}
/**
@ -365,7 +371,9 @@ class MainLogger extends \AttachableThreadedLogger{
while(!$this->shutdown){
$this->writeLogStream($logResource);
$this->synchronized(function() : void{
$this->wait(25000);
if(!$this->shutdown){
$this->wait();
}
});
}

View File

@ -21,5 +21,6 @@ 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"
PHP_BUILD_INSTALL_EXTENSION='pthreads=@acc6e52b2144c61c434b62a3cb680d537e06828e yaml=2.2.1' PHP_BUILD_ZTS_ENABLE=on ./bin/php-build "$VERSION" "$INSTALL_DIR" || exit 1
rm "$INSTALL_DIR/etc/conf.d/xdebug.ini" || true
cp install-dependencies.sh "$INSTALL_DIR"

View File

@ -70,36 +70,6 @@ parameters:
count: 2
path: ../../../src/pocketmine/PocketMine.php
-
message: "#^Parameter \\#1 \\$fp of function flock expects resource, resource\\|false given\\.$#"
count: 4
path: ../../../src/pocketmine/PocketMine.php
-
message: "#^Parameter \\#1 \\$source of function stream_get_contents expects resource, resource\\|false given\\.$#"
count: 1
path: ../../../src/pocketmine/PocketMine.php
-
message: "#^Parameter \\#1 \\$fp of function ftruncate expects resource, resource\\|false given\\.$#"
count: 1
path: ../../../src/pocketmine/PocketMine.php
-
message: "#^Parameter \\#1 \\$fp of function fwrite expects resource, resource\\|false given\\.$#"
count: 1
path: ../../../src/pocketmine/PocketMine.php
-
message: "#^Parameter \\#1 \\$fp of function fflush expects resource, resource\\|false given\\.$#"
count: 1
path: ../../../src/pocketmine/PocketMine.php
-
message: "#^Parameter \\#1 \\$fp of function fclose expects resource, resource\\|false given\\.$#"
count: 1
path: ../../../src/pocketmine/PocketMine.php
-
message: "#^Parameter \\#1 \\$buffer of method pocketmine\\\\nbt\\\\NBTStream\\:\\:readCompressed\\(\\) expects string, string\\|false given\\.$#"
count: 1

View File

@ -1,15 +1,5 @@
parameters:
ignoreErrors:
-
message: "#^Comparison operation \"\\>\\=\" between 0 and 2 is always false\\.$#"
count: 1
path: ../../../src/pocketmine/block/Liquid.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: ../../../src/pocketmine/block/Liquid.php
-
message: "#^Call to function is_resource\\(\\) with resource will always evaluate to true\\.$#"
count: 3

View File

@ -0,0 +1,37 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\network\mcpe\protocol;
use PHPUnit\Framework\TestCase;
final class ProtocolInfoTest extends TestCase{
public function testMinecraftVersionNetwork() : void{
self::assertMatchesRegularExpression(
'/^(?:\d+\.)?(?:\d+\.)?(?:\d+\.)?\d+$/',
ProtocolInfo::MINECRAFT_VERSION_NETWORK,
"Network version should only contain 0-9 and \".\", and no more than 4 groups of digits"
);
}
}