diff --git a/changelogs/3.11.md b/changelogs/3.11.md new file mode 100644 index 000000000..31bf75d07 --- /dev/null +++ b/changelogs/3.11.md @@ -0,0 +1,14 @@ +**For Minecraft: Bedrock Edition 1.14.0** + +### Note about API versions +Plugins which don't touch the protocol and compatible with any previous 3.x.y version will also run on these releases and do not need API bumps. +Plugin developers should **only** update their required API to this version if you need the changes in this build. + +**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do. + +# 3.11.0 +- Added support for Minecraft: Bedrock Edition 1.14.0 +- Removed compatibility with 1.13.0 + +# 3.11.1 +- Fixed blocks with incorrect properties when placed or interacted with. \ No newline at end of file diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 170897410..c8556a7fd 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,12 +1,14 @@ includes: + - tests/phpstan/configs/debug-const-checks.neon - tests/phpstan/configs/gc-hacks.neon - tests/phpstan/configs/optional-com-dotnet.neon - tests/phpstan/configs/optional-leveldb.neon - tests/phpstan/configs/phpstan-bugs.neon - tests/phpstan/configs/pthreads-bugs.neon + - tests/phpstan/configs/runtime-type-checks.neon parameters: - level: 3 + level: 4 autoload_files: - tests/phpstan/bootstrap.php - src/pocketmine/PocketMine.php diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index a8236d579..3329720ad 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -464,11 +464,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ } public function getFirstPlayed(){ - return $this->namedtag instanceof CompoundTag ? $this->namedtag->getLong("firstPlayed", 0, true) : null; + return $this->namedtag->getLong("firstPlayed", 0, true); } public function getLastPlayed(){ - return $this->namedtag instanceof CompoundTag ? $this->namedtag->getLong("lastPlayed", 0, true) : null; + return $this->namedtag->getLong("lastPlayed", 0, true); } public function hasPlayedBefore() : bool{ @@ -1921,7 +1921,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ $animations = []; foreach($packet->clientData["AnimatedImageData"] as $animation){ - $animations[] = new SkinAnimation(new SkinImage($animation["ImageHeight"], $animation["ImageWidth"], $animation["Image"]), $animation["Type"], $animation["Frames"]); + $animations[] = new SkinAnimation(new SkinImage($animation["ImageHeight"], $animation["ImageWidth"], base64_decode($animation["Image"], true)), $animation["Type"], $animation["Frames"]); } $skinData = new SkinData( @@ -1931,7 +1931,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ $animations, new SkinImage($packet->clientData["CapeImageHeight"], $packet->clientData["CapeImageWidth"], base64_decode($packet->clientData["CapeData"] ?? "")), base64_decode($packet->clientData["SkinGeometryData"] ?? ""), - base64_decode($packet->clientData["AnimationData"] ?? ""), + base64_decode($packet->clientData["SkinAnimationData"] ?? ""), $packet->clientData["PremiumSkin"] ?? false, $packet->clientData["PersonaSkin"] ?? false, $packet->clientData["CapeOnClassicSkin"] ?? false, diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index c5f83858d..0e012e0cd 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -115,6 +115,7 @@ use function asort; use function assert; use function base64_encode; use function class_exists; +use function cli_set_process_title; use function count; use function define; use function explode; @@ -129,7 +130,6 @@ use function getmypid; use function getopt; use function gettype; use function implode; -use function ini_get; use function ini_set; use function is_array; use function is_bool; diff --git a/src/pocketmine/VersionInfo.php b/src/pocketmine/VersionInfo.php index 22776db77..a8e900838 100644 --- a/src/pocketmine/VersionInfo.php +++ b/src/pocketmine/VersionInfo.php @@ -30,6 +30,6 @@ const _VERSION_INFO_INCLUDED = true; const NAME = "PocketMine-MP"; -const BASE_VERSION = "3.10.2"; +const BASE_VERSION = "3.11.2"; const IS_DEVELOPMENT_BUILD = true; const BUILD_NUMBER = 0; diff --git a/src/pocketmine/entity/object/FallingBlock.php b/src/pocketmine/entity/object/FallingBlock.php index 87e408d1f..c96723a61 100644 --- a/src/pocketmine/entity/object/FallingBlock.php +++ b/src/pocketmine/entity/object/FallingBlock.php @@ -34,7 +34,6 @@ use pocketmine\level\Position; use pocketmine\nbt\tag\ByteTag; use pocketmine\nbt\tag\IntTag; use function abs; -use function floor; use function get_class; class FallingBlock extends Entity{ diff --git a/src/pocketmine/inventory/BaseInventory.php b/src/pocketmine/inventory/BaseInventory.php index b703442d6..cf2b7c0f7 100644 --- a/src/pocketmine/inventory/BaseInventory.php +++ b/src/pocketmine/inventory/BaseInventory.php @@ -46,7 +46,7 @@ abstract class BaseInventory implements Inventory{ protected $name; /** @var string */ protected $title; - /** @var \SplFixedArray|Item[] */ + /** @var \SplFixedArray|(Item|null)[] */ protected $slots; /** @var Player[] */ protected $viewers = []; diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index 2dbf4073d..3bd9c5a45 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -2442,7 +2442,7 @@ class Level implements ChunkManager, Metadatable{ * @param int $x * @param int $z * - * @return Chunk[] + * @return (Chunk|null)[] */ public function getAdjacentChunks(int $x, int $z) : array{ $result = []; diff --git a/src/pocketmine/level/format/io/LevelProvider.php b/src/pocketmine/level/format/io/LevelProvider.php index 2854f0e38..5fa272c17 100644 --- a/src/pocketmine/level/format/io/LevelProvider.php +++ b/src/pocketmine/level/format/io/LevelProvider.php @@ -71,7 +71,7 @@ interface LevelProvider{ * @param string $name * @param int $seed * @param string $generator - * @param array[] $options + * @param array $options */ public static function generate(string $path, string $name, int $seed, string $generator, array $options = []); diff --git a/src/pocketmine/level/format/io/leveldb/LevelDB.php b/src/pocketmine/level/format/io/leveldb/LevelDB.php index 6c3e5ec7d..10229f49c 100644 --- a/src/pocketmine/level/format/io/leveldb/LevelDB.php +++ b/src/pocketmine/level/format/io/leveldb/LevelDB.php @@ -33,7 +33,12 @@ use pocketmine\level\generator\GeneratorManager; use pocketmine\level\Level; use pocketmine\level\LevelException; use pocketmine\nbt\LittleEndianNBTStream; -use pocketmine\nbt\tag\{ByteTag, CompoundTag, FloatTag, IntTag, LongTag, StringTag}; +use pocketmine\nbt\tag\ByteTag; +use pocketmine\nbt\tag\CompoundTag; +use pocketmine\nbt\tag\FloatTag; +use pocketmine\nbt\tag\IntTag; +use pocketmine\nbt\tag\LongTag; +use pocketmine\nbt\tag\StringTag; use pocketmine\network\mcpe\protocol\ProtocolInfo; use pocketmine\utils\Binary; use pocketmine\utils\BinaryStream; diff --git a/src/pocketmine/level/generator/PopulationTask.php b/src/pocketmine/level/generator/PopulationTask.php index 007a6f87f..d061c415b 100644 --- a/src/pocketmine/level/generator/PopulationTask.php +++ b/src/pocketmine/level/generator/PopulationTask.php @@ -56,11 +56,9 @@ class PopulationTask extends AsyncTask{ } public function onRun(){ - /** @var SimpleChunkManager $manager */ $manager = $this->getFromThreadStore("generation.level{$this->levelId}.manager"); - /** @var Generator $generator */ $generator = $this->getFromThreadStore("generation.level{$this->levelId}.generator"); - if($manager === null or $generator === null){ + if(!($manager instanceof SimpleChunkManager) or !($generator instanceof Generator)){ $this->state = false; return; } diff --git a/src/pocketmine/network/mcpe/NetworkBinaryStream.php b/src/pocketmine/network/mcpe/NetworkBinaryStream.php index 0b6b8a097..b8cd85838 100644 --- a/src/pocketmine/network/mcpe/NetworkBinaryStream.php +++ b/src/pocketmine/network/mcpe/NetworkBinaryStream.php @@ -38,9 +38,9 @@ use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\IntTag; use pocketmine\network\mcpe\protocol\types\CommandOriginData; use pocketmine\network\mcpe\protocol\types\EntityLink; +use pocketmine\network\mcpe\protocol\types\SkinAnimation; use pocketmine\network\mcpe\protocol\types\SkinData; use pocketmine\network\mcpe\protocol\types\SkinImage; -use pocketmine\network\mcpe\protocol\types\SkinAnimation; use pocketmine\network\mcpe\protocol\types\StructureSettings; use pocketmine\utils\BinaryStream; use pocketmine\utils\UUID; diff --git a/src/pocketmine/network/mcpe/PlayerNetworkSessionAdapter.php b/src/pocketmine/network/mcpe/PlayerNetworkSessionAdapter.php index b064ae803..6b8297e75 100644 --- a/src/pocketmine/network/mcpe/PlayerNetworkSessionAdapter.php +++ b/src/pocketmine/network/mcpe/PlayerNetworkSessionAdapter.php @@ -67,7 +67,6 @@ use pocketmine\network\mcpe\protocol\ShowCreditsPacket; use pocketmine\network\mcpe\protocol\SpawnExperienceOrbPacket; use pocketmine\network\mcpe\protocol\TextPacket; use pocketmine\network\mcpe\protocol\types\SkinAdapterSingleton; -use pocketmine\network\mcpe\protocol\types\SkinData; use pocketmine\Player; use pocketmine\Server; use pocketmine\timings\Timings; diff --git a/src/pocketmine/network/mcpe/VerifyLoginTask.php b/src/pocketmine/network/mcpe/VerifyLoginTask.php index b56f8efe8..620cdae08 100644 --- a/src/pocketmine/network/mcpe/VerifyLoginTask.php +++ b/src/pocketmine/network/mcpe/VerifyLoginTask.php @@ -37,6 +37,7 @@ use function openssl_verify; use function ord; use function str_split; use function strlen; +use function strtr; use function time; use function wordwrap; use const OPENSSL_ALGO_SHA384; diff --git a/src/pocketmine/network/mcpe/protocol/AvailableActorIdentifiersPacket.php b/src/pocketmine/network/mcpe/protocol/AvailableActorIdentifiersPacket.php index e1c3baea7..933b212f7 100644 --- a/src/pocketmine/network/mcpe/protocol/AvailableActorIdentifiersPacket.php +++ b/src/pocketmine/network/mcpe/protocol/AvailableActorIdentifiersPacket.php @@ -26,7 +26,6 @@ namespace pocketmine\network\mcpe\protocol; #include use pocketmine\network\mcpe\NetworkSession; -use function base64_decode; use function file_get_contents; class AvailableActorIdentifiersPacket extends DataPacket{ diff --git a/src/pocketmine/network/mcpe/protocol/AvailableCommandsPacket.php b/src/pocketmine/network/mcpe/protocol/AvailableCommandsPacket.php index d4ef733e9..67c2e691a 100644 --- a/src/pocketmine/network/mcpe/protocol/AvailableCommandsPacket.php +++ b/src/pocketmine/network/mcpe/protocol/AvailableCommandsPacket.php @@ -31,6 +31,7 @@ use pocketmine\network\mcpe\protocol\types\CommandEnum; use pocketmine\network\mcpe\protocol\types\CommandEnumConstraint; use pocketmine\network\mcpe\protocol\types\CommandParameter; use pocketmine\utils\BinaryDataException; +use function array_search; use function count; use function dechex; diff --git a/src/pocketmine/network/mcpe/protocol/PlayerListPacket.php b/src/pocketmine/network/mcpe/protocol/PlayerListPacket.php index f73abb254..b15f7b413 100644 --- a/src/pocketmine/network/mcpe/protocol/PlayerListPacket.php +++ b/src/pocketmine/network/mcpe/protocol/PlayerListPacket.php @@ -27,7 +27,6 @@ namespace pocketmine\network\mcpe\protocol; use pocketmine\network\mcpe\NetworkSession; -use pocketmine\network\mcpe\protocol\types\SkinData; use pocketmine\network\mcpe\protocol\types\PlayerListEntry; use function count; diff --git a/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php b/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php index 242fe0695..0161fa03d 100644 --- a/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php +++ b/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php @@ -39,15 +39,15 @@ interface ProtocolInfo{ /** * Actual Minecraft: PE protocol version */ - public const CURRENT_PROTOCOL = 388; + public const CURRENT_PROTOCOL = 389; /** * Current Minecraft PE version reported by the server. This is usually the earliest currently supported version. */ - public const MINECRAFT_VERSION = 'v1.13.0'; + public const MINECRAFT_VERSION = 'v1.14.0'; /** * Version number sent to clients in ping responses. */ - public const MINECRAFT_VERSION_NETWORK = '1.13.0'; + public const MINECRAFT_VERSION_NETWORK = '1.14.0'; public const LOGIN_PACKET = 0x01; public const PLAY_STATUS_PACKET = 0x02; diff --git a/src/pocketmine/network/mcpe/protocol/ResourcePackChunkDataPacket.php b/src/pocketmine/network/mcpe/protocol/ResourcePackChunkDataPacket.php index 07d34affd..500a878c9 100644 --- a/src/pocketmine/network/mcpe/protocol/ResourcePackChunkDataPacket.php +++ b/src/pocketmine/network/mcpe/protocol/ResourcePackChunkDataPacket.php @@ -28,7 +28,6 @@ namespace pocketmine\network\mcpe\protocol; use pocketmine\network\mcpe\NetworkSession; -use function strlen; class ResourcePackChunkDataPacket extends DataPacket{ public const NETWORK_ID = ProtocolInfo::RESOURCE_PACK_CHUNK_DATA_PACKET; diff --git a/src/pocketmine/network/mcpe/protocol/StartGamePacket.php b/src/pocketmine/network/mcpe/protocol/StartGamePacket.php index 8d3611c8f..b3273ddd0 100644 --- a/src/pocketmine/network/mcpe/protocol/StartGamePacket.php +++ b/src/pocketmine/network/mcpe/protocol/StartGamePacket.php @@ -28,9 +28,7 @@ namespace pocketmine\network\mcpe\protocol; use pocketmine\math\Vector3; use pocketmine\nbt\NetworkLittleEndianNBTStream; -use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\ListTag; -use pocketmine\nbt\tag\StringTag; use pocketmine\network\mcpe\NetworkBinaryStream; use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\protocol\types\PlayerPermissions; diff --git a/src/pocketmine/network/mcpe/protocol/types/LegacySkinAdapter.php b/src/pocketmine/network/mcpe/protocol/types/LegacySkinAdapter.php index 676868b3e..e36a9493b 100644 --- a/src/pocketmine/network/mcpe/protocol/types/LegacySkinAdapter.php +++ b/src/pocketmine/network/mcpe/protocol/types/LegacySkinAdapter.php @@ -27,14 +27,16 @@ use pocketmine\entity\Skin; use function is_array; use function is_string; +use function json_decode; +use function json_encode; +use function random_bytes; +use function str_repeat; class LegacySkinAdapter implements SkinAdapter{ public function toSkinData(Skin $skin) : SkinData{ - $capeData = new SkinImage(32, 64, $skin->getCapeData()); - if($skin->getCapeData() === ""){ - $capeData = new SkinImage(0, 0, $skin->getCapeData()); - } + $capeData = $skin->getCapeData(); + $capeImage = $capeData === "" ? new SkinImage(0, 0, "") : new SkinImage(32, 64, $capeData); $geometryName = $skin->getGeometryName(); if($geometryName === ""){ $geometryName = "geometry.humanoid.custom"; @@ -43,13 +45,18 @@ class LegacySkinAdapter implements SkinAdapter{ $skin->getSkinId(), json_encode(["geometry" => ["default" => $geometryName]]), SkinImage::fromLegacy($skin->getSkinData()), [], - $capeData, + $capeImage, $skin->getGeometryData() ); } public function fromSkinData(SkinData $data) : Skin{ - $capeData = $data->getCapeImage()->getData(); + if($data->isPersona()){ + return new Skin("Standard_Custom", str_repeat(random_bytes(3) . "\xff", 2048)); + } + + $capeData = $data->isPersonaCapeOnClassic() ? "" : $data->getCapeImage()->getData(); + $geometryName = ""; $resourcePatch = json_decode($data->getResourcePatch(), true); if(is_array($resourcePatch["geometry"]) && is_string($resourcePatch["geometry"]["default"])){ @@ -57,11 +64,7 @@ class LegacySkinAdapter implements SkinAdapter{ }else{ //TODO: Kick for invalid skin } - if($data->isPersona()){ - return new Skin("Standard_Custom", str_repeat(random_bytes(3) . "\xff", 2048)); - }elseif($data->isPersonaCapeOnClassic()){ - $capeData = ""; - } + return new Skin($data->getSkinId(), $data->getSkinImage()->getData(), $capeData, $geometryName, $data->getGeometryData()); } } diff --git a/src/pocketmine/network/mcpe/protocol/types/PlayerListEntry.php b/src/pocketmine/network/mcpe/protocol/types/PlayerListEntry.php index ee46417a9..1393bf48b 100644 --- a/src/pocketmine/network/mcpe/protocol/types/PlayerListEntry.php +++ b/src/pocketmine/network/mcpe/protocol/types/PlayerListEntry.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace pocketmine\network\mcpe\protocol\types; -use pocketmine\entity\Skin; use pocketmine\utils\UUID; class PlayerListEntry{ diff --git a/src/pocketmine/network/mcpe/protocol/types/RuntimeBlockMapping.php b/src/pocketmine/network/mcpe/protocol/types/RuntimeBlockMapping.php index 5fedc28b6..5a1bd7141 100644 --- a/src/pocketmine/network/mcpe/protocol/types/RuntimeBlockMapping.php +++ b/src/pocketmine/network/mcpe/protocol/types/RuntimeBlockMapping.php @@ -28,8 +28,6 @@ use pocketmine\nbt\NBT; use pocketmine\nbt\NetworkLittleEndianNBTStream; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\ListTag; -use pocketmine\nbt\tag\StringTag; -use pocketmine\utils\BinaryDataException; use function file_get_contents; use function getmypid; use function json_decode; diff --git a/src/pocketmine/network/mcpe/protocol/types/SkinAdapterSingleton.php b/src/pocketmine/network/mcpe/protocol/types/SkinAdapterSingleton.php index f749752bb..b92cdf0df 100644 --- a/src/pocketmine/network/mcpe/protocol/types/SkinAdapterSingleton.php +++ b/src/pocketmine/network/mcpe/protocol/types/SkinAdapterSingleton.php @@ -25,7 +25,7 @@ namespace pocketmine\network\mcpe\protocol\types; /** * Accessor for SkinAdapter -*/ + */ class SkinAdapterSingleton{ /** @var SkinAdapter|null */ private static $skinAdapter = null; diff --git a/src/pocketmine/network/mcpe/protocol/types/SkinImage.php b/src/pocketmine/network/mcpe/protocol/types/SkinImage.php index 0c0dea6df..fcb0c966f 100644 --- a/src/pocketmine/network/mcpe/protocol/types/SkinImage.php +++ b/src/pocketmine/network/mcpe/protocol/types/SkinImage.php @@ -22,6 +22,7 @@ declare(strict_types=1); namespace pocketmine\network\mcpe\protocol\types; +use function strlen; class SkinImage{ @@ -33,6 +34,9 @@ class SkinImage{ private $data; public function __construct(int $height, int $width, string $data){ + if(($expected = $height * $width * 4) !== ($actual = strlen($data))){ + throw new \InvalidArgumentException("Data should be exactly $expected bytes, got $actual bytes"); + } $this->height = $height; $this->width = $width; $this->data = $data; diff --git a/src/pocketmine/permission/BanEntry.php b/src/pocketmine/permission/BanEntry.php index 7c8cbf3ab..addf5287a 100644 --- a/src/pocketmine/permission/BanEntry.php +++ b/src/pocketmine/permission/BanEntry.php @@ -136,10 +136,10 @@ class BanEntry{ /** * @param string $date * - * @return \DateTime|null + * @return \DateTime * @throws \RuntimeException */ - private static function parseDate(string $date) : ?\DateTime{ + private static function parseDate(string $date) : \DateTime{ $datetime = \DateTime::createFromFormat(self::$format, $date); if(!($datetime instanceof \DateTime)){ throw new \RuntimeException("Error parsing date for BanEntry: " . implode(", ", \DateTime::getLastErrors()["errors"])); diff --git a/src/pocketmine/plugin/PluginDescription.php b/src/pocketmine/plugin/PluginDescription.php index 7cdd1e95a..153c37752 100644 --- a/src/pocketmine/plugin/PluginDescription.php +++ b/src/pocketmine/plugin/PluginDescription.php @@ -38,6 +38,7 @@ use function strlen; use function strtoupper; use function substr; use function version_compare; +use function yaml_parse; class PluginDescription{ private $map; diff --git a/src/pocketmine/plugin/PluginManager.php b/src/pocketmine/plugin/PluginManager.php index 6c1c8bead..6c77ddc2f 100644 --- a/src/pocketmine/plugin/PluginManager.php +++ b/src/pocketmine/plugin/PluginManager.php @@ -40,6 +40,7 @@ use pocketmine\timings\TimingsHandler; use pocketmine\utils\Utils; use function array_intersect; use function array_map; +use function array_merge; use function array_pad; use function class_exists; use function count; diff --git a/src/pocketmine/resourcepacks/ZippedResourcePack.php b/src/pocketmine/resourcepacks/ZippedResourcePack.php index 0364ccd37..6a12ad12b 100644 --- a/src/pocketmine/resourcepacks/ZippedResourcePack.php +++ b/src/pocketmine/resourcepacks/ZippedResourcePack.php @@ -34,6 +34,7 @@ use function filesize; use function fopen; use function fread; use function fseek; +use function gettype; use function hash_file; use function implode; diff --git a/src/pocketmine/resources/vanilla b/src/pocketmine/resources/vanilla index a38b42788..cc132c80d 160000 --- a/src/pocketmine/resources/vanilla +++ b/src/pocketmine/resources/vanilla @@ -1 +1 @@ -Subproject commit a38b42788883fa2094f67874f15594044be1ac4d +Subproject commit cc132c80dd9d76a44e4b0a360e85e8e28bba8956 diff --git a/src/pocketmine/timings/Timings.php b/src/pocketmine/timings/Timings.php index a8d1e646c..5192728f5 100644 --- a/src/pocketmine/timings/Timings.php +++ b/src/pocketmine/timings/Timings.php @@ -31,6 +31,8 @@ use pocketmine\tile\Tile; use function dechex; abstract class Timings{ + /** @var bool */ + private static $initialized = false; /** @var TimingsHandler */ public static $fullTickTimer; @@ -104,9 +106,10 @@ abstract class Timings{ public static $pluginTaskTimingMap = []; public static function init(){ - if(self::$serverTickTimer instanceof TimingsHandler){ + if(self::$initialized){ return; } + self::$initialized = true; self::$fullTickTimer = new TimingsHandler("Full Server Tick"); self::$serverTickTimer = new TimingsHandler("** Full Server Tick", self::$fullTickTimer); diff --git a/src/pocketmine/timings/TimingsHandler.php b/src/pocketmine/timings/TimingsHandler.php index 4018ee730..87a6100c5 100644 --- a/src/pocketmine/timings/TimingsHandler.php +++ b/src/pocketmine/timings/TimingsHandler.php @@ -168,7 +168,7 @@ class TimingsHandler{ public function stopTiming(){ if(self::$enabled){ - if(--$this->timingDepth !== 0 or $this->start === 0){ + if(--$this->timingDepth !== 0 or $this->start == 0){ return; } diff --git a/src/pocketmine/utils/Utils.php b/src/pocketmine/utils/Utils.php index 578800a47..86f0977e6 100644 --- a/src/pocketmine/utils/Utils.php +++ b/src/pocketmine/utils/Utils.php @@ -57,6 +57,7 @@ use function is_object; use function is_readable; use function is_string; use function json_decode; +use function ltrim; use function ob_end_clean; use function ob_get_contents; use function ob_start; @@ -68,6 +69,7 @@ use function preg_match; use function preg_match_all; use function preg_replace; use function rmdir; +use function rtrim; use function scandir; use function sha1; use function spl_object_hash; @@ -78,6 +80,7 @@ use function stripos; use function strlen; use function strpos; use function strtolower; +use function strtr; use function substr; use function sys_get_temp_dir; use function trim; diff --git a/tests/phpstan/configs/debug-const-checks.neon b/tests/phpstan/configs/debug-const-checks.neon new file mode 100644 index 000000000..bfe2fa5c6 --- /dev/null +++ b/tests/phpstan/configs/debug-const-checks.neon @@ -0,0 +1,21 @@ +parameters: + ignoreErrors: + - + message: "#^If condition is always true\\.$#" + count: 1 + path: ../../../src/pocketmine/Server.php + + - + message: "#^Ternary operator condition is always true\\.$#" + count: 1 + path: ../../../src/pocketmine/Server.php + + - + message: "#^If condition is always false\\.$#" + count: 1 + path: ../../../src/pocketmine/updater/AutoUpdater.php + + - + message: "#^Negated boolean expression is always false\\.$#" + count: 1 + path: ../../../src/pocketmine/updater/AutoUpdater.php diff --git a/tests/phpstan/configs/phpstan-bugs.neon b/tests/phpstan/configs/phpstan-bugs.neon index 696fcc8ab..2efbbb37b 100644 --- a/tests/phpstan/configs/phpstan-bugs.neon +++ b/tests/phpstan/configs/phpstan-bugs.neon @@ -27,7 +27,45 @@ parameters: path: ../../../src/pocketmine/MemoryManager.php - - message: "#^Array \\(array\\) does not accept key int\\.$#" + message: "#^Comparison operation \"\\>\\=\" between 0 and 2 is always false\\.$#" count: 1 - path: ../../../src/pocketmine/plugin/PluginDescription.php + path: ../../../src/pocketmine/block/Liquid.php + - + #adjacentSources comparison FP + message: "#^If condition is always false\\.$#" + count: 1 + path: ../../../src/pocketmine/block/Liquid.php + + - + #$class::NETWORK_ID false positive + message: "#^Strict comparison using \\!\\=\\= between \\-1 and \\-1 will always evaluate to false\\.$#" + count: 1 + path: ../../../src/pocketmine/entity/Entity.php + + - + message: "#^Call to function assert\\(\\) with false and 'unknown hit type' will always evaluate to false\\.$#" + count: 1 + path: ../../../src/pocketmine/entity/projectile/Projectile.php + + - + message: "#^Strict comparison using \\=\\=\\= between int\\ and 4 will always evaluate to false\\.$#" + count: 1 + path: ../../../src/pocketmine/level/Level.php + + - + message: "#^Instanceof between int and PharFileInfo will always evaluate to false\\.$#" + count: 1 + path: ../../../src/pocketmine/plugin/PharPluginLoader.php + + - + #ReflectionFunction::getClosureThis() should be nullable + message: "#^Else branch is unreachable because ternary operator condition is always true\\.$#" + count: 1 + path: ../../../src/pocketmine/utils/Utils.php + + - + #ReflectionFunction::getClosureScopeClass() should be nullable + message: "#^Unreachable statement \\- code above always terminates\\.$#" + count: 1 + path: ../../../src/pocketmine/utils/Utils.php diff --git a/tests/phpstan/configs/runtime-type-checks.neon b/tests/phpstan/configs/runtime-type-checks.neon new file mode 100644 index 000000000..7d48cacd9 --- /dev/null +++ b/tests/phpstan/configs/runtime-type-checks.neon @@ -0,0 +1,31 @@ +parameters: + ignoreErrors: + - + #::add() / ::remove() thread parameter + message: "#^If condition is always true\\.$#" + count: 2 + path: ../../../src/pocketmine/ThreadManager.php + + - + #::get() tags parameter + message: "#^If condition is always false\\.$#" + count: 1 + path: ../../../src/pocketmine/item/ItemFactory.php + + - + #::get() tags parameter + message: "#^Strict comparison using \\!\\=\\= between null and null will always evaluate to false\\.$#" + count: 1 + path: ../../../src/pocketmine/item/ItemFactory.php + + - + #::get() tags parameter + message: "#^Else branch is unreachable because ternary operator condition is always true\\.$#" + count: 1 + path: ../../../src/pocketmine/item/ItemFactory.php + + - + #->sendBlocks() blocks parameter + message: "#^Else branch is unreachable because ternary operator condition is always true\\.$#" + count: 2 + path: ../../../src/pocketmine/level/Level.php diff --git a/tests/travis.sh b/tests/travis.sh index ba90d4a19..ee5053262 100755 --- a/tests/travis.sh +++ b/tests/travis.sh @@ -21,7 +21,7 @@ if [ $? -ne 0 ]; then exit 1 fi -[ ! -f phpstan.phar ] && echo "Downloading PHPStan..." && curl -sSLO https://github.com/phpstan/phpstan/releases/download/0.12.0/phpstan.phar +[ ! -f phpstan.phar ] && echo "Downloading PHPStan..." && curl -sSLO https://github.com/phpstan/phpstan/releases/download/0.12.2/phpstan.phar "$PHP_BINARY" phpstan.phar analyze --no-progress --memory-limit=2G || exit 1 echo "PHPStan scan succeeded"