Compare commits

..

13 Commits

Author SHA1 Message Date
54ae4d0ea2 Release 4.20.0 2023-04-26 23:15:34 +01:00
0d21e591d1 Support sign editing UI in 1.19.80, with APIs to allow plugins to use it
this doesn't support editing the rear side of a sign, since the 1.12 format doesn't allow us to represent the rear text, and it would necessitate API breaks to support anyway.

However, we can quite trivially support APIs for the sign GUI, which plugins can use to enable editing signs. PocketMine-MP doesn't currently permit this, since it's currently an experimental feature in 1.20, but plugins can simply use Player->openSignEditor() to mimic it.

This is, however, a byproduct of the fact that APIs needed to be added in order to facilitate the use of OpenSignPacket in 1.19.80.
2023-04-26 22:55:05 +01:00
408616723c Changes for 1.19.80 2023-04-26 22:52:02 +01:00
b162d688a3 CI: use php-cs-fixer 3.16 2023-04-26 16:05:06 +01:00
3b09c3a48a actions: updated setup-php-action to pmmp/setup-php-action@c7fb29d835 2023-04-26 14:40:39 +01:00
87781cff4d Update GitHub Actions PHP versions 2023-04-26 14:38:40 +01:00
db0cf4bb5a Update composer dependencies 2023-04-26 14:35:05 +01:00
a4f2b99ed5 InGamePacketHandler: queue slots for syncing if they appear in requestChangedSlots
this is essentially a prediction without the actual predicted item. We have to sync these regardless of what happens.

fixes #5708
2023-04-24 14:06:29 +01:00
3ecc980bc4 ÂInventoryManagerEntry: fixed incorrect PHPDoc type 2023-04-24 13:42:11 +01:00
107b56154b ItemStackRequestExecutor: fixed stonecutter recipes
this uses the same dodgy hack used by CraftingTransaction, which assumes that getResultsFor() does not care about the crafting inputs.

While this is currently OK, since none of the currently-implemented recipes care about inputs anyway, it will become a problem when we implement shulker box recipes, so this needs to be addressed.

However, it can't be addressed without BC breaks, so this will have to be dealt with in PM5.

closes #5715
2023-04-24 13:35:00 +01:00
f86fde064d CraftingManager: fixed uninitialized field
I'm having deja vu about this ...
2023-04-24 12:34:34 +01:00
84a16ce69a HandlerList: fixed crash on getting unused priority
these sub-arrays are no longer allocated if no handlers are registered.

fixes #5713
2023-04-21 16:19:15 +01:00
d06d3bc871 4.19.4 is next 2023-04-21 15:53:05 +01:00
15 changed files with 192 additions and 82 deletions

View File

@ -13,11 +13,11 @@ jobs:
strategy:
matrix:
image: [ubuntu-20.04]
php: [8.0.28, 8.1.16, 8.2.3]
php: [8.0.28, 8.1.18, 8.2.5]
steps:
- name: Build and prepare PHP cache
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
uses: pmmp/setup-php-action@c7fb29d83535320922068087c7285bdedbbfa3c2
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
@ -32,13 +32,13 @@ jobs:
fail-fast: false
matrix:
image: [ubuntu-20.04]
php: [8.0.28, 8.1.16, 8.2.3]
php: [8.0.28, 8.1.18, 8.2.5]
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
uses: pmmp/setup-php-action@c7fb29d83535320922068087c7285bdedbbfa3c2
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
@ -71,13 +71,13 @@ jobs:
fail-fast: false
matrix:
image: [ubuntu-20.04]
php: [8.0.28, 8.1.16, 8.2.3]
php: [8.0.28, 8.1.18, 8.2.5]
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
uses: pmmp/setup-php-action@c7fb29d83535320922068087c7285bdedbbfa3c2
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
@ -110,7 +110,7 @@ jobs:
fail-fast: false
matrix:
image: [ubuntu-20.04]
php: [8.0.28, 8.1.16, 8.2.3]
php: [8.0.28, 8.1.18, 8.2.5]
steps:
- uses: actions/checkout@v3
@ -118,7 +118,7 @@ jobs:
submodules: true
- name: Setup PHP
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
uses: pmmp/setup-php-action@c7fb29d83535320922068087c7285bdedbbfa3c2
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
@ -151,13 +151,13 @@ jobs:
fail-fast: false
matrix:
image: [ubuntu-20.04]
php: [8.0.28, 8.1.16, 8.2.3]
php: [8.0.28, 8.1.18, 8.2.5]
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
uses: pmmp/setup-php-action@c7fb29d83535320922068087c7285bdedbbfa3c2
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
@ -206,7 +206,7 @@ jobs:
uses: shivammathur/setup-php@2.24.0
with:
php-version: 8.0
tools: php-cs-fixer:3.11
tools: php-cs-fixer:3.16
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

36
changelogs/4.20.md Normal file
View File

@ -0,0 +1,36 @@
**For Minecraft: Bedrock Edition 1.19.80**
### Note about API versions
Plugins which don't touch the `pocketmine\network\mcpe` namespace are 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 `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.17.x directly to 4.20.x, please also read the following changelogs, as the interim releases contain important changes:
- [4.18.0](https://github.com/pmmp/PocketMine-MP/blob/4.20.0/changelogs/4.18.md#4180) - major performance improvements, internal network changes, minor API additions
- [4.19.0](https://github.com/pmmp/PocketMine-MP/blob/4.20.0/changelogs/4.19.md#4190) - minor performance improvements, improved timings system, minor API additions
# 4.20.0
Released 26th April 2023.
## General
- Added support for Minecraft: Bedrock Edition 1.19.80.
- Removed support for older versions.
## Fixes
- Fixed packet processing error when attempting to use a stonecutter.
- Fixed armor slots containing ghost items when cancelling right-click to equip armor.
- Fixed crash in `HandlerList->getListenersByPriority()` when no listeners are registered at the given priority.
## API
### `pocketmine\block`
- The following API methods have been added:
- `public BaseSign->getEditorEntityRuntimeId() : int` - returns the entity runtime ID of the player currently editing this sign, or `null` if none
- `public BaseSign->setEditorEntityRuntimeId(?int $editorEntityRuntimeId) : $this` - sets the entity runtime ID of the player currently editing this sign
### `pocketmine\player`
- The following API methods have been added:
- `public Player->openSignEditor(Vector3 $position) : void` - opens the client-side sign editor GUI for the given position

View File

@ -34,10 +34,10 @@
"adhocore/json-comment": "^1.1",
"fgrosse/phpasn1": "^2.3",
"netresearch/jsonmapper": "^4.0",
"pocketmine/bedrock-block-upgrade-schema": "~1.1.1+bedrock-1.19.70",
"pocketmine/bedrock-data": "~2.1.1+bedrock-1.19.70",
"pocketmine/bedrock-item-upgrade-schema": "~1.1.0+bedrock-1.19.70",
"pocketmine/bedrock-protocol": "~20.1.1+bedrock-1.19.70",
"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",
"pocketmine/binaryutils": "^0.2.1",
"pocketmine/callback-validator": "^1.0.2",
"pocketmine/classloader": "^0.2.0",
@ -56,7 +56,7 @@
"webmozart/path-util": "^2.3"
},
"require-dev": {
"phpstan/phpstan": "1.10.13",
"phpstan/phpstan": "1.10.14",
"phpstan/phpstan-phpunit": "^1.1.0",
"phpstan/phpstan-strict-rules": "^1.2.0",
"phpunit/phpunit": "^9.2"

91
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": "d819da2b086b38c4dd2a5028084e251c",
"content-hash": "7ca2d4ed0987ac17cf615d67945f5687",
"packages": [
{
"name": "adhocore/json-comment",
@ -67,26 +67,25 @@
},
{
"name": "brick/math",
"version": "0.10.2",
"version": "0.11.0",
"source": {
"type": "git",
"url": "https://github.com/brick/math.git",
"reference": "459f2781e1a08d52ee56b0b1444086e038561e3f"
"reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/brick/math/zipball/459f2781e1a08d52ee56b0b1444086e038561e3f",
"reference": "459f2781e1a08d52ee56b0b1444086e038561e3f",
"url": "https://api.github.com/repos/brick/math/zipball/0ad82ce168c82ba30d1c01ec86116ab52f589478",
"reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": "^7.4 || ^8.0"
"php": "^8.0"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.2",
"phpunit/phpunit": "^9.0",
"vimeo/psalm": "4.25.0"
"vimeo/psalm": "5.0.0"
},
"type": "library",
"autoload": {
@ -111,7 +110,7 @@
],
"support": {
"issues": "https://github.com/brick/math/issues",
"source": "https://github.com/brick/math/tree/0.10.2"
"source": "https://github.com/brick/math/tree/0.11.0"
},
"funding": [
{
@ -119,7 +118,7 @@
"type": "github"
}
],
"time": "2022-08-10T22:54:19+00:00"
"time": "2023-01-15T23:15:59+00:00"
},
{
"name": "fgrosse/phpasn1",
@ -250,16 +249,16 @@
},
{
"name": "pocketmine/bedrock-block-upgrade-schema",
"version": "1.1.1",
"version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockBlockUpgradeSchema.git",
"reference": "e0540343e649a92126a1d4071ec401a811416c76"
"reference": "1c07ced86be7d185551082441b5a2b9b7fbd6b21"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/e0540343e649a92126a1d4071ec401a811416c76",
"reference": "e0540343e649a92126a1d4071ec401a811416c76",
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/1c07ced86be7d185551082441b5a2b9b7fbd6b21",
"reference": "1c07ced86be7d185551082441b5a2b9b7fbd6b21",
"shasum": ""
},
"type": "library",
@ -270,22 +269,22 @@
"description": "Schemas describing how to upgrade saved block data in older Minecraft: Bedrock Edition world saves",
"support": {
"issues": "https://github.com/pmmp/BedrockBlockUpgradeSchema/issues",
"source": "https://github.com/pmmp/BedrockBlockUpgradeSchema/tree/1.1.1"
"source": "https://github.com/pmmp/BedrockBlockUpgradeSchema/tree/2.1.0"
},
"time": "2023-03-08T23:45:59+00:00"
"time": "2023-04-19T17:58:49+00:00"
},
{
"name": "pocketmine/bedrock-data",
"version": "2.1.1+bedrock-1.19.70",
"version": "2.2.0+bedrock-1.19.80",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockData.git",
"reference": "cba0567bcb25f987f2712092f8d662056719e82d"
"reference": "33dd83601442b377af42ac91473278243cafd576"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/cba0567bcb25f987f2712092f8d662056719e82d",
"reference": "cba0567bcb25f987f2712092f8d662056719e82d",
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/33dd83601442b377af42ac91473278243cafd576",
"reference": "33dd83601442b377af42ac91473278243cafd576",
"shasum": ""
},
"type": "library",
@ -296,22 +295,22 @@
"description": "Blobs of data generated from Minecraft: Bedrock Edition, used by PocketMine-MP",
"support": {
"issues": "https://github.com/pmmp/BedrockData/issues",
"source": "https://github.com/pmmp/BedrockData/tree/2.1.1+bedrock-1.19.70"
"source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.19.80"
},
"time": "2023-03-14T18:03:19+00:00"
"time": "2023-04-26T20:00:35+00:00"
},
{
"name": "pocketmine/bedrock-item-upgrade-schema",
"version": "1.1.0",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockItemUpgradeSchema.git",
"reference": "aab89a1f121a0c127557a4a0cf981330301c9c45"
"reference": "dd804c3f2b1e8990434812627e62eb5bde9670a5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/aab89a1f121a0c127557a4a0cf981330301c9c45",
"reference": "aab89a1f121a0c127557a4a0cf981330301c9c45",
"url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/dd804c3f2b1e8990434812627e62eb5bde9670a5",
"reference": "dd804c3f2b1e8990434812627e62eb5bde9670a5",
"shasum": ""
},
"type": "library",
@ -322,22 +321,22 @@
"description": "JSON schemas for upgrading items found in older Minecraft: Bedrock world saves",
"support": {
"issues": "https://github.com/pmmp/BedrockItemUpgradeSchema/issues",
"source": "https://github.com/pmmp/BedrockItemUpgradeSchema/tree/1.1.0"
"source": "https://github.com/pmmp/BedrockItemUpgradeSchema/tree/1.2.0"
},
"time": "2023-03-08T22:27:13+00:00"
"time": "2023-04-19T18:16:14+00:00"
},
{
"name": "pocketmine/bedrock-protocol",
"version": "20.1.2+bedrock-1.19.70",
"version": "21.0.1+bedrock-1.19.80",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockProtocol.git",
"reference": "2787c531039b3d92fa3ec92f28b95158dc24b915"
"reference": "981ea2e76e207a25c1361df858c639feba5cf348"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/2787c531039b3d92fa3ec92f28b95158dc24b915",
"reference": "2787c531039b3d92fa3ec92f28b95158dc24b915",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/981ea2e76e207a25c1361df858c639feba5cf348",
"reference": "981ea2e76e207a25c1361df858c639feba5cf348",
"shasum": ""
},
"require": {
@ -369,9 +368,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/20.1.2+bedrock-1.19.70"
"source": "https://github.com/pmmp/BedrockProtocol/tree/21.0.1+bedrock-1.19.80"
},
"time": "2023-04-10T11:40:32+00:00"
"time": "2023-04-26T21:00:01+00:00"
},
{
"name": "pocketmine/binaryutils",
@ -994,20 +993,20 @@
},
{
"name": "ramsey/uuid",
"version": "4.7.3",
"version": "4.7.4",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
"reference": "433b2014e3979047db08a17a205f410ba3869cf2"
"reference": "60a4c63ab724854332900504274f6150ff26d286"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/433b2014e3979047db08a17a205f410ba3869cf2",
"reference": "433b2014e3979047db08a17a205f410ba3869cf2",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/60a4c63ab724854332900504274f6150ff26d286",
"reference": "60a4c63ab724854332900504274f6150ff26d286",
"shasum": ""
},
"require": {
"brick/math": "^0.8.8 || ^0.9 || ^0.10",
"brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11",
"ext-json": "*",
"php": "^8.0",
"ramsey/collection": "^1.2 || ^2.0"
@ -1070,7 +1069,7 @@
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
"source": "https://github.com/ramsey/uuid/tree/4.7.3"
"source": "https://github.com/ramsey/uuid/tree/4.7.4"
},
"funding": [
{
@ -1082,7 +1081,7 @@
"type": "tidelift"
}
],
"time": "2023-01-12T18:13:24+00:00"
"time": "2023-04-15T23:01:58+00:00"
},
{
"name": "symfony/filesystem",
@ -1884,16 +1883,16 @@
},
{
"name": "phpstan/phpstan",
"version": "1.10.13",
"version": "1.10.14",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "f07bf8c6980b81bf9e49d44bd0caf2e737614a70"
"reference": "d232901b09e67538e5c86a724be841bea5768a7c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/f07bf8c6980b81bf9e49d44bd0caf2e737614a70",
"reference": "f07bf8c6980b81bf9e49d44bd0caf2e737614a70",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/d232901b09e67538e5c86a724be841bea5768a7c",
"reference": "d232901b09e67538e5c86a724be841bea5768a7c",
"shasum": ""
},
"require": {
@ -1942,7 +1941,7 @@
"type": "tidelift"
}
],
"time": "2023-04-12T19:29:52+00:00"
"time": "2023-04-19T13:47:27+00:00"
},
{
"name": "phpstan/phpstan-phpunit",

View File

@ -31,7 +31,7 @@ use function str_repeat;
final class VersionInfo{
public const NAME = "PocketMine-MP";
public const BASE_VERSION = "4.19.3";
public const BASE_VERSION = "4.20.0";
public const IS_DEVELOPMENT_BUILD = false;
public const BUILD_CHANNEL = "stable";

View File

@ -97,6 +97,15 @@ abstract class BaseSign extends Transparent{
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onPostPlace() : void{
$player = $this->editorEntityRuntimeId !== null ?
$this->position->getWorld()->getEntity($this->editorEntityRuntimeId) :
null;
if($player instanceof Player){
$player->openSignEditor($this->position);
}
}
/**
* Returns an object containing information about the sign text.
*/
@ -110,6 +119,19 @@ abstract class BaseSign extends Transparent{
return $this;
}
/**
* Sets the runtime entity ID of the player editing this sign. Only this player will be able to edit the sign.
* This is used to prevent multiple players from editing the same sign at the same time, and to prevent players
* from editing signs they didn't place.
*/
public function getEditorEntityRuntimeId() : ?int{ return $this->editorEntityRuntimeId; }
/** @return $this */
public function setEditorEntityRuntimeId(?int $editorEntityRuntimeId) : self{
$this->editorEntityRuntimeId = $editorEntityRuntimeId;
return $this;
}
/**
* Called by the player controller (network session) to update the sign text, firing events as appropriate.
*
@ -133,6 +155,7 @@ abstract class BaseSign extends Transparent{
$ev->call();
if(!$ev->isCancelled()){
$this->setText($ev->getNewText());
$this->setEditorEntityRuntimeId(null);
$this->position->getWorld()->setBlock($this->position, $this);
return true;
}

View File

@ -45,12 +45,18 @@ class Sign extends Spawnable{
public const TAG_TEXT_LINE = "Text%d"; //sprintf()able
public const TAG_TEXT_COLOR = "SignTextColor";
public const TAG_GLOWING_TEXT = "IgnoreLighting";
public const TAG_PERSIST_FORMATTING = "PersistFormatting"; //TAG_Byte
/**
* This tag is set to indicate that MCPE-117835 has been addressed in whatever version this sign was created.
* @see https://bugs.mojang.com/browse/MCPE-117835
*/
public const TAG_LEGACY_BUG_RESOLVE = "TextIgnoreLegacyBugResolved";
public const TAG_FRONT_TEXT = "FrontText"; //TAG_Compound
public const TAG_BACK_TEXT = "BackText"; //TAG_Compound
public const TAG_WAXED = "IsWaxed"; //TAG_Byte
public const TAG_LOCKED_FOR_EDITING_BY = "LockedForEditingBy"; //TAG_Long
/**
* @return string[]
*/
@ -118,12 +124,22 @@ class Sign extends Spawnable{
}
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
$nbt->setString(self::TAG_TEXT_BLOB, implode("\n", $this->text->getLines()));
//the following are not yet used by the server, but needed to roll back any changes to glowing state or colour
//if the client uses dye on the sign
$nbt->setInt(self::TAG_TEXT_COLOR, Binary::signInt(0xff_00_00_00));
$nbt->setByte(self::TAG_GLOWING_TEXT, 0);
$nbt->setByte(self::TAG_LEGACY_BUG_RESOLVE, 1);
$textPolyfill = function(CompoundTag $textTag) : CompoundTag{
//the following are not yet used by the server, but needed to roll back any changes to glowing state or colour
//if the client uses dye on the sign
return $textTag
->setInt(self::TAG_TEXT_COLOR, Binary::signInt(0xff_00_00_00))
->setByte(self::TAG_GLOWING_TEXT, 0)
->setByte(self::TAG_PERSIST_FORMATTING, 1); //TODO: not sure what this is used for
};
$nbt->setTag(self::TAG_FRONT_TEXT, $textPolyfill(CompoundTag::create()
->setString(self::TAG_TEXT_BLOB, implode("\n", $this->text->getLines()))
));
//TODO: this is not yet used by the server, but needed to rollback any client-side changes to the back text
$nbt->setTag(self::TAG_BACK_TEXT, $textPolyfill(CompoundTag::create()
->setString(self::TAG_TEXT_BLOB, "")
));
$nbt->setByte(self::TAG_WAXED, 0);
$nbt->setLong(self::TAG_LOCKED_FOR_EDITING_BY, $this->editorEntityRuntimeId ?? -1);
}
}

View File

@ -55,7 +55,7 @@ class CraftingManager{
* @var FurnaceRecipeManager[]
* @phpstan-var array<int, FurnaceRecipeManager>
*/
protected $furnaceRecipeManagers;
protected $furnaceRecipeManagers = [];
/**
* @var PotionTypeRecipe[][]

View File

@ -102,7 +102,7 @@ class HandlerList{
* @return RegisteredListener[]
*/
public function getListenersByPriority(int $priority) : array{
return $this->handlerSlots[$priority];
return $this->handlerSlots[$priority] ?? [];
}
public function getParent() : ?HandlerList{

View File

@ -40,7 +40,7 @@ final class InventoryManagerEntry{
public array $itemStackInfos = [];
/**
* @var int[]
* @var ItemStack[]
* @phpstan-var array<int, ItemStack>
*/
public array $pendingSyncs = [];

View File

@ -60,6 +60,7 @@ use pocketmine\network\mcpe\protocol\DisconnectPacket;
use pocketmine\network\mcpe\protocol\ModalFormRequestPacket;
use pocketmine\network\mcpe\protocol\MovePlayerPacket;
use pocketmine\network\mcpe\protocol\NetworkChunkPublisherUpdatePacket;
use pocketmine\network\mcpe\protocol\OpenSignPacket;
use pocketmine\network\mcpe\protocol\Packet;
use pocketmine\network\mcpe\protocol\PacketDecodeException;
use pocketmine\network\mcpe\protocol\PacketPool;
@ -1093,6 +1094,10 @@ class NetworkSession{
$this->sendDataPacket(ToastRequestPacket::create($title, $body));
}
public function onOpenSignEditor(Vector3 $signPosition, bool $frontSide) : void{
$this->sendDataPacket(OpenSignPacket::create(BlockPosition::fromVector3($signPosition), $frontSide));
}
public function tick() : void{
if(!$this->isConnected()){
$this->dispose();

View File

@ -328,6 +328,9 @@ class InGamePacketHandler extends PacketHandler{
if(count($packet->trData->getActions()) > 50){
throw new PacketHandlingException("Too many actions in inventory transaction");
}
if(count($packet->requestChangedSlots) > 10){
throw new PacketHandlingException("Too many slot sync requests in inventory transaction");
}
$this->inventoryManager->setCurrentItemStackRequestId($packet->requestId);
$this->inventoryManager->addRawPredictedSlotChanges($packet->trData->getActions());
@ -347,6 +350,21 @@ class InGamePacketHandler extends PacketHandler{
}
$this->inventoryManager->syncMismatchedPredictedSlotChanges();
//requestChangedSlots asks the server to always send out the contents of the specified slots, even if they
//haven't changed. Handling these is necessary to ensure the client inventory stays in sync if the server
//rejects the transaction. The most common example of this is equipping armor by right-click, which doesn't send
//a legacy prediction action for the destination armor slot.
foreach($packet->requestChangedSlots as $containerInfo){
$windowId = ItemStackContainerIdTranslator::translate($containerInfo->getContainerId(), $this->inventoryManager->getCurrentWindowId());
foreach($containerInfo->getChangedSlotIndexes() as $slot){
$inventoryAndSlot = $this->inventoryManager->locateWindowAndSlot($windowId, $slot);
if($inventoryAndSlot !== null){ //trigger the normal slot sync logic
$this->inventoryManager->onSlotChange($inventoryAndSlot[0], $inventoryAndSlot[1]);
}
}
}
$this->inventoryManager->setCurrentItemStackRequestId(null);
return $result;
}
@ -730,7 +748,7 @@ 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->getTag(Sign::TAG_TEXT_BLOB)) instanceof StringTag){
if(($textBlobTag = $nbt->getCompoundTag(Sign::TAG_FRONT_TEXT)?->getTag(Sign::TAG_TEXT_BLOB)) instanceof StringTag){
try{
$text = SignText::fromBlob($textBlobTag->getValue());
}catch(\InvalidArgumentException $e){

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe\handler;
use pocketmine\crafting\CraftingGrid;
use pocketmine\inventory\CreativeInventory;
use pocketmine\inventory\Inventory;
use pocketmine\inventory\transaction\action\CreateItemAction;
@ -246,13 +245,11 @@ class ItemStackRequestExecutor{
$this->specialTransaction = new CraftingTransaction($this->player, $craftingManager, [], $recipe, $repetitions);
$currentWindow = $this->player->getCurrentWindow();
if($currentWindow !== null && !($currentWindow instanceof CraftingGrid)){
throw new ItemStackRequestProcessException("Player's current window is not a crafting grid");
}
$craftingGrid = $currentWindow ?? $this->player->getCraftingGrid();
$craftingResults = $recipe->getResultsFor($craftingGrid);
//TODO: Since the system assumes that crafting can only be done in the crafting grid, we have to give it a
//crafting grid to make the API happy. No implementation of getResultsFor() actually uses the crafting grid
//right now, so this will work, but this will become a problem in the future for things like shulker boxes and
//custom crafting recipes.
$craftingResults = $recipe->getResultsFor($this->player->getCraftingGrid());
foreach($craftingResults as $k => $craftingResult){
$craftingResult->setCount($craftingResult->getCount() * $repetitions);
$this->craftingResults[$k] = $craftingResult;

View File

@ -105,6 +105,7 @@ class PreSpawnPacketHandler extends PacketHandler{
sprintf("%s %s", VersionInfo::NAME, VersionInfo::VERSION()->getFullVersion(true)),
Uuid::fromString(Uuid::NIL),
false,
false,
[],
0,
GlobalItemTypeDictionary::getInstance()->getDictionary()->getEntries(),

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\player;
use pocketmine\block\BaseSign;
use pocketmine\block\Bed;
use pocketmine\block\BlockLegacyIds;
use pocketmine\block\UnknownBlock;
@ -2626,6 +2627,20 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$this->permanentWindows = [];
}
/**
* Opens the player's sign editor GUI for the sign at the given position.
* TODO: add support for editing the rear side of the sign (not currently supported due to technical limitations)
*/
public function openSignEditor(Vector3 $position) : void{
$block = $this->getWorld()->getBlock($position);
if($block instanceof BaseSign){
$this->getWorld()->setBlock($position, $block->setEditorEntityRuntimeId($this->getId()));
$this->getNetworkSession()->onOpenSignEditor($position, true);
}else{
throw new \InvalidArgumentException("Block at this position is not a sign");
}
}
use ChunkListenerNoOpTrait {
onChunkChanged as private;
onChunkUnloaded as private;