mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-09 03:06:55 +00:00
Compare commits
56 Commits
5.0.0-BETA
...
4.23.2
Author | SHA1 | Date | |
---|---|---|---|
20b7e8d702 | |||
c6110be051 | |||
86bd6777a3 | |||
935df62006 | |||
2709dd359c | |||
4e646d19a4 | |||
2a11762e61 | |||
7e0b5cf73d | |||
e903da8998 | |||
f2193d1ba7 | |||
f7977c9668 | |||
cfd9950b02 | |||
8ebcdb452d | |||
aacc00a911 | |||
0c250a2ef0 | |||
70dd9c7371 | |||
f8e6f036af | |||
bbabccfc89 | |||
1698eac6dc | |||
321972b87b | |||
c86c9b3ead | |||
249ef9c534 | |||
f4dab17a1b | |||
e85605af7f | |||
dfd70615ad | |||
ee903cad1f | |||
9a04481bec | |||
5d514a274f | |||
2220dc557e | |||
b5fc31a781 | |||
179eec9754 | |||
441f1f534f | |||
e747478afd | |||
92c45dd7e1 | |||
2538880408 | |||
c715efb18e | |||
6678360c00 | |||
3db45b6a68 | |||
3e87ad281f | |||
b72da777eb | |||
1101f35c17 | |||
3948dc4f75 | |||
20942b37eb | |||
d343db8750 | |||
f2df702c67 | |||
481270e6aa | |||
e7bdaa8579 | |||
76749cbaa7 | |||
a897bdfaa0 | |||
09668a37d6 | |||
ea92a23d0d | |||
691e67018d | |||
fe2140a716 | |||
57330a7186 | |||
9ddac21de0 | |||
c91aa24daa |
2
.github/workflows/discord-release-notify.yml
vendored
2
.github/workflows/discord-release-notify.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PHP and tools
|
||||
uses: shivammathur/setup-php@2.24.0
|
||||
uses: shivammathur/setup-php@2.25.2
|
||||
with:
|
||||
php-version: 8.1
|
||||
|
||||
|
4
.github/workflows/draft-release.yml
vendored
4
.github/workflows/draft-release.yml
vendored
@ -18,7 +18,7 @@ jobs:
|
||||
submodules: true
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@2.24.0
|
||||
uses: shivammathur/setup-php@2.25.2
|
||||
with:
|
||||
php-version: 8.1
|
||||
|
||||
@ -84,3 +84,5 @@ jobs:
|
||||
**For Minecraft: Bedrock Edition ${{ steps.get-pm-version.outputs.MCPE_VERSION }}**
|
||||
|
||||
Please see the [changelogs](${{ github.server_url }}/${{ github.repository }}/blob/${{ steps.get-pm-version.outputs.PM_VERSION }}/changelogs/${{ steps.get-pm-version.outputs.PM_VERSION_SHORT }}${{ steps.get-pm-version.outputs.CHANGELOG_SUFFIX }}.md#${{ steps.get-pm-version.outputs.PM_VERSION_MD }}) for details.
|
||||
|
||||
:warning: **4.x is now deprecated. Please read https://github.com/pmmp/PocketMine-MP/issues/5784 for details, and prepare to upgrade to 5.x.**
|
||||
|
61
.github/workflows/main.yml
vendored
61
.github/workflows/main.yml
vendored
@ -6,47 +6,26 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-php:
|
||||
name: Prepare PHP
|
||||
runs-on: ${{ matrix.image }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.1.19, 8.2.6]
|
||||
|
||||
steps:
|
||||
- name: Build and prepare PHP cache
|
||||
uses: pmmp/setup-php-action@c7fb29d83535320922068087c7285bdedbbfa3c2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "4"
|
||||
|
||||
phpstan:
|
||||
name: PHPStan analysis
|
||||
needs: build-php
|
||||
runs-on: ${{ matrix.image }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.1.19, 8.2.6]
|
||||
php: ["8.1", "8.2"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@c7fb29d83535320922068087c7285bdedbbfa3c2
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "4"
|
||||
|
||||
- name: Install Composer
|
||||
run: curl -sS https://getcomposer.org/installer | php
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
@ -58,34 +37,30 @@ jobs:
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: php composer.phar install --prefer-dist --no-interaction
|
||||
run: composer 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: ${{ matrix.image }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.1.19, 8.2.6]
|
||||
php: ["8.1", "8.2"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@c7fb29d83535320922068087c7285bdedbbfa3c2
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "4"
|
||||
|
||||
- name: Install Composer
|
||||
run: curl -sS https://getcomposer.org/installer | php
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
@ -97,20 +72,19 @@ jobs:
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: php composer.phar install --prefer-dist --no-interaction
|
||||
run: composer 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: ${{ matrix.image }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.1.19, 8.2.6]
|
||||
php: ["8.1", "8.2"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@ -118,15 +92,12 @@ jobs:
|
||||
submodules: true
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@c7fb29d83535320922068087c7285bdedbbfa3c2
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "4"
|
||||
|
||||
- name: Install Composer
|
||||
run: curl -sS https://getcomposer.org/installer | php
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
@ -138,34 +109,30 @@ jobs:
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: php composer.phar install --no-dev --prefer-dist --no-interaction
|
||||
run: composer install --no-dev --prefer-dist --no-interaction
|
||||
|
||||
- name: Run integration tests
|
||||
run: ./tests/travis.sh -t4
|
||||
|
||||
codegen:
|
||||
name: Generated Code consistency checks
|
||||
needs: build-php
|
||||
runs-on: ${{ matrix.image }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.1.19, 8.2.6]
|
||||
php: ["8.1", "8.2"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@c7fb29d83535320922068087c7285bdedbbfa3c2
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "4"
|
||||
|
||||
- name: Install Composer
|
||||
run: curl -sS https://getcomposer.org/installer | php
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
@ -177,7 +144,7 @@ jobs:
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: php composer.phar install --no-dev --prefer-dist --no-interaction
|
||||
run: composer install --no-dev --prefer-dist --no-interaction
|
||||
|
||||
- name: Regenerate registry annotations
|
||||
run: php build/generate-registry-annotations.php src
|
||||
@ -203,10 +170,10 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PHP and tools
|
||||
uses: shivammathur/setup-php@2.24.0
|
||||
uses: shivammathur/setup-php@2.25.2
|
||||
with:
|
||||
php-version: 8.1
|
||||
tools: php-cs-fixer:3.16
|
||||
tools: php-cs-fixer:3.17
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
50
.github/workflows/update-php-versions.php
vendored
50
.github/workflows/update-php-versions.php
vendored
@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const VERSIONS = [
|
||||
"8.1",
|
||||
"8.2"
|
||||
];
|
||||
|
||||
$workflowFile = file_get_contents(__DIR__ . '/main.yml');
|
||||
$newWorkflowFile = $workflowFile;
|
||||
foreach(VERSIONS as $v){
|
||||
$releaseInfo = file_get_contents("https://secure.php.net/releases?json&version=$v");
|
||||
if($releaseInfo === false){
|
||||
throw new \RuntimeException("Failed to contact php.net API");
|
||||
}
|
||||
$data = json_decode($releaseInfo, true);
|
||||
if(!is_array($data) || !isset($data["version"]) || !is_string($data["version"]) || preg_match('/^\d+\.\d+\.\d+(-[A-Za-z\d]+)?$/', $data["version"]) === 0){
|
||||
throw new \RuntimeException("Invalid data returned by API");
|
||||
}
|
||||
$updated = preg_replace("/$v\.\d+/", $data["version"], $newWorkflowFile);
|
||||
if($updated !== $newWorkflowFile){
|
||||
echo "Updated $v revision to " . $data["version"] . "\n";
|
||||
}
|
||||
$newWorkflowFile = $updated;
|
||||
}
|
||||
|
||||
if($workflowFile !== $newWorkflowFile){
|
||||
echo "Writing modified workflow file\n";
|
||||
file_put_contents(__DIR__ . '/main.yml', $newWorkflowFile);
|
||||
}
|
1
.github/workflows/update-updater-api.yml
vendored
1
.github/workflows/update-updater-api.yml
vendored
@ -8,6 +8,7 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
concurrency: update-updater-api # only one job can run at a time, to avoid git conflicts when updating the repository
|
||||
|
||||
steps:
|
||||
- name: Install jq
|
||||
|
7
.idea/codeStyles/Project.xml
generated
7
.idea/codeStyles/Project.xml
generated
@ -30,6 +30,13 @@
|
||||
<option name="USE_TAB_CHARACTER" value="true" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="Markdown">
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="PHP">
|
||||
<option name="CLASS_BRACE_STYLE" value="1" />
|
||||
<option name="METHOD_BRACE_STYLE" value="1" />
|
||||
|
Submodule build/php updated: f860ade30a...16378ffcc3
@ -71,3 +71,9 @@ Released 6th May 2023.
|
||||
## Fixes
|
||||
- Fixed players being forced into flight mode in every game mode.
|
||||
- Moral of the story: do not assume anything in Mojang internals does what its name suggests...
|
||||
|
||||
# 4.20.5
|
||||
Released 30th May 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed server crash due to a bug in upstream dependency [`netresearch/jsonmapper`](https://github.com/cweiske/JsonMapper).
|
||||
|
@ -69,3 +69,9 @@ Released 17th May 2023.
|
||||
- Registered but ineligible ticking chunks are no longer rechecked every tick.
|
||||
- This was causing wasted cycles during async worker backlog.
|
||||
- The internal system must call `markTickingChunkForRecheck()` whenever a ticking chunk's eligibility for ticking has potentially changed, rather than just when it has changed from a yes to a no.
|
||||
|
||||
# 4.21.1
|
||||
Released 30th May 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed server crash due to a bug in upstream dependency [`netresearch/jsonmapper`](https://github.com/cweiske/JsonMapper).
|
||||
|
58
changelogs/4.22.md
Normal file
58
changelogs/4.22.md
Normal file
@ -0,0 +1,58 @@
|
||||
# 4.22.0
|
||||
Released 7th June 2023.
|
||||
|
||||
**For Minecraft: Bedrock Edition 1.20.0**
|
||||
|
||||
This is a support release for Minecraft: Bedrock Edition 1.20.0.
|
||||
|
||||
**Plugin compatibility:** Plugins for previous 4.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` namespace.
|
||||
Do not update plugin minimum API versions unless you need new features added in this release.
|
||||
|
||||
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
|
||||
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
|
||||
|
||||
## Interim releases
|
||||
If you're upgrading from 4.20.x directly to 4.22.x, please also read the following changelogs, as the interim releases contain important changes:
|
||||
- [4.21.0](https://github.com/pmmp/PocketMine-MP/blob/4.22.0/changelogs/4.21.md#4210) - PHP 8.1 minimum version, minor performance improvements
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.20.0.
|
||||
- Removed support for older versions.
|
||||
|
||||
## Fixes
|
||||
- Removed deprecated `ReflectionProperty::setAccessible()` calls.
|
||||
- Fixed jukebox music not stopping when destroyed by an explosion.
|
||||
|
||||
# 4.22.1
|
||||
Released 9th June 2023.
|
||||
|
||||
## Fixes
|
||||
- Replaced workaround for an old teleporting client bug:
|
||||
- This workaround broke due to an additional client bug introduced by 1.20, causing players to become frozen to observers when teleported.
|
||||
- The original client bug has still not been fixed, meaning a new workaround was needed, but no perfect solution could be found.
|
||||
- The new workaround involves broadcasting teleport movements as regular movements, which causes unwanted interpolation between the old and new positions, but otherwise works correctly. This solution is not ideal, but it is the best we can do for now.
|
||||
- See issues [#4394](https://github.com/pmmp/PocketMine-MP/issues/4394) and [#5810](https://github.com/pmmp/PocketMine-MP/issues/5810) for more details.
|
||||
|
||||
# 4.22.2
|
||||
Released 1st July 2023.
|
||||
|
||||
## Changes
|
||||
- Added obsoletion warnings to the server log at the end of the startup sequence.
|
||||
|
||||
## Fixes
|
||||
- Fixed players being disconnected en masse with "Not authenticated" messages.
|
||||
- This occurred due to a check intended to disable the old authentication key after July 1st.
|
||||
- We expected that the new key would have been deployed by Mojang by now, but it seems like that has not yet happened.
|
||||
- Due to the lack of a hard date for the key changeover, we guessed that July 1st would be a safe bet, but this appears to have backfired.
|
||||
- This version will accept both old and new keys indefinitely.
|
||||
- A security release will be published to remove the old key after the transition occurs.
|
||||
|
||||
# 4.22.3
|
||||
Released 11th July 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed mishandling of NBT leading to a server crash when editing signs.
|
||||
- Fixed an edge case crash that could occur in `AsyncTask->__destruct()` when thread-local storage referenced other `AsyncTask` objects.
|
||||
|
||||
## Internals
|
||||
- Added a concurrency lock to prevent the `update-updater-api` GitHub Action from running for multiple releases at the same time (which would have caused one of them to fail due to git conflicts).
|
32
changelogs/4.23.md
Normal file
32
changelogs/4.23.md
Normal file
@ -0,0 +1,32 @@
|
||||
# 4.23.0
|
||||
Released 12th July 2023.
|
||||
|
||||
**For Minecraft: Bedrock Edition 1.20.10**
|
||||
|
||||
This is a support release for Minecraft: Bedrock Edition 1.20.10.
|
||||
|
||||
**Plugin compatibility:** Plugins for previous 4.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` namespace.
|
||||
Do not update plugin minimum API versions unless you need new features added in this release.
|
||||
|
||||
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
|
||||
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.20.10.
|
||||
- Removed support for older versions.
|
||||
|
||||
## Fixes
|
||||
- Fixed Docker image build failure due to outdated `build/php` submodule.
|
||||
|
||||
# 4.23.1
|
||||
Released 14th July 2023.
|
||||
|
||||
## Fixes
|
||||
- Hardened validation of JWT signing keys in `LoginPacket`.
|
||||
- Fixed server crash due to a bug in upstream dependency [`netresearch/jsonmapper`](https://github.com/cweiske/JsonMapper).
|
||||
|
||||
# 4.23.2
|
||||
Released 18th July 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed login errors due to a new `sandboxId` field appearing in the Xbox Live authentication data in `LoginPacket`. All clients, regardless of version, are affected by this change.
|
@ -31,13 +31,13 @@
|
||||
"ext-zip": "*",
|
||||
"ext-zlib": ">=1.2.11",
|
||||
"composer-runtime-api": "^2.0",
|
||||
"adhocore/json-comment": "^1.1",
|
||||
"fgrosse/phpasn1": "^2.3",
|
||||
"netresearch/jsonmapper": "^4.0",
|
||||
"pocketmine/bedrock-block-upgrade-schema": "~2.1.0+bedrock-1.19.80",
|
||||
"pocketmine/bedrock-data": "~2.2.0+bedrock-1.19.80",
|
||||
"pocketmine/bedrock-item-upgrade-schema": "~1.2.0+bedrock-1.19.80",
|
||||
"pocketmine/bedrock-protocol": "~21.0.0+bedrock-1.19.80",
|
||||
"adhocore/json-comment": "~1.2.0",
|
||||
"fgrosse/phpasn1": "~2.5.0",
|
||||
"pocketmine/netresearch-jsonmapper": "~v4.2.1000",
|
||||
"pocketmine/bedrock-block-upgrade-schema": "~3.1.0+bedrock-1.20.10",
|
||||
"pocketmine/bedrock-data": "~2.4.0+bedrock-1.20.10",
|
||||
"pocketmine/bedrock-item-upgrade-schema": "~1.4.0+bedrock-1.20.10",
|
||||
"pocketmine/bedrock-protocol": "~23.0.0+bedrock-1.20.10",
|
||||
"pocketmine/binaryutils": "^0.2.1",
|
||||
"pocketmine/callback-validator": "^1.0.2",
|
||||
"pocketmine/classloader": "^0.2.0",
|
||||
@ -51,15 +51,15 @@
|
||||
"pocketmine/raklib": "^0.14.2",
|
||||
"pocketmine/raklib-ipc": "^0.1.0",
|
||||
"pocketmine/snooze": "^0.3.0",
|
||||
"ramsey/uuid": "^4.1",
|
||||
"symfony/filesystem": "^5.4",
|
||||
"webmozart/path-util": "^2.3"
|
||||
"ramsey/uuid": "~4.7.0",
|
||||
"symfony/filesystem": "~5.4.0",
|
||||
"webmozart/path-util": "~2.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.10.15",
|
||||
"phpstan/phpstan-phpunit": "^1.1.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.2.0",
|
||||
"phpunit/phpunit": "^9.2"
|
||||
"phpunit/phpunit": "^10.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
773
composer.lock
generated
773
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -316,9 +316,6 @@ class MemoryManager{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!$property->isPublic()){
|
||||
$property->setAccessible(true);
|
||||
}
|
||||
if(!$property->isInitialized()){
|
||||
continue;
|
||||
}
|
||||
@ -442,9 +439,6 @@ class MemoryManager{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(!$property->isPublic()){
|
||||
$property->setAccessible(true);
|
||||
}
|
||||
if(!$property->isInitialized($object)){
|
||||
continue;
|
||||
}
|
||||
|
@ -1054,6 +1054,11 @@ class Server{
|
||||
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_defaultGameMode($this->getGamemode()->getTranslatableName())));
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_donate(TextFormat::AQUA . "https://patreon.com/pocketminemp" . TextFormat::RESET)));
|
||||
|
||||
$this->logger->alert($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_obsolete_warning1("4.x", "5.0")));
|
||||
$this->logger->alert($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_obsolete_warning2("4.x", "2023-09-01")));
|
||||
$this->logger->alert($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_obsolete_warning3("https://github.com/pmmp/PocketMine-MP/issues/5784")));
|
||||
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_startFinished(strval(round(microtime(true) - $this->startTime, 3)))));
|
||||
|
||||
$forwarder = new BroadcastLoggerForwarder($this, $this->logger, $this->language);
|
||||
|
@ -31,8 +31,8 @@ use function str_repeat;
|
||||
|
||||
final class VersionInfo{
|
||||
public const NAME = "PocketMine-MP";
|
||||
public const BASE_VERSION = "4.21.1";
|
||||
public const IS_DEVELOPMENT_BUILD = true;
|
||||
public const BASE_VERSION = "4.23.2";
|
||||
public const IS_DEVELOPMENT_BUILD = false;
|
||||
public const BUILD_CHANNEL = "stable";
|
||||
|
||||
private function __construct(){
|
||||
|
@ -26,6 +26,7 @@ namespace pocketmine\block\tile;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Record;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\world\sound\RecordStopSound;
|
||||
|
||||
class Jukebox extends Spawnable{
|
||||
private const TAG_RECORD = "RecordItem"; //Item CompoundTag
|
||||
@ -61,4 +62,8 @@ class Jukebox extends Spawnable{
|
||||
$nbt->setTag(self::TAG_RECORD, $this->record->nbtSerialize());
|
||||
}
|
||||
}
|
||||
|
||||
protected function onBlockDestroyedHook() : void{
|
||||
$this->position->getWorld()->addSound($this->position, new RecordStopSound());
|
||||
}
|
||||
}
|
||||
|
@ -248,7 +248,6 @@ class CrashDump{
|
||||
if(file_exists($filePath)){
|
||||
$reflection = new \ReflectionClass(PluginBase::class);
|
||||
$file = $reflection->getProperty("file");
|
||||
$file->setAccessible(true);
|
||||
foreach($this->server->getPluginManager()->getPlugins() as $plugin){
|
||||
$filePath = Filesystem::cleanPath($file->getValue($plugin));
|
||||
if(str_starts_with($frameCleanPath, $filePath)){
|
||||
|
@ -781,29 +781,21 @@ abstract class Entity{
|
||||
}
|
||||
|
||||
protected function broadcastMovement(bool $teleport = false) : void{
|
||||
if($teleport){
|
||||
//TODO: HACK! workaround for https://github.com/pmmp/PocketMine-MP/issues/4394
|
||||
//this happens because MoveActor*Packet doesn't clear interpolation targets on the client, so the entity
|
||||
//snaps to the teleport position, but then lerps back to the original position if a normal movement for the
|
||||
//entity was recently broadcasted. This can be seen with players throwing ender pearls.
|
||||
//TODO: remove this if the bug ever gets fixed (lol)
|
||||
foreach($this->hasSpawned as $player){
|
||||
$this->despawnFrom($player);
|
||||
$this->spawnTo($player);
|
||||
}
|
||||
}else{
|
||||
NetworkBroadcastUtils::broadcastPackets($this->hasSpawned, [MoveActorAbsolutePacket::create(
|
||||
$this->id,
|
||||
$this->getOffsetPosition($this->location),
|
||||
$this->location->pitch,
|
||||
$this->location->yaw,
|
||||
$this->location->yaw,
|
||||
(
|
||||
//TODO: if the above hack for #4394 gets removed, we should be setting FLAG_TELEPORT here
|
||||
($this->onGround ? MoveActorAbsolutePacket::FLAG_GROUND : 0)
|
||||
)
|
||||
)]);
|
||||
}
|
||||
NetworkBroadcastUtils::broadcastPackets($this->hasSpawned, [MoveActorAbsolutePacket::create(
|
||||
$this->id,
|
||||
$this->getOffsetPosition($this->location),
|
||||
$this->location->pitch,
|
||||
$this->location->yaw,
|
||||
$this->location->yaw,
|
||||
(
|
||||
//TODO: We should be setting FLAG_TELEPORT here to disable client-side movement interpolation, but it
|
||||
//breaks player teleporting (observers see the player rubberband back to the pre-teleport position while
|
||||
//the teleported player sees themselves at the correct position), and does nothing whatsoever for
|
||||
//non-player entities (movement is still interpolated). Both of these are client bugs.
|
||||
//See https://github.com/pmmp/PocketMine-MP/issues/4394
|
||||
($this->onGround ? MoveActorAbsolutePacket::FLAG_GROUND : 0)
|
||||
)
|
||||
)]);
|
||||
}
|
||||
|
||||
protected function broadcastMotion() : void{
|
||||
|
@ -61,6 +61,7 @@ use const OPENSSL_ALGO_SHA384;
|
||||
use const STR_PAD_LEFT;
|
||||
|
||||
final class JwtUtils{
|
||||
public const BEDROCK_SIGNING_KEY_CURVE_NAME = "secp384r1";
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
@ -203,6 +204,17 @@ final class JwtUtils{
|
||||
if($signingKeyOpenSSL === false){
|
||||
throw new JwtException("OpenSSL failed to parse key: " . openssl_error_string());
|
||||
}
|
||||
$details = openssl_pkey_get_details($signingKeyOpenSSL);
|
||||
if($details === false){
|
||||
throw new JwtException("OpenSSL failed to get details from key: " . openssl_error_string());
|
||||
}
|
||||
if(!isset($details['ec']['curve_name'])){
|
||||
throw new JwtException("Expected an EC key");
|
||||
}
|
||||
$curve = $details['ec']['curve_name'];
|
||||
if($curve !== self::BEDROCK_SIGNING_KEY_CURVE_NAME){
|
||||
throw new JwtException("Key must belong to curve " . self::BEDROCK_SIGNING_KEY_CURVE_NAME . ", got $curve");
|
||||
}
|
||||
return $signingKeyOpenSSL;
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +84,7 @@ use pocketmine\network\mcpe\protocol\types\AbilitiesLayer;
|
||||
use pocketmine\network\mcpe\protocol\types\BlockPosition;
|
||||
use pocketmine\network\mcpe\protocol\types\command\CommandData;
|
||||
use pocketmine\network\mcpe\protocol\types\command\CommandEnum;
|
||||
use pocketmine\network\mcpe\protocol\types\command\CommandOverload;
|
||||
use pocketmine\network\mcpe\protocol\types\command\CommandParameter;
|
||||
use pocketmine\network\mcpe\protocol\types\command\CommandPermissions;
|
||||
use pocketmine\network\mcpe\protocol\types\DimensionIds;
|
||||
@ -949,8 +950,9 @@ class NetworkSession{
|
||||
0,
|
||||
$aliasObj,
|
||||
[
|
||||
[CommandParameter::standard("args", AvailableCommandsPacket::ARG_TYPE_RAWTEXT, 0, true)]
|
||||
]
|
||||
new CommandOverload(chaining: false, parameters: [CommandParameter::standard("args", AvailableCommandsPacket::ARG_TYPE_RAWTEXT, 0, true)])
|
||||
],
|
||||
chainedSubCommandData: []
|
||||
);
|
||||
|
||||
$commandData[$command->getLabel()] = $data;
|
||||
|
@ -138,6 +138,6 @@ final class StandardEntityEventBroadcaster implements EntityEventBroadcaster{
|
||||
}
|
||||
|
||||
public function onEmote(array $recipients, Human $from, string $emoteId) : void{
|
||||
$this->sendDataPacket($recipients, EmotePacket::create($from->getId(), $emoteId, EmotePacket::FLAG_SERVER));
|
||||
$this->sendDataPacket($recipients, EmotePacket::create($from->getId(), $emoteId, "", "", EmotePacket::FLAG_SERVER));
|
||||
}
|
||||
}
|
||||
|
@ -32,13 +32,27 @@ use pocketmine\scheduler\AsyncTask;
|
||||
use function base64_decode;
|
||||
use function igbinary_serialize;
|
||||
use function igbinary_unserialize;
|
||||
use function openssl_error_string;
|
||||
use function time;
|
||||
|
||||
class ProcessLoginTask extends AsyncTask{
|
||||
private const TLS_KEY_ON_COMPLETION = "completion";
|
||||
|
||||
public const MOJANG_ROOT_PUBLIC_KEY = "MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8ELkixyLcwlZryUQcu1TvPOmI2B7vX83ndnWRUaXm74wFfa5f/lwQNTfrLVHa2PmenpGI6JhIMUJaWZrjmMj90NoKNFSNBuKdm8rYiXsfaz3K36x/1U26HpG0ZxK/V1V";
|
||||
/**
|
||||
* Old Mojang root auth key. This was used since the introduction of Xbox Live authentication in 0.15.0.
|
||||
* This key is expected to be replaced by the key below in the future, but this has not yet happened as of
|
||||
* 2023-07-01.
|
||||
* Ideally we would place a time expiry on this key, but since Mojang have not given a hard date for the key change,
|
||||
* and one bad guess has already caused a major outage, we can't do this.
|
||||
* TODO: This needs to be removed as soon as the new key is deployed by Mojang's authentication servers.
|
||||
*/
|
||||
public const MOJANG_OLD_ROOT_PUBLIC_KEY = "MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8ELkixyLcwlZryUQcu1TvPOmI2B7vX83ndnWRUaXm74wFfa5f/lwQNTfrLVHa2PmenpGI6JhIMUJaWZrjmMj90NoKNFSNBuKdm8rYiXsfaz3K36x/1U26HpG0ZxK/V1V";
|
||||
|
||||
/**
|
||||
* New Mojang root auth key. Mojang notified third-party developers of this change prior to the release of 1.20.0.
|
||||
* Expectations were that this would be used starting a "couple of weeks" after the release, but as of 2023-07-01,
|
||||
* it has not yet been deployed.
|
||||
*/
|
||||
public const MOJANG_ROOT_PUBLIC_KEY = "MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAECRXueJeTDqNRRgJi/vlRufByu/2G0i2Ebt6YMar5QX/R0DIIyrJMcUpruK4QveTfJSTp3Shlq4Gk34cD/4GUWwkv0DVuzeuB+tXija7HBxii03NHDbPAD0AKnLr2wdAp";
|
||||
|
||||
private const CLOCK_DRIFT_MAX = 60;
|
||||
|
||||
@ -141,7 +155,8 @@ class ProcessLoginTask extends AsyncTask{
|
||||
try{
|
||||
$signingKeyOpenSSL = JwtUtils::parseDerPublicKey($headerDerKey);
|
||||
}catch(JwtException $e){
|
||||
throw new VerifyLoginException("Invalid JWT public key: " . openssl_error_string());
|
||||
//TODO: we shouldn't be showing this internal information to the client
|
||||
throw new VerifyLoginException("Invalid JWT public key: " . $e->getMessage(), 0, $e);
|
||||
}
|
||||
try{
|
||||
if(!JwtUtils::verify($jwt, $signingKeyOpenSSL)){
|
||||
@ -151,7 +166,7 @@ class ProcessLoginTask extends AsyncTask{
|
||||
throw new VerifyLoginException($e->getMessage(), 0, $e);
|
||||
}
|
||||
|
||||
if($headers->x5u === self::MOJANG_ROOT_PUBLIC_KEY){
|
||||
if($headers->x5u === self::MOJANG_ROOT_PUBLIC_KEY || $headers->x5u === self::MOJANG_OLD_ROOT_PUBLIC_KEY){
|
||||
$this->authenticated = true; //we're signed into xbox live
|
||||
}
|
||||
|
||||
@ -181,6 +196,12 @@ class ProcessLoginTask extends AsyncTask{
|
||||
if($identityPublicKey === false){
|
||||
throw new VerifyLoginException("Invalid identityPublicKey: base64 error decoding");
|
||||
}
|
||||
try{
|
||||
//verify key format and parameters
|
||||
JwtUtils::parseDerPublicKey($identityPublicKey);
|
||||
}catch(JwtException $e){
|
||||
throw new VerifyLoginException("Invalid identityPublicKey: " . $e->getMessage(), 0, $e);
|
||||
}
|
||||
$currentPublicKey = $identityPublicKey; //if there are further links, the next link should be signed with this
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ final class RuntimeBlockMapping{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $keyIndex
|
||||
* @param string[] $keyIndex
|
||||
* @param (ByteTag|StringTag|IntTag)[][] $valueIndex
|
||||
* @phpstan-param array<string, string> $keyIndex
|
||||
* @phpstan-param array<int, array<int|string, ByteTag|IntTag|StringTag>> $valueIndex
|
||||
|
@ -33,6 +33,7 @@ use function hex2bin;
|
||||
use function openssl_digest;
|
||||
use function openssl_error_string;
|
||||
use function openssl_pkey_derive;
|
||||
use function openssl_pkey_get_details;
|
||||
use function str_pad;
|
||||
use const STR_PAD_LEFT;
|
||||
|
||||
@ -42,7 +43,20 @@ final class EncryptionUtils{
|
||||
//NOOP
|
||||
}
|
||||
|
||||
private static function validateKey(\OpenSSLAsymmetricKey $key) : void{
|
||||
$keyDetails = Utils::assumeNotFalse(openssl_pkey_get_details($key));
|
||||
if(!isset($keyDetails["ec"]["curve_name"])){
|
||||
throw new \InvalidArgumentException("Key must be an EC key");
|
||||
}
|
||||
$curveName = $keyDetails["ec"]["curve_name"];
|
||||
if($curveName !== JwtUtils::BEDROCK_SIGNING_KEY_CURVE_NAME){
|
||||
throw new \InvalidArgumentException("Key must belong to the " . JwtUtils::BEDROCK_SIGNING_KEY_CURVE_NAME . " elliptic curve, got $curveName");
|
||||
}
|
||||
}
|
||||
|
||||
public static function generateSharedSecret(\OpenSSLAsymmetricKey $localPriv, \OpenSSLAsymmetricKey $remotePub) : \GMP{
|
||||
self::validateKey($localPriv);
|
||||
self::validateKey($remotePub);
|
||||
$hexSecret = openssl_pkey_derive($remotePub, $localPriv, 48);
|
||||
if($hexSecret === false){
|
||||
throw new \InvalidArgumentException("Failed to derive shared secret: " . openssl_error_string());
|
||||
|
@ -113,9 +113,9 @@ use pocketmine\utils\TextFormat;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\world\format\Chunk;
|
||||
use function array_push;
|
||||
use function base64_encode;
|
||||
use function count;
|
||||
use function fmod;
|
||||
use function get_debug_type;
|
||||
use function implode;
|
||||
use function in_array;
|
||||
use function is_bool;
|
||||
@ -748,27 +748,32 @@ class InGamePacketHandler extends PacketHandler{
|
||||
if(!($nbt instanceof CompoundTag)) throw new AssumptionFailedError("PHPStan should ensure this is a CompoundTag"); //for phpstorm's benefit
|
||||
|
||||
if($block instanceof BaseSign){
|
||||
if(($textBlobTag = $nbt->getCompoundTag(Sign::TAG_FRONT_TEXT)?->getTag(Sign::TAG_TEXT_BLOB)) instanceof StringTag){
|
||||
try{
|
||||
$text = SignText::fromBlob($textBlobTag->getValue());
|
||||
}catch(\InvalidArgumentException $e){
|
||||
throw PacketHandlingException::wrap($e, "Invalid sign text update");
|
||||
}
|
||||
|
||||
try{
|
||||
if(!$block->updateText($this->player, $text)){
|
||||
foreach($this->player->getWorld()->createBlockUpdatePackets([$pos]) as $updatePacket){
|
||||
$this->session->sendDataPacket($updatePacket);
|
||||
}
|
||||
}
|
||||
}catch(\UnexpectedValueException $e){
|
||||
throw PacketHandlingException::wrap($e);
|
||||
}
|
||||
|
||||
return true;
|
||||
$frontTextTag = $nbt->getTag(Sign::TAG_FRONT_TEXT);
|
||||
if(!$frontTextTag instanceof CompoundTag){
|
||||
throw new PacketHandlingException("Invalid tag type " . get_debug_type($frontTextTag) . " for tag \"" . Sign::TAG_FRONT_TEXT . "\" in sign update data");
|
||||
}
|
||||
$textBlobTag = $frontTextTag->getTag(Sign::TAG_TEXT_BLOB);
|
||||
if(!$textBlobTag instanceof StringTag){
|
||||
throw new PacketHandlingException("Invalid tag type " . get_debug_type($textBlobTag) . " for tag \"" . Sign::TAG_TEXT_BLOB . "\" in sign update data");
|
||||
}
|
||||
|
||||
$this->session->getLogger()->debug("Invalid sign update data: " . base64_encode($packet->nbt->getEncodedNbt()));
|
||||
try{
|
||||
$text = SignText::fromBlob($textBlobTag->getValue());
|
||||
}catch(\InvalidArgumentException $e){
|
||||
throw PacketHandlingException::wrap($e, "Invalid sign text update");
|
||||
}
|
||||
|
||||
try{
|
||||
if(!$block->updateText($this->player, $text)){
|
||||
foreach($this->player->getWorld()->createBlockUpdatePackets([$pos]) as $updatePacket){
|
||||
$this->session->sendDataPacket($updatePacket);
|
||||
}
|
||||
}
|
||||
}catch(\UnexpectedValueException $e){
|
||||
throw PacketHandlingException::wrap($e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -39,6 +39,7 @@ use pocketmine\network\mcpe\protocol\types\CacheableNbt;
|
||||
use pocketmine\network\mcpe\protocol\types\DimensionIds;
|
||||
use pocketmine\network\mcpe\protocol\types\Experiments;
|
||||
use pocketmine\network\mcpe\protocol\types\LevelSettings;
|
||||
use pocketmine\network\mcpe\protocol\types\NetworkPermissions;
|
||||
use pocketmine\network\mcpe\protocol\types\PlayerMovementSettings;
|
||||
use pocketmine\network\mcpe\protocol\types\PlayerMovementType;
|
||||
use pocketmine\network\mcpe\protocol\types\SpawnSettings;
|
||||
@ -106,6 +107,7 @@ class PreSpawnPacketHandler extends PacketHandler{
|
||||
Uuid::fromString(Uuid::NIL),
|
||||
false,
|
||||
false,
|
||||
new NetworkPermissions(disableClientSounds: true),
|
||||
[],
|
||||
0,
|
||||
GlobalItemTypeDictionary::getInstance()->getDictionary()->getEntries(),
|
||||
|
@ -252,9 +252,15 @@ abstract class AsyncTask extends \Threaded{
|
||||
final public function __destruct(){
|
||||
$this->reallyDestruct();
|
||||
if(self::$threadLocalStorage !== null && isset(self::$threadLocalStorage[$h = spl_object_id($this)])){
|
||||
unset(self::$threadLocalStorage[$h]);
|
||||
if(self::$threadLocalStorage->count() === 0){
|
||||
//Beware changing this code!
|
||||
//This code may cause the GC to be triggered, causing destruction of other AsyncTasks (which may or may not
|
||||
//have been indirectly referenced by the TLS).
|
||||
//This may cause the code to be re-entered from a different context unexpectedly, causing a crash if handled
|
||||
//incorrectly.
|
||||
if(self::$threadLocalStorage->count() === 1){
|
||||
self::$threadLocalStorage = null;
|
||||
}else{
|
||||
unset(self::$threadLocalStorage[$h]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ class BlockTest extends TestCase{
|
||||
* @return int[][]
|
||||
* @phpstan-return list<array{int,int}>
|
||||
*/
|
||||
public function blockGetProvider() : array{
|
||||
public static function blockGetProvider() : array{
|
||||
return [
|
||||
[BlockLegacyIds::STONE, 5],
|
||||
[BlockLegacyIds::GOLD_BLOCK, 0],
|
||||
|
@ -33,7 +33,7 @@ class BrewingStandTest extends TestCase{
|
||||
/**
|
||||
* @phpstan-return \Generator<int, array{list<BrewingStandSlot>}, void, void>
|
||||
*/
|
||||
public function slotsProvider() : \Generator{
|
||||
public static function slotsProvider() : \Generator{
|
||||
yield [array_values(BrewingStandSlot::getAll())];
|
||||
yield [[BrewingStandSlot::EAST()]];
|
||||
yield [[BrewingStandSlot::EAST(), BrewingStandSlot::NORTHWEST()]];
|
||||
|
@ -27,7 +27,7 @@ use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CommandStringHelperTest extends TestCase{
|
||||
|
||||
public function parseQuoteAwareProvider() : \Generator{
|
||||
public static function parseQuoteAwareProvider() : \Generator{
|
||||
yield [
|
||||
'give "steve jobs" apple',
|
||||
['give', 'steve jobs', 'apple']
|
||||
|
@ -49,7 +49,7 @@ class HandlerListManagerTest extends TestCase{
|
||||
* @return \Generator|mixed[][]
|
||||
* @phpstan-return \Generator<int, array{\ReflectionClass<Event>, bool, string}, void, void>
|
||||
*/
|
||||
public function isValidClassProvider() : \Generator{
|
||||
public static function isValidClassProvider() : \Generator{
|
||||
yield [new \ReflectionClass(Event::class), false, "event base should not be handleable"];
|
||||
yield [new \ReflectionClass(TestConcreteEvent::class), true, ""];
|
||||
yield [new \ReflectionClass(TestAbstractEvent::class), false, "abstract event cannot be handled"];
|
||||
@ -69,7 +69,7 @@ class HandlerListManagerTest extends TestCase{
|
||||
* @return \Generator|\ReflectionClass[][]
|
||||
* @phpstan-return \Generator<int, array{\ReflectionClass<Event>, \ReflectionClass<Event>|null}, void, void>
|
||||
*/
|
||||
public function resolveParentClassProvider() : \Generator{
|
||||
public static function resolveParentClassProvider() : \Generator{
|
||||
yield [new \ReflectionClass(TestConcreteExtendsAllowHandleEvent::class), new \ReflectionClass(TestAbstractAllowHandleEvent::class)];
|
||||
yield [new \ReflectionClass(TestConcreteEvent::class), null];
|
||||
yield [new \ReflectionClass(TestConcreteExtendsAbstractEvent::class), null];
|
||||
|
@ -31,7 +31,7 @@ class LegacyStringToItemParserTest extends TestCase{
|
||||
* @return mixed[][]
|
||||
* @phpstan-return list<array{string,int,int}>
|
||||
*/
|
||||
public function itemFromStringProvider() : array{
|
||||
public static function itemFromStringProvider() : array{
|
||||
return [
|
||||
["dye:4", ItemIds::DYE, 4],
|
||||
["351", ItemIds::DYE, 0],
|
||||
|
@ -32,7 +32,7 @@ class ApiVersionTest extends TestCase{
|
||||
* @return \Generator|mixed[][]
|
||||
* @phpstan-return \Generator<int, array{string, string, bool}, void, void>
|
||||
*/
|
||||
public function compatibleApiProvider() : \Generator{
|
||||
public static function compatibleApiProvider() : \Generator{
|
||||
yield ["3.0.0", "3.0.0", true];
|
||||
yield ["3.1.0", "3.0.0", true];
|
||||
yield ["3.0.0", "3.1.0", false];
|
||||
@ -58,7 +58,7 @@ class ApiVersionTest extends TestCase{
|
||||
* @return mixed[][][]
|
||||
* @phpstan-return \Generator<int, array{list<string>, list<string>}, void, void>
|
||||
*/
|
||||
public function ambiguousVersionsProvider() : \Generator{
|
||||
public static function ambiguousVersionsProvider() : \Generator{
|
||||
yield [["3.0.0"], []];
|
||||
yield [["3.0.0", "3.0.1"], ["3.0.0", "3.0.1"]];
|
||||
yield [["3.0.0", "3.1.0", "4.0.0"], ["3.0.0", "3.1.0"]];
|
||||
|
@ -69,4 +69,36 @@ class AsyncPoolTest extends TestCase{
|
||||
}
|
||||
self::assertTrue(PublishProgressRaceAsyncTask::$success, "Progress was not reported before task completion");
|
||||
}
|
||||
|
||||
/**
|
||||
* This test ensures that the fix for an exotic AsyncTask::__destruct() reentrancy bug has not regressed.
|
||||
*
|
||||
* Due to an unset() in the function body, other AsyncTask::__destruct() calls could be triggered during
|
||||
* an AsyncTask's destruction. If done in the wrong way, this could lead to a crash.
|
||||
*
|
||||
* @doesNotPerformAssertions This test is checking for a crash condition, not a specific output.
|
||||
*/
|
||||
public function testTaskDestructorReentrancy() : void{
|
||||
$this->pool->submitTask(new class extends AsyncTask{
|
||||
public function __construct(){
|
||||
$this->storeLocal("task", new class extends AsyncTask{
|
||||
|
||||
public function __construct(){
|
||||
$this->storeLocal("dummy", 1);
|
||||
}
|
||||
|
||||
public function onRun() : void{
|
||||
//dummy
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function onRun() : void{
|
||||
//dummy
|
||||
}
|
||||
});
|
||||
while($this->pool->collectTasks()){
|
||||
usleep(50 * 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ final class CloningRegistryTraitTest extends TestCase{
|
||||
/**
|
||||
* @phpstan-return \Generator<int, array{\Closure() : \stdClass}, void, void>
|
||||
*/
|
||||
public function cloningRegistryMembersProvider() : \Generator{
|
||||
public static function cloningRegistryMembersProvider() : \Generator{
|
||||
yield [function() : \stdClass{ return TestCloningRegistry::TEST1(); }];
|
||||
yield [function() : \stdClass{ return TestCloningRegistry::TEST2(); }];
|
||||
yield [function() : \stdClass{ return TestCloningRegistry::TEST3(); }];
|
||||
|
@ -32,7 +32,7 @@ class ConfigTest extends TestCase{
|
||||
* @return \Generator|mixed[][]
|
||||
* @phpstan-return \Generator<int, array{string, mixed[]}, void, void>
|
||||
*/
|
||||
public function fixYamlIndexesProvider() : \Generator{
|
||||
public static function fixYamlIndexesProvider() : \Generator{
|
||||
yield ["x: 1\ny: 2\nz: 3\n", [
|
||||
"x" => 1,
|
||||
"y" => 2,
|
||||
|
@ -44,7 +44,7 @@ class UtilsTest extends TestCase{
|
||||
* @return string[][]
|
||||
* @phpstan-return list<array{string}>
|
||||
*/
|
||||
public function parseDocCommentNewlineProvider() : array{
|
||||
public static function parseDocCommentNewlineProvider() : array{
|
||||
return [
|
||||
["\t/**\r\n\t * @param PlayerJoinEvent \$event\r\n\t * @priority HIGHEST\r\n\t * @notHandler\r\n\t */"],
|
||||
["\t/**\n\t * @param PlayerJoinEvent \$event\n\t * @priority HIGHEST\n\t * @notHandler\n\t */"],
|
||||
@ -68,7 +68,7 @@ class UtilsTest extends TestCase{
|
||||
* @return string[][]
|
||||
* @phpstan-return list<array{string}>
|
||||
*/
|
||||
public function parseDocCommentOneLineProvider() : array{
|
||||
public static function parseDocCommentOneLineProvider() : array{
|
||||
return [
|
||||
["/** @ignoreCancelled true dummy */"],
|
||||
["/**@ignoreCancelled true dummy*/"],
|
||||
@ -105,7 +105,7 @@ class UtilsTest extends TestCase{
|
||||
* @return string[][]
|
||||
* @return list<array{class-string, class-string}>
|
||||
*/
|
||||
public function validInstanceProvider() : array{
|
||||
public static function validInstanceProvider() : array{
|
||||
return [
|
||||
//direct instance / implement / extend
|
||||
[TestInstantiableClass::class, TestInstantiableClass::class],
|
||||
@ -133,7 +133,7 @@ class UtilsTest extends TestCase{
|
||||
* @return string[][]
|
||||
* @return list<array{string, string}>
|
||||
*/
|
||||
public function validInstanceInvalidCombinationsProvider() : array{
|
||||
public static function validInstanceInvalidCombinationsProvider() : array{
|
||||
return [
|
||||
["iDontExist abc", TestInstantiableClass::class],
|
||||
[TestInstantiableClass::class, "iDon'tExist abc"],
|
||||
|
@ -74,7 +74,7 @@ class RegionLoaderTest extends TestCase{
|
||||
* @return \Generator|int[][]
|
||||
* @phpstan-return \Generator<int, array{int,int}, void, void>
|
||||
*/
|
||||
public function outOfBoundsCoordsProvider() : \Generator{
|
||||
public static function outOfBoundsCoordsProvider() : \Generator{
|
||||
yield [-1, -1];
|
||||
yield [32, 32];
|
||||
yield [-1, 32];
|
||||
|
@ -31,7 +31,7 @@ class RegionLocationTableEntryTest extends TestCase{
|
||||
/**
|
||||
* @phpstan-return \Generator<int, array{RegionLocationTableEntry, RegionLocationTableEntry, bool}, void, void>
|
||||
*/
|
||||
public function overlapDataProvider() : \Generator{
|
||||
public static function overlapDataProvider() : \Generator{
|
||||
yield [new RegionLocationTableEntry(2, 1, 0), new RegionLocationTableEntry(2, 1, 0), true];
|
||||
yield [new RegionLocationTableEntry(2, 1, 0), new RegionLocationTableEntry(3, 1, 0), false];
|
||||
yield [new RegionLocationTableEntry(2, 2, 0), new RegionLocationTableEntry(3, 2, 0), true];
|
||||
|
Submodule tests/plugins/DevTools updated: a67f9af8d6...a2f36e8dbf
Reference in New Issue
Block a user