Player: track hardcoded window state, fixes crashes opening inventory on high-latency connections

This commit is contained in:
Dylan K. Taylor 2020-06-27 18:34:39 +01:00
parent a6c1b7bf9c
commit 8480ee82ea
2 changed files with 28 additions and 12 deletions

View File

@ -176,6 +176,7 @@ use pocketmine\timings\Timings;
use pocketmine\utils\TextFormat;
use pocketmine\utils\UUID;
use function abs;
use function array_key_exists;
use function array_merge;
use function array_values;
use function assert;
@ -315,6 +316,15 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
/** @var CraftingTransaction|null */
protected $craftingTransaction = null;
/**
* TODO: HACK! This tracks GUIs for inventories that the server considers "always open" so that the client can't
* open them twice. (1.16 hack)
* @var true[]
* @phpstan-var array<int, true>
* @internal
*/
public $openHardcodedWindows = [];
/** @var int */
protected $messageCounter = 2;
/** @var bool */
@ -2795,12 +2805,13 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
case InteractPacket::ACTION_MOUSEOVER:
break; //TODO: handle these
case InteractPacket::ACTION_OPEN_INVENTORY:
if($target === $this){
if($target === $this && !array_key_exists($windowId = self::HARDCODED_INVENTORY_WINDOW_ID, $this->openHardcodedWindows)){
//TODO: HACK! this restores 1.14ish behaviour, but this should be able to be listened to and
//controlled by plugins. However, the player is always a subscriber to their own inventory so it
//doesn't integrate well with the regular container system right now.
$this->openHardcodedWindows[$windowId] = true;
$pk = new ContainerOpenPacket();
$pk->windowId = self::HARDCODED_INVENTORY_WINDOW_ID;
$pk->windowId = $windowId;
$pk->type = WindowTypes::INVENTORY;
$pk->x = $pk->y = $pk->z = 0;
$pk->entityUniqueId = $this->getId();
@ -3027,7 +3038,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->doCloseInventory();
if($packet->windowId >= self::RESERVED_WINDOW_ID_RANGE_START and $packet->windowId <= self::RESERVED_WINDOW_ID_RANGE_END){
if(array_key_exists($packet->windowId, $this->openHardcodedWindows)){
unset($this->openHardcodedWindows[$packet->windowId]);
$pk = new ContainerClosePacket();
$pk->windowId = $packet->windowId;
$this->sendDataPacket($pk);

View File

@ -28,6 +28,7 @@ use pocketmine\item\Item;
use pocketmine\network\mcpe\protocol\ContainerOpenPacket;
use pocketmine\network\mcpe\protocol\types\WindowTypes;
use pocketmine\Player;
use function array_key_exists;
class CraftingTable extends Solid{
@ -53,15 +54,18 @@ class CraftingTable extends Solid{
if($player instanceof Player){
$player->setCraftingGrid(new CraftingGrid($player, CraftingGrid::SIZE_BIG));
//TODO: HACK! crafting grid doesn't fit very well into the current PM container system, so this hack allows
//it to carry on working approximately the same way as it did in 1.14
$pk = new ContainerOpenPacket();
$pk->windowId = Player::HARDCODED_CRAFTING_GRID_WINDOW_ID;
$pk->type = WindowTypes::WORKBENCH;
$pk->x = $this->getFloorX();
$pk->y = $this->getFloorY();
$pk->z = $this->getFloorZ();
$player->sendDataPacket($pk);
if(!array_key_exists($windowId = Player::HARDCODED_CRAFTING_GRID_WINDOW_ID, $player->openHardcodedWindows)){
//TODO: HACK! crafting grid doesn't fit very well into the current PM container system, so this hack allows
//it to carry on working approximately the same way as it did in 1.14
$pk = new ContainerOpenPacket();
$pk->windowId = $windowId;
$pk->type = WindowTypes::WORKBENCH;
$pk->x = $this->getFloorX();
$pk->y = $this->getFloorY();
$pk->z = $this->getFloorZ();
$player->sendDataPacket($pk);
$player->openHardcodedWindows[$windowId] = true;
}
}
return true;