diff --git a/build/php b/build/php index f292501a7..cf79c0172 160000 --- a/build/php +++ b/build/php @@ -1 +1 @@ -Subproject commit f292501a703352ab793b07b7861f3e1b3860ed86 +Subproject commit cf79c0172283a0a26f2c3695af260d100e0fdabd diff --git a/changelogs/4.7.md b/changelogs/4.7.md index 950158cd3..bdbdf5249 100644 --- a/changelogs/4.7.md +++ b/changelogs/4.7.md @@ -29,3 +29,18 @@ Released 16th August 2022. - Fixed crash when processing player skins with invalid geometry data. - Fixed spectator players being able to pick blocks using mousewheel click. - Improved supporting requirements for sugarcane. + +# 4.7.3 +Released 22nd August 2022. + +## General +- Added complete translations for Spanish and Vietnamese. +- All continuous integration (static analysis, unit tests, integration tests) are now performed on PHP 8.1 as well as 8.0. +- InventoryTransaction now verifies that stack sizes of items after the transaction don't exceed the maximum stack size of the item type or the containing inventory. + +## Fixes +- Fixed Normal generator crash on PHP 8.1. +- Fixed a race condition during async worker shutdown that could lead to tasks executing in the wrong order. This (very rarely) led to a crash in `PopulationTask` due to its preceding `GeneratorRegisterTask` not being executed. +- Fixed `/give` accepting negative amounts or amounts larger than 32767 (vanilla max). +- Fixed placement conditions for vines (no longer able to be placed on the side of cacti). +- Fixed incorrect documentation of `SignText::__construct()`. diff --git a/changelogs/4.8.md b/changelogs/4.8.md new file mode 100644 index 000000000..4f1cde520 --- /dev/null +++ b/changelogs/4.8.md @@ -0,0 +1,14 @@ +**For Minecraft: Bedrock Edition 1.19.21** + +### Note about API versions +Plugins which don't touch the protocol and compatible with any previous 4.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. + +# 4.8.0 +Released 9th August 2022. + +## General +- Added support for Minecraft: Bedrock Edition 1.19.21. +- Removed support for older versions. diff --git a/composer.json b/composer.json index 5bd92f912..206fce6d5 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,7 @@ "pocketmine/bedrock-block-upgrade-schema": "dev-master@dev", "pocketmine/bedrock-data": "dev-modern-world-support@dev", "pocketmine/bedrock-item-upgrade-schema": "dev-master", - "pocketmine/bedrock-protocol": "~12.0.0+bedrock-1.19.20", + "pocketmine/bedrock-protocol": "~12.2.0+bedrock-1.19.20", "pocketmine/binaryutils": "^0.2.1", "pocketmine/callback-validator": "^1.0.2", "pocketmine/classloader": "^0.2.0", diff --git a/composer.lock b/composer.lock index fd93078e5..9bfb5608c 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "2466f7f325b36cce50ce002854e85f89", + "content-hash": "5e91ab5b70093a7566adf2d1be7a7dbc", "packages": [ { "name": "adhocore/json-comment", @@ -325,16 +325,16 @@ }, { "name": "pocketmine/bedrock-protocol", - "version": "12.0.0+bedrock-1.19.20", + "version": "12.2.0+bedrock-1.19.21", "source": { "type": "git", "url": "https://github.com/pmmp/BedrockProtocol.git", - "reference": "c2778039544fa0c7c5bd3af7963149e7552f4215" + "reference": "d1b3e83f77e2c6628b64793485260cddc55d92e3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/c2778039544fa0c7c5bd3af7963149e7552f4215", - "reference": "c2778039544fa0c7c5bd3af7963149e7552f4215", + "url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/d1b3e83f77e2c6628b64793485260cddc55d92e3", + "reference": "d1b3e83f77e2c6628b64793485260cddc55d92e3", "shasum": "" }, "require": { @@ -366,9 +366,9 @@ "description": "An implementation of the Minecraft: Bedrock Edition protocol in PHP", "support": { "issues": "https://github.com/pmmp/BedrockProtocol/issues", - "source": "https://github.com/pmmp/BedrockProtocol/tree/bedrock-1.19.20" + "source": "https://github.com/pmmp/BedrockProtocol/tree/12.2.0+bedrock-1.19.21" }, - "time": "2022-08-09T17:57:29+00:00" + "time": "2022-08-24T18:47:37+00:00" }, { "name": "pocketmine/binaryutils", diff --git a/src/block/Vine.php b/src/block/Vine.php index 6fa3ee8f1..9edeca3c4 100644 --- a/src/block/Vine.php +++ b/src/block/Vine.php @@ -105,7 +105,7 @@ class Vine extends Flowable{ } public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ - if(!$blockClicked->isSolid() || Facing::axis($face) === Axis::Y){ + if(!$blockClicked->isFullCube() || Facing::axis($face) === Axis::Y){ return false; } diff --git a/src/block/utils/SignText.php b/src/block/utils/SignText.php index cdde8f5eb..27e8b5c5e 100644 --- a/src/block/utils/SignText.php +++ b/src/block/utils/SignText.php @@ -42,7 +42,7 @@ class SignText{ private bool $glowing; /** - * @param string[]|null $lines index-sensitive; omitting an index will leave it unchanged + * @param string[]|null $lines index-sensitive; keys 0-3 will be used, regardless of array order * * @throws \InvalidArgumentException if the array size is greater than 4 * @throws \InvalidArgumentException if invalid keys (out of bounds or string) are found in the array diff --git a/src/command/defaults/GiveCommand.php b/src/command/defaults/GiveCommand.php index 2d465c74c..ed3e5df42 100644 --- a/src/command/defaults/GiveCommand.php +++ b/src/command/defaults/GiveCommand.php @@ -71,7 +71,11 @@ class GiveCommand extends VanillaCommand{ if(!isset($args[2])){ $item->setCount($item->getMaxStackSize()); }else{ - $item->setCount((int) $args[2]); + $count = $this->getBoundedInt($sender, $args[2], 1, 32767); + if($count === null){ + return true; + } + $item->setCount($count); } if(isset($args[3])){ diff --git a/src/command/defaults/VersionCommand.php b/src/command/defaults/VersionCommand.php index 6c579cdda..0200c4ff3 100644 --- a/src/command/defaults/VersionCommand.php +++ b/src/command/defaults/VersionCommand.php @@ -32,9 +32,7 @@ use pocketmine\utils\TextFormat; use pocketmine\utils\Utils; use pocketmine\VersionInfo; use function count; -use function function_exists; use function implode; -use function opcache_get_status; use function sprintf; use function stripos; use function strtolower; @@ -67,16 +65,10 @@ class VersionCommand extends VanillaCommand{ )); $sender->sendMessage(KnownTranslationFactory::pocketmine_command_version_phpVersion(PHP_VERSION)); - if( - function_exists('opcache_get_status') && - ($opcacheStatus = opcache_get_status(false)) !== false && - isset($opcacheStatus["jit"]["on"]) - ){ - $jit = $opcacheStatus["jit"]; - if($jit["on"] === true){ - $jitStatus = KnownTranslationFactory::pocketmine_command_version_phpJitEnabled( - sprintf("CRTO: %s%s%s%s", $jit["opt_flags"] >> 2, $jit["opt_flags"] & 0x03, $jit["kind"], $jit["opt_level"]) - ); + $jitMode = Utils::getOpcacheJitMode(); + if($jitMode !== null){ + if($jitMode !== 0){ + $jitStatus = KnownTranslationFactory::pocketmine_command_version_phpJitEnabled(sprintf("CRTO: %d", $jitMode)); }else{ $jitStatus = KnownTranslationFactory::pocketmine_command_version_phpJitDisabled(); } diff --git a/src/crash/CrashDump.php b/src/crash/CrashDump.php index 101e35201..e724ea217 100644 --- a/src/crash/CrashDump.php +++ b/src/crash/CrashDump.php @@ -164,6 +164,8 @@ class CrashDump{ } $this->data->extensions = $extensions; + $this->data->jit_mode = Utils::getOpcacheJitMode(); + if($this->server->getConfigGroup()->getPropertyBool("auto-report.send-phpinfo", true)){ ob_start(); phpinfo(); diff --git a/src/crash/CrashDumpData.php b/src/crash/CrashDumpData.php index 264f67d67..0f5358be5 100644 --- a/src/crash/CrashDumpData.php +++ b/src/crash/CrashDumpData.php @@ -66,6 +66,8 @@ final class CrashDumpData implements \JsonSerializable{ */ public array $extensions = []; + public ?int $jit_mode = null; + public string $phpinfo = ""; public CrashDumpDataGeneral $general; diff --git a/src/inventory/transaction/action/DropItemAction.php b/src/inventory/transaction/action/DropItemAction.php index 896d8fbe9..636317fcf 100644 --- a/src/inventory/transaction/action/DropItemAction.php +++ b/src/inventory/transaction/action/DropItemAction.php @@ -42,6 +42,9 @@ class DropItemAction extends InventoryAction{ if($this->targetItem->isNull()){ throw new TransactionValidationException("Cannot drop an empty itemstack"); } + if($this->targetItem->getCount() > $this->targetItem->getMaxStackSize()){ + throw new TransactionValidationException("Target item exceeds item type max stack size"); + } } public function onPreExecute(Player $source) : bool{ diff --git a/src/inventory/transaction/action/SlotChangeAction.php b/src/inventory/transaction/action/SlotChangeAction.php index cee364ed0..453f0c4d2 100644 --- a/src/inventory/transaction/action/SlotChangeAction.php +++ b/src/inventory/transaction/action/SlotChangeAction.php @@ -68,6 +68,12 @@ class SlotChangeAction extends InventoryAction{ if(!$this->inventory->getItem($this->inventorySlot)->equalsExact($this->sourceItem)){ throw new TransactionValidationException("Slot does not contain expected original item"); } + if($this->targetItem->getCount() > $this->targetItem->getMaxStackSize()){ + throw new TransactionValidationException("Target item exceeds item type max stack size"); + } + if($this->targetItem->getCount() > $this->inventory->getMaxStackSize()){ + throw new TransactionValidationException("Target item exceeds inventory max stack size"); + } } /** diff --git a/src/thread/Worker.php b/src/thread/Worker.php index 1315202b1..572da3c67 100644 --- a/src/thread/Worker.php +++ b/src/thread/Worker.php @@ -56,7 +56,9 @@ abstract class Worker extends \Worker{ $this->isKilled = true; if(!$this->isShutdown()){ - while($this->unstack() !== null); + $this->synchronized(function() : void{ + while($this->unstack() !== null); + }); $this->notify(); $this->shutdown(); } diff --git a/src/utils/Utils.php b/src/utils/Utils.php index 03377b6c4..8d27c9861 100644 --- a/src/utils/Utils.php +++ b/src/utils/Utils.php @@ -69,6 +69,7 @@ use function mb_check_encoding; use function ob_end_clean; use function ob_get_contents; use function ob_start; +use function opcache_get_status; use function ord; use function php_uname; use function phpversion; @@ -486,8 +487,8 @@ final class Utils{ */ public static function currentTrace(int $skipFrames = 0) : array{ ++$skipFrames; //omit this frame from trace, in addition to other skipped frames - if(function_exists("xdebug_get_function_stack")){ - $trace = array_reverse(xdebug_get_function_stack()); + if(function_exists("xdebug_get_function_stack") && count($trace = @xdebug_get_function_stack()) !== 0){ + $trace = array_reverse($trace); }else{ $e = new \Exception(); $trace = $e->getTrace(); @@ -634,4 +635,30 @@ final class Utils{ public static function checkLocationNotInfOrNaN(Location $location) : void{ self::checkVector3NotInfOrNaN($location); } + + /** + * Returns an integer describing the current OPcache JIT setting. + * @see https://www.php.net/manual/en/opcache.configuration.php#ini.opcache.jit + */ + public static function getOpcacheJitMode() : ?int{ + if( + function_exists('opcache_get_status') && + ($opcacheStatus = opcache_get_status(false)) !== false && + isset($opcacheStatus["jit"]["on"]) + ){ + $jit = $opcacheStatus["jit"]; + if($jit["on"] === true){ + return (($jit["opt_flags"] >> 2) * 1000) + + (($jit["opt_flags"] & 0x03) * 100) + + ($jit["kind"] * 10) + + $jit["opt_level"]; + } + + //jit available, but disabled + return 0; + } + + //jit not available + return null; + } } diff --git a/tests/phpstan/configs/phpstan-bugs.neon b/tests/phpstan/configs/phpstan-bugs.neon index bfb3b1734..dcfda66bc 100644 --- a/tests/phpstan/configs/phpstan-bugs.neon +++ b/tests/phpstan/configs/phpstan-bugs.neon @@ -35,11 +35,6 @@ parameters: count: 1 path: ../../../src/network/mcpe/handler/InGamePacketHandler.php - - - message: "#^Negated boolean expression is always true\\.$#" - count: 1 - path: ../../../src/network/mcpe/handler/InGamePacketHandler.php - - message: "#^Property pocketmine\\\\network\\\\mcpe\\\\raklib\\\\PthreadsChannelWriter\\:\\:\\$buffer is never read, only written\\.$#" count: 1