Merge branch 'stable'

This commit is contained in:
Dylan K. Taylor 2021-01-27 20:04:13 +00:00
commit bbae02264d
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
18 changed files with 108 additions and 127 deletions

View File

@ -4,6 +4,9 @@
</p>
![CI](https://github.com/pmmp/PocketMine-MP/workflows/CI/badge.svg)
[![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/pmmp/PocketMine-MP?label=release&logo=github)](https://github.com/pmmp/PocketMine-MP/releases)
[![Docker Image Version (latest semver)](https://img.shields.io/docker/v/pmmp/pocketmine-mp?logo=docker&label=image)](https://hub.docker.com/r/pmmp/pocketmine-mp)
[![Discord](https://img.shields.io/discord/373199722573201408?label=discord&color=7289DA&logo=discord)](https://discord.gg/bmSAZBG)
## Getting started
- [Documentation](http://pmmp.readthedocs.org/)

View File

@ -26,3 +26,9 @@ Plugin developers should **only** update their required API to this version if y
- Fixed region header corruption when chunks with larger-than-expected lengths are found. These chunks are now treated as corrupted, instead of automatically attempting to salvage them (which usually fails anyway).
- `RegionLoader->removeChunk()` now allows the space used by the removed chunk to be reused by future region saves.
- Extracted `Living->applyConsumptionResults()` from `Living->consumeObject()` (preparation for a future bug fix).
# 3.17.3
- Improved performance of chunk loading in Region-based worlds.
- Improved performance of region header validation in Region-based worlds (indirect improvement to chunk loading performance).
- Fixed some PHP 8.0 language-level compatibility issues.
- Source installations will now exit with an error when Composer dependencies are not in sync with the current Git revision. Now, it's required to run `composer install` after every git pull to make sure the correct dependency versions are installed.

View File

@ -50,7 +50,7 @@
"composer-runtime-api": "^2.0"
},
"require-dev": {
"phpstan/phpstan": "0.12.67",
"phpstan/phpstan": "0.12.69",
"phpstan/phpstan-phpunit": "^0.12.6",
"phpstan/phpstan-strict-rules": "^0.12.2",
"phpunit/phpunit": "^9.2"

26
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "87788eccf53392e9d2bd3345ad9f9c99",
"content-hash": "516f0ca0b6b64244f81ea8340c48347f",
"packages": [
{
"name": "adhocore/json-comment",
@ -1521,16 +1521,16 @@
},
{
"name": "phpstan/phpstan",
"version": "0.12.67",
"version": "0.12.69",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "ced7a5d9c5dba908c1c00cea3f1d4ad74da71b86"
"reference": "8f436ea35241da33487fd0d38b4bc3e6dfe30ea8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/ced7a5d9c5dba908c1c00cea3f1d4ad74da71b86",
"reference": "ced7a5d9c5dba908c1c00cea3f1d4ad74da71b86",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/8f436ea35241da33487fd0d38b4bc3e6dfe30ea8",
"reference": "8f436ea35241da33487fd0d38b4bc3e6dfe30ea8",
"shasum": ""
},
"require": {
@ -1561,7 +1561,7 @@
"description": "PHPStan - PHP Static Analysis Tool",
"support": {
"issues": "https://github.com/phpstan/phpstan/issues",
"source": "https://github.com/phpstan/phpstan/tree/0.12.67"
"source": "https://github.com/phpstan/phpstan/tree/0.12.69"
},
"funding": [
{
@ -1577,7 +1577,7 @@
"type": "tidelift"
}
],
"time": "2021-01-14T14:16:19+00:00"
"time": "2021-01-24T14:55:37+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
@ -2005,16 +2005,16 @@
},
{
"name": "phpunit/phpunit",
"version": "9.5.0",
"version": "9.5.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "8e16c225d57c3d6808014df6b1dd7598d0a5bbbe"
"reference": "e7bdf4085de85a825f4424eae52c99a1cec2f360"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8e16c225d57c3d6808014df6b1dd7598d0a5bbbe",
"reference": "8e16c225d57c3d6808014df6b1dd7598d0a5bbbe",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e7bdf4085de85a825f4424eae52c99a1cec2f360",
"reference": "e7bdf4085de85a825f4424eae52c99a1cec2f360",
"shasum": ""
},
"require": {
@ -2092,7 +2092,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.0"
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.1"
},
"funding": [
{
@ -2104,7 +2104,7 @@
"type": "github"
}
],
"time": "2020-12-04T05:05:53+00:00"
"time": "2021-01-17T07:42:25+00:00"
},
{
"name": "sebastian/cli-parser",

View File

@ -4,6 +4,7 @@ includes:
- tests/phpstan/configs/com-dotnet-magic.neon
- tests/phpstan/configs/ds-bugs.neon
- tests/phpstan/configs/gc-hacks.neon
- tests/phpstan/configs/impossible-generics.neon
- tests/phpstan/configs/l7-baseline.neon
- tests/phpstan/configs/l8-baseline.neon
- tests/phpstan/configs/php-bugs.neon
@ -21,6 +22,7 @@ rules:
parameters:
level: 8
checkExplicitMixed: true
checkMissingCallableSignature: true
bootstrapFiles:
- tests/phpstan/bootstrap.php
scanDirectories:
@ -46,3 +48,9 @@ parameters:
reportUnmatchedIgnoredErrors: false #no other way to silence platform-specific non-warnings
staticReflectionClassNamePatterns:
- "#^COM$#"
typeAliases:
#variadics don't work for this - mixed probably shouldn't work either, but for now it does
#what we actually need is something that accepts an infinite number of parameters, but in the absence of that,
#we'll just fill it with 10 - it's very unlikely to encounter a callable with 10 parameters anyway.
anyCallable: 'callable(mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed) : mixed'
anyClosure: '\Closure(mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed) : mixed'

View File

@ -458,8 +458,12 @@ class MemoryManager{
}
$name = $property->getName();
if($reflection !== $original and !$property->isPublic()){
$name = $reflection->getName() . ":" . $name;
if($reflection !== $original){
if($property->isPrivate()){
$name = $reflection->getName() . ":" . $name;
}else{
continue;
}
}
if(!$property->isPublic()){
$property->setAccessible(true);

View File

@ -26,23 +26,18 @@ namespace pocketmine\command;
use pocketmine\snooze\SleeperNotifier;
use pocketmine\thread\Thread;
use pocketmine\thread\ThreadException;
use pocketmine\utils\Utils;
use function extension_loaded;
use function fclose;
use function fgets;
use function fopen;
use function fstat;
use function getopt;
use function is_resource;
use function microtime;
use function preg_replace;
use function readline;
use function readline_add_history;
use function stream_isatty;
use function stream_select;
use function trim;
use function usleep;
use const STDIN;
class CommandReader extends Thread{
@ -66,12 +61,6 @@ class CommandReader extends Thread{
public function __construct(?SleeperNotifier $notifier = null){
$this->buffer = new \Threaded;
$this->notifier = $notifier;
$opts = getopt("", ["disable-readline", "enable-readline"]);
if(extension_loaded("readline") and (Utils::getOS() === Utils::OS_WINDOWS ? isset($opts["enable-readline"]) : !isset($opts["disable-readline"])) and !$this->isPipe(STDIN)){
$this->type = self::TYPE_READLINE;
}
}
public function shutdown() : void{
@ -126,41 +115,34 @@ class CommandReader extends Thread{
*/
private function readLine() : bool{
$line = "";
if($this->type === self::TYPE_READLINE){
if(($raw = readline("> ")) !== false and ($line = trim($raw)) !== ""){
readline_add_history($line);
}else{
return true;
}
}else{
if(!is_resource(self::$stdin)){
$this->initStdin();
}
switch($this->type){
/** @noinspection PhpMissingBreakStatementInspection */
case self::TYPE_STREAM:
//stream_select doesn't work on piped streams for some reason
$r = [self::$stdin];
$w = $e = null;
if(($count = stream_select($r, $w, $e, 0, 200000)) === 0){ //nothing changed in 200000 microseconds
return true;
}elseif($count === false){ //stream error
$this->initStdin();
}
if(!is_resource(self::$stdin)){
$this->initStdin();
}
case self::TYPE_PIPED:
if(($raw = fgets(self::$stdin)) === false){ //broken pipe or EOF
$this->initStdin();
$this->synchronized(function() : void{
$this->wait(200000);
}); //prevent CPU waste if it's end of pipe
return true; //loop back round
}
switch($this->type){
/** @noinspection PhpMissingBreakStatementInspection */
case self::TYPE_STREAM:
//stream_select doesn't work on piped streams for some reason
$r = [self::$stdin];
$w = $e = null;
if(($count = stream_select($r, $w, $e, 0, 200000)) === 0){ //nothing changed in 200000 microseconds
return true;
}elseif($count === false){ //stream error
$this->initStdin();
}
$line = trim($raw);
break;
}
case self::TYPE_PIPED:
if(($raw = fgets(self::$stdin)) === false){ //broken pipe or EOF
$this->initStdin();
$this->synchronized(function() : void{
$this->wait(200000);
}); //prevent CPU waste if it's end of pipe
return true; //loop back round
}
$line = trim($raw);
break;
}
if($line !== ""){
@ -185,16 +167,11 @@ class CommandReader extends Thread{
}
protected function onRun() : void{
if($this->type !== self::TYPE_READLINE){
$this->initStdin();
}
$this->initStdin();
while(!$this->shutdown and $this->readLine());
if($this->type !== self::TYPE_READLINE){
fclose(self::$stdin);
}
fclose(self::$stdin);
}
public function getThreadName() : string{

View File

@ -69,7 +69,7 @@ class ProcessLoginTask extends AsyncTask{
/**
* @param string[] $chainJwts
* @phpstan-var \Closure(bool $isAuthenticated, bool $authRequired, ?string $error, ?PublicKeyInterface $clientPublicKey) : void $onCompletion
* @phpstan-param \Closure(bool $isAuthenticated, bool $authRequired, ?string $error, ?PublicKeyInterface $clientPublicKey) : void $onCompletion
*/
public function __construct(array $chainJwts, string $clientDataJwt, bool $authRequired, \Closure $onCompletion){
$this->storeLocal(self::TLS_KEY_ON_COMPLETION, $onCompletion);

View File

@ -124,8 +124,8 @@ class InGamePacketHandler extends PacketHandler{
/** @var float */
protected $lastRightClickTime = 0.0;
/** @var Vector3|null */
protected $lastRightClickPos = null;
/** @var UseItemTransactionData|null */
protected $lastRightClickData = null;
/** @var bool */
public $forceMoveSync = false;
@ -339,12 +339,14 @@ class InGamePacketHandler extends PacketHandler{
case UseItemTransactionData::ACTION_CLICK_BLOCK:
//TODO: start hack for client spam bug
$clickPos = $data->getClickPos();
$spamBug = ($this->lastRightClickPos !== null and
$spamBug = ($this->lastRightClickData !== null and
microtime(true) - $this->lastRightClickTime < 0.1 and //100ms
$this->lastRightClickPos->distanceSquared($clickPos) < 0.00001 //signature spam bug has 0 distance, but allow some error
$this->lastRightClickData->getPlayerPos()->distanceSquared($data->getPlayerPos()) < 0.00001 and
$this->lastRightClickData->getBlockPos()->equals($data->getBlockPos()) and
$this->lastRightClickData->getClickPos()->distanceSquared($clickPos) < 0.00001 //signature spam bug has 0 distance, but allow some error
);
//get rid of continued spam if the player clicks and holds right-click
$this->lastRightClickPos = clone $clickPos;
$this->lastRightClickData = $data;
$this->lastRightClickTime = microtime(true);
if($spamBug){
return true;

View File

@ -473,6 +473,7 @@ class PluginManager{
}
$handlerClosure = $method->getClosure($listener);
if($handlerClosure === null) throw new AssumptionFailedError("This should never happen");
try{
$priority = isset($tags["priority"]) ? EventPriority::fromString($tags["priority"]) : EventPriority::NORMAL;

View File

@ -99,6 +99,7 @@ final class Utils{
/**
* Returns a readable identifier for the given Closure, including file and line.
*
* @phpstan-param anyClosure $closure
* @throws \ReflectionException
*/
public static function getNiceClosureName(\Closure $closure) : string{
@ -498,6 +499,8 @@ final class Utils{
*
* @param callable $signature Dummy callable with the required parameters and return type
* @param callable $subject Callable to check the signature of
* @phpstan-param anyCallable $signature
* @phpstan-param anyCallable $subject
*
* @throws \DaveRandom\CallbackValidator\InvalidCallbackException
* @throws \TypeError

View File

@ -495,10 +495,12 @@ class World implements ChunkManager{
$this->closed = true;
}
/** @phpstan-param \Closure() : void $callback */
public function addOnUnloadCallback(\Closure $callback) : void{
$this->unloadCallbacks[spl_object_id($callback)] = $callback;
}
/** @phpstan-param \Closure() : void $callback */
public function removeOnUnloadCallback(\Closure $callback) : void{
unset($this->unloadCallbacks[spl_object_id($callback)]);
}

View File

@ -0,0 +1,17 @@
parameters:
ignoreErrors:
-
message: "#^Property pocketmine\\\\event\\\\RegisteredListener\\:\\:\\$handler type has no signature specified for Closure\\.$#"
count: 1
path: ../../../src/event/RegisteredListener.php
-
message: "#^Method pocketmine\\\\event\\\\RegisteredListener\\:\\:__construct\\(\\) has parameter \\$handler with no signature specified for Closure\\.$#"
count: 1
path: ../../../src/event/RegisteredListener.php
-
message: "#^Method pocketmine\\\\event\\\\RegisteredListener\\:\\:getHandler\\(\\) return type has no signature specified for Closure\\.$#"
count: 1
path: ../../../src/event/RegisteredListener.php

View File

@ -40,16 +40,6 @@ parameters:
count: 1
path: ../../../src/PocketMine.php
-
message: "#^Parameter \\#1 \\$filename of function is_file expects string, array\\<int, mixed\\>\\|string given\\.$#"
count: 1
path: ../../../src/PocketMine.php
-
message: "#^Binary operation \"\\.\" between 'Composer autoloader…' and array\\<int, mixed\\>\\|string\\|false results in an error\\.$#"
count: 1
path: ../../../src/PocketMine.php
-
message: "#^Binary operation \"\\.\" between array\\<int, mixed\\>\\|string\\|false and '/'\\|'\\\\\\\\' results in an error\\.$#"
count: 2
@ -85,11 +75,6 @@ parameters:
count: 1
path: ../../../src/ServerConfigGroup.php
-
message: "#^Parameter \\#2 \\$y of method pocketmine\\\\world\\\\format\\\\Chunk\\:\\:setFullBlock\\(\\) expects int, float\\|int given\\.$#"
count: 1
path: ../../../src/block/Block.php
-
message: "#^Parameter \\#1 \\$x of method pocketmine\\\\world\\\\World\\:\\:isInWorld\\(\\) expects int, float\\|int given\\.$#"
count: 1
@ -635,11 +620,6 @@ parameters:
count: 1
path: ../../../src/network/mcpe/auth/ProcessLoginTask.php
-
message: "#^Parameter \\#1 \\$buffer of method pocketmine\\\\nbt\\\\BaseNbtSerializer\\:\\:read\\(\\) expects string, string\\|false given\\.$#"
count: 1
path: ../../../src/network/mcpe/convert/RuntimeBlockMapping.php
-
message: "#^Parameter \\#1 \\$buffer of class pocketmine\\\\network\\\\mcpe\\\\protocol\\\\serializer\\\\PacketSerializer constructor expects string, string\\|false given\\.$#"
count: 1

View File

@ -255,16 +255,6 @@ parameters:
count: 4
path: ../../../src/plugin/PluginManager.php
-
message: "#^Parameter \\#1 \\$closure of static method pocketmine\\\\utils\\\\Utils\\:\\:getNiceClosureName\\(\\) expects Closure, Closure\\|null given\\.$#"
count: 2
path: ../../../src/plugin/PluginManager.php
-
message: "#^Parameter \\#2 \\$handler of method pocketmine\\\\plugin\\\\PluginManager\\:\\:registerEvent\\(\\) expects Closure\\(pocketmine\\\\event\\\\Event\\)\\: void, Closure\\|null given\\.$#"
count: 1
path: ../../../src/plugin/PluginManager.php
-
message: "#^Cannot call method handleException\\(\\) on pocketmine\\\\scheduler\\\\AsyncWorker\\|null\\.$#"
count: 1
@ -380,11 +370,6 @@ parameters:
count: 1
path: ../../../src/world/generator/PopulationTask.php
-
message: "#^Cannot call method getAsyncWorkerId\\(\\) on pocketmine\\\\scheduler\\\\AsyncWorker\\|null\\.$#"
count: 1
path: ../../../src/world/generator/PopulationTask.php
-
message: "#^Method pocketmine\\\\world\\\\generator\\\\biome\\\\BiomeSelector\\:\\:pickBiome\\(\\) should return pocketmine\\\\world\\\\biome\\\\Biome but returns pocketmine\\\\world\\\\biome\\\\Biome\\|null\\.$#"
count: 1
@ -460,11 +445,6 @@ parameters:
count: 1
path: ../../../src/world/light/BlockLightUpdate.php
-
message: "#^Parameter \\#4 \\$newLevel of method pocketmine\\\\world\\\\light\\\\LightUpdate\\:\\:setAndUpdateLight\\(\\) expects int, int\\<1, max\\>\\|null given\\.$#"
count: 1
path: ../../../src/world/light/BlockLightUpdate.php
-
message: "#^Cannot call method getFullBlock\\(\\) on pocketmine\\\\world\\\\format\\\\SubChunk\\|null\\.$#"
count: 1
@ -541,12 +521,12 @@ parameters:
path: ../../../src/world/light/SkyLightUpdate.php
-
message: "#^Property pocketmine\\\\event\\\\HandlerListManagerTest\\:\\:\\$isValidFunc \\(Closure\\) does not accept Closure\\|null\\.$#"
message: "#^Property pocketmine\\\\event\\\\HandlerListManagerTest\\:\\:\\$isValidFunc \\(Closure\\(ReflectionClass\\<pocketmine\\\\event\\\\Event\\>\\)\\: bool\\) does not accept Closure\\|null\\.$#"
count: 1
path: ../../phpunit/event/HandlerListManagerTest.php
-
message: "#^Property pocketmine\\\\event\\\\HandlerListManagerTest\\:\\:\\$resolveParentFunc \\(Closure\\) does not accept Closure\\|null\\.$#"
message: "#^Property pocketmine\\\\event\\\\HandlerListManagerTest\\:\\:\\$resolveParentFunc \\(Closure\\(ReflectionClass\\<pocketmine\\\\event\\\\Event\\>\\)\\: ReflectionClass\\<pocketmine\\\\event\\\\Event\\>\\|null\\) does not accept Closure\\|null\\.$#"
count: 1
path: ../../phpunit/event/HandlerListManagerTest.php

View File

@ -1,10 +1,5 @@
parameters:
ignoreErrors:
-
message: "#^Parameter \\#1 \\$class of method pocketmine\\\\world\\\\format\\\\io\\\\WorldProviderManager\\:\\:setDefault\\(\\) expects class\\-string\\<pocketmine\\\\world\\\\format\\\\io\\\\WritableWorldProvider\\>, class\\-string\\<pocketmine\\\\world\\\\format\\\\io\\\\WorldProvider\\> given\\.$#"
count: 1
path: ../../../src/Server.php
-
message: "#^Comparison operation \"\\>\\=\" between 0 and 2 is always false\\.$#"
count: 1

View File

@ -1,10 +1,5 @@
parameters:
ignoreErrors:
-
message: "#^Instanceof between pocketmine\\\\block\\\\utils\\\\BannerPattern and pocketmine\\\\block\\\\utils\\\\BannerPattern will always evaluate to true\\.$#"
count: 1
path: ../../../src/block/BaseBanner.php
-
message: "#^Instanceof between pocketmine\\\\event\\\\RegisteredListener and pocketmine\\\\event\\\\RegisteredListener will always evaluate to true\\.$#"
count: 1

View File

@ -27,9 +27,15 @@ use PHPUnit\Framework\TestCase;
class HandlerListManagerTest extends TestCase{
/** @var \Closure */
/**
* @var \Closure
* @phpstan-var \Closure(\ReflectionClass<Event>) : bool
*/
private $isValidFunc;
/** @var \Closure */
/**
* @var \Closure
* @phpstan-var \Closure(\ReflectionClass<Event>) : ?\ReflectionClass<Event>
*/
private $resolveParentFunc;
public function setUp() : void{
@ -80,7 +86,9 @@ class HandlerListManagerTest extends TestCase{
if($expect === null){
self::assertNull(($this->resolveParentFunc)($class));
}else{
self::assertSame(($this->resolveParentFunc)($class)->getName(), $expect->getName());
$actualParent = ($this->resolveParentFunc)($class);
self::assertNotNull($actualParent);
self::assertSame($actualParent->getName(), $expect->getName());
}
}
}