Compare commits

...

79 Commits

Author SHA1 Message Date
9d4c37fc3a Release 4.23.6 2023-08-21 18:26:47 +01:00
7f78ec0a32 Include PHP binary URLs in GitHub releases and build info 2023-08-21 16:05:59 +01:00
9f09acc079 Workaround for slot IDs not changing client side when old item == new item
this is a really dumb bug and seems similar to the armor bug I fixed a while ago.

fixes #5987

it's unlikely that #5727 will be solved by this, but one can hope...
2023-08-18 12:27:27 +01:00
aa3f4f2545 4.23.6 is next 2023-08-09 13:56:19 +01:00
f7279b6672 Release 4.23.5 2023-08-09 13:56:19 +01:00
2711ab4f00 Update composer dependencies 2023-08-09 13:49:19 +01:00
b4c5f5d58d PluginBase: fixed resource leak
all this time we've been harping at plugin devs to fix their own leaks, and here's one right under our noses that no one spotted for 10 years ...

this leak is rather common, since it will occur whenever a plugin attempts to save a resource which already exists in the data folder.

This bug was introduced in 2014 by commit 6328834681.
2023-08-09 13:28:05 +01:00
d88c3d8ced Fixed coral block killing itself when calling getDropsForCompatibleTool()
this might be called by plugins without actually breaking the block, in which case the block will glitch.
2023-08-02 13:43:36 +01:00
bb0e648276 Fixed BlockDeathEvent usages showing an oldState which is already dead 2023-08-02 13:36:54 +01:00
e9e5923639 4.23.5 is next 2023-08-01 11:12:52 +01:00
49a9da147b Release 4.23.4 2023-08-01 11:12:41 +01:00
eb53b795d5 ItemEntity: fixed O(n^2) performance issue when many of the same unstackable item are in the same place
this produced a 40% performance improvement in a simulation with 800 item entities.

If the items were all different, then this would still be a problem. However, many of the same unstackable items occupying the same space is a problem for SkyBlock farms, so this should improve performance for SkyBlock quite a bit.
2023-07-31 11:29:12 +01:00
1c611a03e6 4.23.4 is next 2023-07-24 16:59:48 +01:00
948875b025 Release 4.23.3 2023-07-24 16:59:45 +01:00
2a4909d328 Fixed missing handling for some ContainerUIIds
SMITHING_TABLE_TEMPLATE is new in 1.20
HORSE_EQUIP was always present, but somehow got overlooked when building up that big ugly switch table
2023-07-24 16:44:01 +01:00
70dd8732e2 Update build/php to pmmp/PHP-Binaries@46604f2f6a 2023-07-24 11:59:11 +01:00
cdf72563f4 Update composer dependencies 2023-07-24 11:58:50 +01:00
d65d8c3356 Fix typo in documentation of ChunkSelector:selectChunks() (#5924) 2023-07-21 10:34:34 +01:00
9b43ddecbd Drop usages of Process:kill() with subprocesses parameter
we don't need this any more with console reader improvements, and this was not working correctly anyway.

closes #5234
2023-07-20 17:10:39 +01:00
4bdd6410db Fire: fixed support requirements
closes #5599
2023-07-20 17:00:32 +01:00
6ea7fd7d6b ShulkerBox: do not offer support for other blocks 2023-07-20 16:36:25 +01:00
5e7f18cbcf StandardEntityEventBroadcaster: suppress client-side emote messages
if users want these, they can broadcast them themselves using Server::broadcastMessage(), which will also record the message in the server log like chat

closes #5669
2023-07-20 16:20:34 +01:00
cff4a8d2bc 4.23.3 is next 2023-07-18 22:14:24 +01:00
20b7e8d702 Release 4.23.2 2023-07-18 22:14:23 +01:00
c6110be051 Update BedrockProtocol dependency 2023-07-18 22:12:33 +01:00
86bd6777a3 4.23.2 is next 2023-07-14 13:06:26 +01:00
935df62006 Release 4.23.1 2023-07-14 13:06:26 +01:00
2709dd359c ProcessLoginTask: fixed backport errors 2023-07-14 12:37:50 +01:00
4e646d19a4 Harden login EC key validation 2023-07-14 11:55:47 +01:00
2a11762e61 Update JsonMapper dependency 2023-07-14 11:54:05 +01:00
7e0b5cf73d 4.23.1 is next 2023-07-12 13:44:16 +01:00
e903da8998 Release 4.23.0 2023-07-12 13:44:16 +01:00
f2193d1ba7 1.20.10 2023-07-12 13:23:47 +01:00
f7977c9668 Update build/php submodule to pmmp/PHP-Binaries@16378ffcc3 2023-07-12 12:10:09 +01:00
cfd9950b02 4.22.4 is next 2023-07-11 16:01:42 +01:00
8ebcdb452d Release 4.22.3 2023-07-11 16:01:38 +01:00
aacc00a911 update-updater-api: do not allow multiple jobs to run simultaneously
this would result in git conflicts if multiple releases are made at the same time

closes #5814
2023-07-11 15:10:35 +01:00
0c250a2ef0 InGamePacketHandler: fixed inconsistent handling of invalid data in BlockActorDataPacket 2023-07-11 12:53:29 +01:00
70dd9c7371 AsyncTask: fixed reentrancy bug tested by f8e6f036af 2023-07-01 13:27:32 +01:00
f8e6f036af AsyncPoolTest: added failing test case for AsyncTask::__destruct() reentrancy bug 2023-07-01 13:24:50 +01:00
bbabccfc89 4.22.3 is next 2023-07-01 12:04:59 +01:00
1698eac6dc Release 4.22.2 2023-07-01 12:04:59 +01:00
321972b87b Composer: do not allow automatic minor dependency updates
manual intervention should always be used here, since we need to present a consistent API to plugins.
2023-07-01 11:57:13 +01:00
c86c9b3ead Update Composer dependencies 2023-07-01 11:43:36 +01:00
249ef9c534 ProcessLoginTask: remove old key expiry
since we don't have a hard date for this, and I've already made one wrong educated guess, I'd rather not have another massive outage.
A security update will have to be made to remove the old key as soon as the new one is rolled. This is not ideal, but it's the least disruptive option.
2023-07-01 11:41:04 +01:00
f4dab17a1b Added deprecation notices 2023-07-01 10:29:14 +01:00
e85605af7f changelog: fixed typo
[ci skip]
2023-06-09 01:44:45 +01:00
dfd70615ad 4.22.2 is next 2023-06-09 01:33:35 +01:00
ee903cad1f Release 4.22.1 2023-06-09 01:33:35 +01:00
9a04481bec Entity: broadcast teleports as regular movements
fixes #5810

probably fixes #4986

#5810 was caused by the workaround for #4394, which broke in 1.20 for reasons I'm still unclear on.

As FLAG_TELEPORT does not work at all for non-player entities, and causes bugs with player entities, sending the teleport movement without the flag is the least buggy way to solve all of these issues. Having the client interpolate teleport movements is not ideal, but there doesn't seem to be a way to reliably prevent it without causing even more bugs, so this will have to do.
2023-06-09 01:24:57 +01:00
5d514a274f Merge branch 'legacy/pm4' of github.com:pmmp/PocketMine-MP into legacy/pm4 2023-06-07 21:24:13 +01:00
2220dc557e 4.22.1 is next 2023-06-07 21:23:57 +01:00
b5fc31a781 Release 4.22.0 2023-06-07 21:23:54 +01:00
179eec9754 PHP-CS-Fixer 3.17 2023-06-07 21:04:11 +01:00
441f1f534f Random change PHP-CS-Fixer wanted to make 2023-06-07 20:59:32 +01:00
e747478afd and one more 2023-06-07 20:58:15 +01:00
92c45dd7e1 Fixed PHPUnit deprecation warnings 2023-06-07 20:57:43 +01:00
2538880408 1.20.0 2023-06-07 20:56:59 +01:00
c715efb18e Jukebox: fix music not stopping when destroyed by explosion
closes #5794
2023-06-03 21:22:26 +01:00
6678360c00 Make changelogs less infuriating in PhpStorm 2023-06-02 13:34:16 +01:00
3db45b6a68 Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2023-06-01 14:51:14 +01:00
3e87ad281f Use tagged fork of netresearch/jsonmapper
we need this for it to not be a huge pain in the ass to install PM as a composer dependency, which plugin CIs may do.
2023-06-01 14:51:04 +01:00
b72da777eb Bump tests/plugins/DevTools from a67f9af to a2f36e8 (#5785)
Bumps [tests/plugins/DevTools](https://github.com/pmmp/DevTools) from `a67f9af` to `a2f36e8`.
- [Release notes](https://github.com/pmmp/DevTools/releases)
- [Commits](a67f9af8d6...a2f36e8dbf)

---
updated-dependencies:
- dependency-name: tests/plugins/DevTools
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-01 13:45:20 +01:00
1101f35c17 Update setup-php-action to 2.0.0
this version vastly improves build time by using optimized prebuilts
instead of building the binaries on the runner.
2023-05-31 22:09:33 +01:00
3948dc4f75 Remove calls to ReflectionProperty::setAccessible() (#5783)
This is a no-op in PHP 8.1 and up.
2023-05-31 14:03:14 +01:00
20942b37eb Update composer dependencies 2023-05-30 16:07:01 +01:00
d343db8750 4.21.2 is next 2023-05-30 14:42:59 +01:00
f2df702c67 Release 4.21.1 2023-05-30 14:42:59 +01:00
481270e6aa Merge tag '4.20.5' into stable 2023-05-30 14:42:11 +01:00
e7bdaa8579 Release 4.20.5 2023-05-30 14:35:17 +01:00
76749cbaa7 Use fork of JsonMapper to solve cweiske/jsonmapper#210 2023-05-30 14:30:28 +01:00
a897bdfaa0 Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2023-05-30 14:17:21 +01:00
09668a37d6 Use fork of JsonMapper to solve cweiske/JsonMapper#210 2023-05-30 14:17:09 +01:00
ea92a23d0d Bump build/php from b1d5c0d to f2ece7b (#5765)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `b1d5c0d` to `f2ece7b`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](b1d5c0d737...f2ece7b30d)

---
updated-dependencies:
- dependency-name: build/php
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-29 21:37:18 +01:00
691e67018d Bump phpstan/phpstan-phpunit from 1.3.11 to 1.3.13 (#5772)
Bumps [phpstan/phpstan-phpunit](https://github.com/phpstan/phpstan-phpunit) from 1.3.11 to 1.3.13.
- [Release notes](https://github.com/phpstan/phpstan-phpunit/releases)
- [Commits](https://github.com/phpstan/phpstan-phpunit/compare/1.3.11...1.3.13)

---
updated-dependencies:
- dependency-name: phpstan/phpstan-phpunit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-29 21:36:58 +01:00
fe2140a716 Bump shivammathur/setup-php from 2.25.1 to 2.25.2 (#5766)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.25.1 to 2.25.2.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.25.1...2.25.2)

---
updated-dependencies:
- dependency-name: shivammathur/setup-php
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-29 21:36:46 +01:00
57330a7186 Bump build/php from f860ade to b1d5c0d (#5760)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `f860ade` to `b1d5c0d`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](f860ade30a...b1d5c0d737)

---
updated-dependencies:
- dependency-name: build/php
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-23 12:27:12 +01:00
9ddac21de0 Bump shivammathur/setup-php from 2.24.0 to 2.25.1 (#5711)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.24.0 to 2.25.1.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.24.0...2.25.1)

---
updated-dependencies:
- dependency-name: shivammathur/setup-php
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-21 00:13:22 +01:00
c91aa24daa Bump phpunit/phpunit from 9.6.8 to 10.1.3 (#5753)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.6.8 to 10.1.3.
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.1.3/ChangeLog-10.1.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.6.8...10.1.3)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-19 15:09:24 +01:00
56 changed files with 813 additions and 694 deletions

View File

@ -18,7 +18,12 @@ require dirname(__DIR__, 2) . '/vendor/autoload.php';
/**
* @phpstan-return array<string, mixed>
*/
function generateDiscordEmbed(string $version, string $channel, string $description, string $detailsUrl, string $sourceUrl, string $pharDownloadUrl, string $buildLogUrl, int $newsPingRoleId) : array{
function generateDiscordEmbed(string $version, string $channel, string $description, string $detailsUrl, string $sourceUrl, string $pharDownloadUrl, string $buildLogUrl, int $newsPingRoleId, ?string $phpDownloadUrl) : array{
if($phpDownloadUrl !== null){
$phpEmbedLink = " | [PHP Binaries]($phpDownloadUrl)";
}else{
$phpEmbedLink = "";
}
return [
"content" => "<@&$newsPingRoleId> New PocketMine-MP release: $version ($channel)",
"embeds" => [
@ -27,7 +32,7 @@ function generateDiscordEmbed(string $version, string $channel, string $descript
"description" => <<<DESCRIPTION
$description
[Details]($detailsUrl) | [Source Code]($sourceUrl) | [Build Log]($buildLogUrl) | [Download]($pharDownloadUrl)
[Details]($detailsUrl) | [Source Code]($sourceUrl) | [Build Log]($buildLogUrl) | [Download]($pharDownloadUrl)$phpEmbedLink
DESCRIPTION,
"url" => $detailsUrl,
"color" => $channel === "stable" ? 0x57ab5a : 0xc69026
@ -84,10 +89,21 @@ $detailsUrl = $buildInfoJson["details_url"];
$sourceUrl = $buildInfoJson["source_url"];
$pharDownloadUrl = $buildInfoJson["download_url"];
$buildLogUrl = $buildInfoJson["build_log_url"];
$phpBinaryUrl = $buildInfoJson["php_download_url"] ?? null;
$description = $releaseInfoJson["body"];
$discordPayload = generateDiscordEmbed($buildInfoJson["base_version"], $buildInfoJson["channel"], $description, $detailsUrl, $sourceUrl, $pharDownloadUrl, $buildLogUrl, (int) $newsPingRoleId);
$discordPayload = generateDiscordEmbed(
$buildInfoJson["base_version"],
$buildInfoJson["channel"],
$description,
$detailsUrl,
$sourceUrl,
$pharDownloadUrl,
$buildLogUrl,
(int) $newsPingRoleId,
$phpBinaryUrl
);
$response = Internet::postURL(
$hookURL,

View File

@ -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

View File

@ -11,6 +11,8 @@ jobs:
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
php-version: [8.1]
steps:
- uses: actions/checkout@v3
@ -18,9 +20,9 @@ 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
php-version: ${{ matrix.php-version }}
- name: Restore Composer package cache
uses: actions/cache@v3
@ -58,8 +60,21 @@ jobs:
echo CHANGELOG_SUFFIX=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BUILD_CHANNEL === "stable" ? "" : "-" . \pocketmine\VersionInfo::BUILD_CHANNEL;') >> $GITHUB_OUTPUT
echo PRERELEASE=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BUILD_CHANNEL === "stable" ? "false" : "true";') >> $GITHUB_OUTPUT
- name: Generate PHP binary download URL
id: php-binary-url
run: |
echo PHP_BINARY_URL="${{ github.server_url }}/${{ github.repository_owner }}/PHP-Binaries/releases/tag/php-${{ matrix.php-version }}-latest" >> $GITHUB_OUTPUT
- name: Generate build info
run: php build/generate-build-info-json.php ${{ github.sha }} ${{ steps.get-pm-version.outputs.PM_VERSION }} ${{ github.repository }} ${{ steps.build-number.outputs.BUILD_NUMBER }} ${{ github.run_id }} > build_info.json
run: |
php build/generate-build-info-json.php \
${{ github.sha }} \
${{ steps.get-pm-version.outputs.PM_VERSION }} \
${{ github.repository }} \
${{ steps.build-number.outputs.BUILD_NUMBER }} \
${{ github.run_id }} \
${{ steps.php-binary-url.outputs.PHP_BINARY_URL }} \
> build_info.json
- name: Upload release artifacts
uses: actions/upload-artifact@v3
@ -84,3 +99,7 @@ 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.
:information_source: Download the recommended PHP binary [here](${{ steps.php-binary-url.outputs.PHP_BINARY_URL }}).
: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.**

View File

@ -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 }}

View File

@ -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);
}

View File

@ -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

View File

@ -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" />

View File

@ -23,13 +23,13 @@ declare(strict_types=1);
require dirname(__DIR__) . '/vendor/autoload.php';
if(count($argv) !== 6){
fwrite(STDERR, "required args: <git hash> <tag name> <github repo (owner/name)> <build number> <github actions run ID>\n");
if(count($argv) !== 7){
fwrite(STDERR, "required args: <git hash> <tag name> <github repo (owner/name)> <build number> <github actions run ID> <PHP binary download URL>\n");
exit(1);
}
echo json_encode([
"php_version" => sprintf("%d.%d", PHP_MAJOR_VERSION, PHP_MINOR_VERSION),
"php_version" => sprintf("%d.%d", PHP_MAJOR_VERSION, PHP_MINOR_VERSION), //deprecated
"base_version" => \pocketmine\VersionInfo::BASE_VERSION,
"build" => (int) $argv[4],
"is_dev" => \pocketmine\VersionInfo::IS_DEVELOPMENT_BUILD,
@ -41,4 +41,5 @@ echo json_encode([
"download_url" => "https://github.com/$argv[3]/releases/download/$argv[2]/PocketMine-MP.phar",
"source_url" => "https://github.com/$argv[3]/tree/$argv[2]",
"build_log_url" => "https://github.com/$argv[3]/actions/runs/$argv[5]",
"php_download_url" => $argv[6],
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR) . "\n";

View File

@ -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).

View File

@ -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
View 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).

68
changelogs/4.23.md Normal file
View File

@ -0,0 +1,68 @@
# 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.
# 4.23.3
Released 24th July 2023.
## Documentation
- Fixed typo in `ChunkSelector::selectChunks()` documentation.
## Fixes
- Fixed the server not stopping properly during crash conditions on *nix platforms.
- Fixed `HORSE_EQUIP` and `SMITHING_TABLE_TEMPLATE` container UI types not being handled by `ItemStackContainerIdTranslator`. This bug prevented plugins from implementing missing inventory types.
- Player emotes no longer broadcast messages to other players. This was unintended behaviour caused by a client-side behavioural change.
- Shulker boxes no longer support the placement of torches or other similar blocks.
- Fire can now be placed on upper slabs and the top of upside-down stairs.
# 4.23.4
Released 1st August 2023.
## Fixes
- Fixed exponentially increasing lag when many hundreds of non-mergeable dropped items occupied the same space. This disproportionately affected SkyBlock servers due to large cactus farms using water to collect items together.
# 4.23.5
Released 9th August 2023.
## General
- Updated translation data to [pmmp/Language 2.19.6](https://github.com/pmmp/Language/releases/tag/2.19.6).
## Fixes
- Fixed `PluginBase->saveResource()` leaking file resources when the data file already exists in the plugin's data folder. This bug existed since 2014 and was only discovered recently.
- Fixed coral blocks becoming dead after calling `getDropsForCompatibleTool()` on them.
- Fixed `BlockDeathEvent->getOldState()` returning a block which is already dead.
# 4.23.6
Released 21st August 2023.
## Fixes
- Added a workaround for armor and other inventories not working correctly after inventory sync. This is caused by a client bug.

View File

@ -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.2+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": {

790
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -343,7 +343,7 @@ JIT_WARNING
if(ThreadManager::getInstance()->stopAll() > 0){
$logger->debug("Some threads could not be stopped, performing a force-kill");
Process::kill(Process::pid(), true);
Process::kill(Process::pid());
}
}while(false);

View File

@ -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);
@ -1441,7 +1446,7 @@ class Server{
private function forceShutdownExit() : void{
$this->forceShutdown();
Process::kill(Process::pid(), true);
Process::kill(Process::pid());
}
public function forceShutdown() : void{
@ -1509,7 +1514,7 @@ class Server{
}catch(\Throwable $e){
$this->logger->logException($e);
$this->logger->emergency("Crashed while crashing, killing process");
@Process::kill(Process::pid(), true);
@Process::kill(Process::pid());
}
}
@ -1663,7 +1668,7 @@ class Server{
echo "--- Waiting $spacing seconds to throttle automatic restart (you can kill the process safely now) ---" . PHP_EOL;
sleep($spacing);
}
@Process::kill(Process::pid(), true);
@Process::kill(Process::pid());
exit(1);
}

View File

@ -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.6";
public const IS_DEVELOPMENT_BUILD = false;
public const BUILD_CHANNEL = "stable";
private function __construct(){

View File

@ -51,7 +51,7 @@ abstract class BaseCoral extends Transparent{
//TODO: check water inside the block itself (not supported on the API yet)
if(!$hasWater){
$ev = new BlockDeathEvent($this, $this->setDead(true));
$ev = new BlockDeathEvent($this, (clone $this)->setDead(true));
$ev->call();
if(!$ev->isCancelled()){
$world->setBlock($this->position, $ev->getNewState());

View File

@ -78,7 +78,7 @@ final class CoralBlock extends Opaque{
}
}
if(!$hasWater){
$ev = new BlockDeathEvent($this, $this->setDead(true));
$ev = new BlockDeathEvent($this, (clone $this)->setDead(true));
$ev->call();
if(!$ev->isCancelled()){
$world->setBlock($this->position, $ev->getNewState());
@ -88,7 +88,7 @@ final class CoralBlock extends Opaque{
}
public function getDropsForCompatibleTool(Item $item) : array{
return [$this->setDead(true)->asItem()];
return [(clone $this)->setDead(true)->asItem()];
}
public function isAffectedBySilkTouch() : bool{

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\SupportType;
use pocketmine\entity\Entity;
use pocketmine\entity\projectile\Arrow;
use pocketmine\event\block\BlockBurnEvent;
@ -99,9 +100,13 @@ class Fire extends Flowable{
return [];
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::UP)->equals(SupportType::FULL());
}
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
if($this->getSide(Facing::DOWN)->isTransparent() && !$this->hasAdjacentFlammableBlocks()){
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN)) && !$this->hasAdjacentFlammableBlocks()){
$world->setBlock($this->position, VanillaBlocks::AIR());
}else{
$world->scheduleDelayedBlockUpdate($this->position, mt_rand(30, 40));

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\block\tile\ShulkerBox as TileShulkerBox;
use pocketmine\block\utils\AnyFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
@ -103,4 +104,8 @@ class ShulkerBox extends Opaque{
return true;
}
public function getSupportType(int $facing) : SupportType{
return SupportType::NONE();
}
}

View File

@ -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());
}
}

View File

@ -90,4 +90,4 @@ while(!feof($socket)){
//For simplicity's sake, we don't bother with a graceful shutdown here.
//The parent process would normally forcibly terminate the child process anyway, so we only reach this point if the
//parent process was terminated forcibly and didn't clean up after itself.
Process::kill(Process::pid(), false);
Process::kill(Process::pid());

View File

@ -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)){

View File

@ -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{

View File

@ -131,7 +131,7 @@ class ItemEntity extends Entity{
}
}
if($this->hasMovementUpdate() && $this->despawnDelay % self::MERGE_CHECK_PERIOD === 0){
if($this->hasMovementUpdate() && $this->isMergeCandidate() && $this->despawnDelay % self::MERGE_CHECK_PERIOD === 0){
$mergeable = [$this]; //in case the merge target ends up not being this
$mergeTarget = $this;
foreach($this->getWorld()->getNearbyEntities($this->boundingBox->expandedCopy(0.5, 0.5, 0.5), $this) as $entity){
@ -173,12 +173,19 @@ class ItemEntity extends Entity{
}
}
private function isMergeCandidate() : bool{
return $this->pickupDelay !== self::NEVER_DESPAWN && $this->item->getCount() < $this->item->getMaxStackSize();
}
/**
* Returns whether this item entity can merge with the given one.
*/
public function isMergeable(ItemEntity $entity) : bool{
if(!$this->isMergeCandidate() || !$entity->isMergeCandidate()){
return false;
}
$item = $entity->item;
return $entity !== $this && $entity->pickupDelay !== self::NEVER_DESPAWN && $item->canStackWith($this->item) && $item->getCount() + $this->item->getCount() <= $item->getMaxStackSize();
return $entity !== $this && $item->canStackWith($this->item) && $item->getCount() + $this->item->getCount() <= $item->getMaxStackSize();
}
/**

View File

@ -59,6 +59,7 @@ use pocketmine\network\PacketHandlingException;
use pocketmine\player\Player;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\ObjectSet;
use function array_fill_keys;
use function array_keys;
use function array_search;
use function count;
@ -429,6 +430,50 @@ class InventoryManager{
unset($inventoryEntry->predictions[$slot]);
}
private function sendInventorySlotPackets(int $windowId, int $netSlot, ItemStackWrapper $itemStackWrapper) : void{
/*
* TODO: HACK!
* As of 1.20.12, the client ignores change of itemstackID in some cases when the old item == the new item.
* Notably, this happens with armor, offhand and enchanting tables, but not with main inventory.
* While we could track the items previously sent to the client, that's a waste of memory and would
* cost performance. Instead, clear the slot(s) first, then send the new item(s).
* The network cost of doing this is fortunately minimal, as an air itemstack is only 1 byte.
*/
if($itemStackWrapper->getStackId() !== 0){
$this->session->sendDataPacket(InventorySlotPacket::create(
$windowId,
$netSlot,
new ItemStackWrapper(0, ItemStack::null())
));
}
//now send the real contents
$this->session->sendDataPacket(InventorySlotPacket::create(
$windowId,
$netSlot,
$itemStackWrapper
));
}
/**
* @param ItemStackWrapper[] $itemStackWrappers
*/
private function sendInventoryContentPackets(int $windowId, array $itemStackWrappers) : void{
/*
* TODO: HACK!
* As of 1.20.12, the client ignores change of itemstackID in some cases when the old item == the new item.
* Notably, this happens with armor, offhand and enchanting tables, but not with main inventory.
* While we could track the items previously sent to the client, that's a waste of memory and would
* cost performance. Instead, clear the slot(s) first, then send the new item(s).
* The network cost of doing this is fortunately minimal, as an air itemstack is only 1 byte.
*/
$this->session->sendDataPacket(InventoryContentPacket::create(
$windowId,
array_fill_keys(array_keys($itemStackWrappers), new ItemStackWrapper(0, ItemStack::null()))
));
//now send the real contents
$this->session->sendDataPacket(InventoryContentPacket::create($windowId, $itemStackWrappers));
}
public function syncSlot(Inventory $inventory, int $slot, ItemStack $itemStack) : void{
$entry = $this->inventories[spl_object_id($inventory)] ?? null;
if($entry === null){
@ -453,24 +498,9 @@ class InventoryManager{
//This can cause a lot of problems (totems, arrows, and more...).
//The workaround is to send an InventoryContentPacket instead
//BDS (Bedrock Dedicated Server) also seems to work this way.
$this->session->sendDataPacket(InventoryContentPacket::create($windowId, [$itemStackWrapper]));
$this->sendInventoryContentPackets($windowId, [$itemStackWrapper]);
}else{
if($windowId === ContainerIds::ARMOR){
//TODO: HACK!
//When right-clicking to equip armour, the client predicts the content of the armour slot, but
//doesn't report it in the transaction packet. The server then sends an InventorySlotPacket to
//the client, assuming the slot changed for some other reason, since there is no prediction for
//the slot.
//However, later requests involving that itemstack will refer to the request ID in which the
//armour was equipped, instead of the stack ID provided by the server in the outgoing
//InventorySlotPacket. (Perhaps because the item is already the same as the client actually
//predicted, but didn't tell us?)
//We work around this bug by setting the slot to air and then back to the correct item. In
//theory, setting a different count and then back again (or changing any other property) would
//also work, but this is simpler.
$this->session->sendDataPacket(InventorySlotPacket::create($windowId, $netSlot, new ItemStackWrapper(0, ItemStack::null())));
}
$this->session->sendDataPacket(InventorySlotPacket::create($windowId, $netSlot, $itemStackWrapper));
$this->sendInventorySlotPackets($windowId, $netSlot, $itemStackWrapper);
}
unset($entry->predictions[$slot], $entry->pendingSyncs[$slot]);
}
@ -497,20 +527,17 @@ class InventoryManager{
$info = $this->trackItemStack($entry, $slot, $itemStack, null);
$contents[] = new ItemStackWrapper($info->getStackId(), $itemStack);
}
$clearSlotWrapper = new ItemStackWrapper(0, ItemStack::null());
if($entry->complexSlotMap !== null){
foreach($contents as $slotId => $info){
$packetSlot = $entry->complexSlotMap->mapCoreToNet($slotId) ?? null;
if($packetSlot === null){
continue;
}
$this->session->sendDataPacket(InventorySlotPacket::create(
$windowId,
$packetSlot,
$info
));
$this->sendInventorySlotPackets($windowId, $packetSlot, $info);
}
}else{
$this->session->sendDataPacket(InventoryContentPacket::create($windowId, $contents));
$this->sendInventoryContentPackets($windowId, $contents);
}
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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 | EmotePacket::FLAG_MUTE_ANNOUNCEMENT));
}
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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());

View File

@ -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;

View File

@ -70,6 +70,7 @@ final class ItemStackContainerIdTranslator{
ContainerUIIds::MATERIAL_REDUCER_OUTPUT,
ContainerUIIds::SMITHING_TABLE_INPUT,
ContainerUIIds::SMITHING_TABLE_MATERIAL,
ContainerUIIds::SMITHING_TABLE_TEMPLATE,
ContainerUIIds::STONECUTTER_INPUT,
ContainerUIIds::TRADE2_INGREDIENT1,
ContainerUIIds::TRADE2_INGREDIENT2,
@ -84,6 +85,7 @@ final class ItemStackContainerIdTranslator{
ContainerUIIds::FURNACE_FUEL,
ContainerUIIds::FURNACE_INGREDIENT,
ContainerUIIds::FURNACE_RESULT,
ContainerUIIds::HORSE_EQUIP,
ContainerUIIds::LEVEL_ENTITY, //chest
ContainerUIIds::SHULKER_BOX,
ContainerUIIds::SMOKER_INGREDIENT => [$currentWindowId, $slotId],

View File

@ -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(),

View File

@ -30,7 +30,7 @@ use const M_SQRT2;
final class ChunkSelector{
/**
* @preturn \Generator|int[]
* @return \Generator|int[]
* @phpstan-return \Generator<int, int, void, void>
*/
public function selectChunks(int $radius, int $centerX, int $centerZ) : \Generator{

View File

@ -226,19 +226,19 @@ abstract class PluginBase implements Plugin, CommandExecutor{
return false;
}
$out = Path::join($this->dataFolder, $filename);
if(file_exists($out) && !$replace){
return false;
}
if(($resource = $this->getResource($filename)) === null){
return false;
}
$out = Path::join($this->dataFolder, $filename);
if(!file_exists(dirname($out))){
mkdir(dirname($out), 0755, true);
}
if(file_exists($out) && !$replace){
return false;
}
$fp = fopen($out, "wb");
if($fp === false) throw new AssumptionFailedError("fopen() should not fail with wb flags");

View File

@ -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]);
}
}
}

View File

@ -125,7 +125,10 @@ final class Process{
return count(ThreadManager::getInstance()->getAll()) + 2; //MainLogger + Main Thread
}
public static function kill(int $pid, bool $subprocesses) : void{
/**
* @param bool $subprocesses @deprecated
*/
public static function kill(int $pid, bool $subprocesses = false) : void{
$logger = \GlobalLogger::get();
if($logger instanceof MainLogger){
$logger->syncFlushBuffer();

View File

@ -49,7 +49,7 @@ class ServerKiller extends Thread{
});
if(time() - $start >= $this->time){
echo "\nTook too long to stop, server was killed forcefully!\n";
@Process::kill(Process::pid(), true);
@Process::kill(Process::pid());
}
}

View File

@ -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],

View File

@ -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()]];

View File

@ -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']

View File

@ -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];

View File

@ -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],

View File

@ -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"]];

View File

@ -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);
}
}
}

View File

@ -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(); }];

View File

@ -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,

View File

@ -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"],

View File

@ -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];

View File

@ -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];