diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index d2dbd3c02..21cd48b7f 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -72,7 +72,6 @@ use pocketmine\form\FormValidationException; use pocketmine\inventory\CraftingGrid; use pocketmine\inventory\Inventory; use pocketmine\inventory\PlayerCursorInventory; -use pocketmine\inventory\PlayerUIInventory; use pocketmine\inventory\transaction\action\InventoryAction; use pocketmine\inventory\transaction\CraftingTransaction; use pocketmine\inventory\transaction\InventoryTransaction; @@ -290,8 +289,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ protected $windowIndex = []; /** @var bool[] */ protected $permanentWindows = []; - /** @var PlayerUIInventory */ - protected $playerUIInventory; + /** @var PlayerCursorInventory */ + protected $cursorInventory; /** @var CraftingGrid */ protected $craftingGrid = null; /** @var CraftingTransaction|null */ @@ -3554,7 +3553,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ $this->removeAllWindows(true); $this->windows = []; $this->windowIndex = []; - $this->playerUIInventory = null; + $this->cursorInventory = null; $this->craftingGrid = null; if($this->constructed){ @@ -3819,19 +3818,15 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ $this->addWindow($this->getArmorInventory(), ContainerIds::ARMOR, true); - $this->playerUIInventory = new PlayerUIInventory($this); - $this->addWindow($this->playerUIInventory, ContainerIds::UI, true); + $this->cursorInventory = new PlayerCursorInventory($this); + $this->addWindow($this->cursorInventory, ContainerIds::UI, true); - $this->craftingGrid = new CraftingGrid($this->playerUIInventory, CraftingGrid::SIZE_SMALL); + $this->craftingGrid = new CraftingGrid($this, CraftingGrid::SIZE_SMALL); //TODO: more windows } - public function getPlayerUIInventory() : PlayerUIInventory{ - return $this->playerUIInventory; - } - public function getCursorInventory() : PlayerCursorInventory{ - return $this->playerUIInventory->getCursorInventory(); + return $this->cursorInventory; } public function getCraftingGrid() : CraftingGrid{ @@ -3847,7 +3842,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ public function doCloseInventory() : void{ /** @var Inventory[] $inventories */ - $inventories = [$this->craftingGrid, $this->getCursorInventory()]; + $inventories = [$this->craftingGrid, $this->cursorInventory]; foreach($inventories as $inventory){ $contents = $inventory->getContents(); if(count($contents) > 0){ @@ -3861,7 +3856,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ } if($this->craftingGrid->getGridWidth() > CraftingGrid::SIZE_SMALL){ - $this->craftingGrid = new CraftingGrid($this->playerUIInventory, CraftingGrid::SIZE_SMALL); + $this->craftingGrid = new CraftingGrid($this, CraftingGrid::SIZE_SMALL); } } diff --git a/src/pocketmine/block/CraftingTable.php b/src/pocketmine/block/CraftingTable.php index 9e416e872..05b52fd6a 100644 --- a/src/pocketmine/block/CraftingTable.php +++ b/src/pocketmine/block/CraftingTable.php @@ -49,7 +49,7 @@ class CraftingTable extends Solid{ public function onActivate(Item $item, Player $player = null) : bool{ if($player instanceof Player){ - $player->setCraftingGrid(new CraftingGrid($player->getPlayerUIInventory(), CraftingGrid::SIZE_BIG)); + $player->setCraftingGrid(new CraftingGrid($player, CraftingGrid::SIZE_BIG)); } return true; diff --git a/src/pocketmine/inventory/BaseUIInventory.php b/src/pocketmine/inventory/BaseUIInventory.php deleted file mode 100644 index 3636e3ab7..000000000 --- a/src/pocketmine/inventory/BaseUIInventory.php +++ /dev/null @@ -1,116 +0,0 @@ -inventory = $inventory; - $this->size = $size; - $this->offset = $offset; - parent::__construct([], $size); - } - - public function getName() : string{ - return "UI"; - } - - public function getDefaultSize() : int{ - return 1; - } - - public function getSize() : int{ - return $this->size; - } - - public function getMaxStackSize() : int{ - return Inventory::MAX_STACK; - } - - public function setMaxStackSize(int $size) : void{ - } - - public function getTitle() : string{ - return ""; - } - - public function getItem(int $index) : Item{ - return $this->inventory->getItem($index + $this->offset); - } - - public function setItem(int $index, Item $item, bool $send = true) : bool{ - return $this->inventory->setItem($index + $this->offset, $item, $send); - } - - public function getContents(bool $includeEmpty = false) : array{ - $contents = []; - $air = null; - foreach($this->slots as $i => $slot){ - if($i < $this->offset || $i > $this->offset + $this->size){ - continue; - } - if($slot !== null){ - $contents[$i] = clone $slot; - }elseif($includeEmpty){ - $contents[$i] = $air ?? ($air = ItemFactory::get(Item::AIR, 0, 0)); - } - } - - return $contents; - } - - public function sendContents($target) : void{ - $this->inventory->sendContents($target); - } - - public function sendSlot(int $index, $target) : void{ - $this->inventory->sendSlot($index + $this->offset, $target); - } - - public function getViewers() : array{ - return $this->inventory->viewers; - } - - public function onOpen(Player $who) : void{} - - public function onClose(Player $who) : void{} - - public function open(Player $who) : bool{ - return false; - } - - public function close(Player $who) : void{} - - public function onSlotChange(int $index, Item $before, bool $send) : void{ - $this->inventory->onSlotChange($index + $this->offset, $before, $send); - } -} \ No newline at end of file diff --git a/src/pocketmine/inventory/CraftingGrid.php b/src/pocketmine/inventory/CraftingGrid.php index b54068f4e..e6097562e 100644 --- a/src/pocketmine/inventory/CraftingGrid.php +++ b/src/pocketmine/inventory/CraftingGrid.php @@ -29,23 +29,124 @@ use function max; use function min; use const PHP_INT_MAX; -class CraftingGrid extends BaseUIInventory{ - public const SIZE_SMALL = 4; - public const SIZE_BIG = 9; +class CraftingGrid extends BaseInventory{ + public const SIZE_SMALL = 2; + public const SIZE_BIG = 3; + + public const SMALL_OFFSET = 28; + public const BIG_OFFSET = 32; + + /** @var int */ + public $offset; + /** @var Player */ + private $holder; /** @var int */ private $gridWidth; + /** @var int|null */ + private $startX; + /** @var int|null */ + private $xLen; + /** @var int|null */ + private $startY; + /** @var int|null */ + private $yLen; - public function __construct(PlayerUIInventory $inventory, int $gridWidth){ + public function __construct(Player $holder, int $gridWidth){ + $this->holder = $holder; $this->gridWidth = $gridWidth; - if($gridWidth === self::SIZE_SMALL){ - parent::__construct($inventory, $gridWidth, 28); - }elseif($gridWidth === self::SIZE_BIG){ - parent::__construct($inventory, $gridWidth, 32); + if($this->gridWidth === self::SIZE_SMALL){ + $this->offset = self::SMALL_OFFSET; + }elseif($this->gridWidth === self::SIZE_BIG){ + $this->offset = self::BIG_OFFSET; } + parent::__construct(); } public function getGridWidth() : int{ return $this->gridWidth; } + + public function getDefaultSize() : int{ + return $this->getGridWidth() ** 2; + } + + public function setSize(int $size){ + throw new \BadMethodCallException("Cannot change the size of a crafting grid"); + } + + public function getName() : string{ + return "Crafting"; + } + + public function getItem(int $index) : Item{ + return parent::getItem($index + $this->offset); + } + + public function setItem(int $index, Item $item, bool $send = true) : bool{ + if(parent::setItem($index + $this->offset, $item, $send)){ + $this->seekRecipeBounds(); + return true; + } + return false; + } + + public function sendSlot(int $index, $target) : void{ + //we can't send a slot of a client-sided inventory window + } + + public function sendContents($target) : void{ + //no way to do this + } + + /** + * @return Player + */ + public function getHolder(){ + return $this->holder; + } + + private function seekRecipeBounds() : void{ + $minX = PHP_INT_MAX; + $maxX = 0; + $minY = PHP_INT_MAX; + $maxY = 0; + $empty = true; + for($y = 0; $y < $this->gridWidth; ++$y){ + for($x = 0; $x < $this->gridWidth; ++$x){ + if(!$this->isSlotEmpty($y * $this->gridWidth + $x)){ + $minX = min($minX, $x); + $maxX = max($maxX, $x); + $minY = min($minY, $y); + $maxY = max($maxY, $y); + $empty = false; + } + } + } + if(!$empty){ + $this->startX = $minX; + $this->xLen = $maxX - $minX + 1; + $this->startY = $minY; + $this->yLen = $maxY - $minY + 1; + }else{ + $this->startX = $this->xLen = $this->startY = $this->yLen = null; + } + } + + /** + * Returns the width of the recipe we're trying to craft, based on items currently in the grid. + * + * @return int + */ + public function getRecipeWidth() : int{ + return $this->xLen ?? 0; + } + + /** + * Returns the height of the recipe we're trying to craft, based on items currently in the grid. + * @return int + */ + public function getRecipeHeight() : int{ + return $this->yLen ?? 0; + } } diff --git a/src/pocketmine/inventory/PlayerCursorInventory.php b/src/pocketmine/inventory/PlayerCursorInventory.php index 32939f7f7..2b0869cd5 100644 --- a/src/pocketmine/inventory/PlayerCursorInventory.php +++ b/src/pocketmine/inventory/PlayerCursorInventory.php @@ -23,9 +23,37 @@ declare(strict_types=1); namespace pocketmine\inventory; -class PlayerCursorInventory extends BaseUIInventory{ +use pocketmine\Player; - public function __construct(PlayerUIInventory $inventory){ - parent::__construct($inventory, 1, 0); +class PlayerCursorInventory extends BaseInventory{ + + /** @var Player */ + protected $holder; + /** @var int */ + protected $offset = 0; + + public function __construct(Player $holder){ + $this->holder = $holder; + parent::__construct(); + } + + public function getName() : string{ + return "Cursor"; + } + + public function getDefaultSize() : int{ + return 1; + } + + public function setSize(int $size){ + throw new \BadMethodCallException("Cursor can only carry one item at a time"); + } + + /** + * This override is here for documentation and code completion purposes only. + * @return Player + */ + public function getHolder(){ + return $this->holder; } } diff --git a/src/pocketmine/inventory/PlayerUIInventory.php b/src/pocketmine/inventory/PlayerUIInventory.php deleted file mode 100644 index a3e9e6454..000000000 --- a/src/pocketmine/inventory/PlayerUIInventory.php +++ /dev/null @@ -1,89 +0,0 @@ -holder = $holder; - $this->cursorInventory = new PlayerCursorInventory($this); - parent::__construct(); - } - - public function getCursorInventory(){ - return $this->cursorInventory; - } - - public function getName() : string{ - return "UI"; - } - - public function getDefaultSize() : int{ - return 51; - } - - public function getSize() : int{ - return 51; - } - - public function getHolder(){ - return $this->holder; - } - - public function setSize(int $size){} - - public function sendSlot(int $index, $target) : void{ - if($target instanceof Player){ - $target = [$target]; - } - $pk = new InventorySlotPacket(); - $pk->inventorySlot = $index; - $pk->item = $this->getItem($index); - foreach($target as $player){ - if($player === $this->getHolder()){ - $pk->windowId = ContainerIds::UI; - $player->dataPacket($pk); - }else{ - if(($id = $player->getWindowId($this)) === ContainerIds::NONE){ - $this->close($player); - continue; - } - $pk->windowId = $id; - $player->dataPacket($pk); - } - } - } -} \ No newline at end of file diff --git a/src/pocketmine/utils/SkinAnimation.php b/src/pocketmine/utils/SkinAnimation.php index 025aee3d6..10092059b 100644 --- a/src/pocketmine/utils/SkinAnimation.php +++ b/src/pocketmine/utils/SkinAnimation.php @@ -25,6 +25,8 @@ namespace pocketmine\utils; class SkinAnimation{ + public const TYPE_HEAD = 1; //Might want a double check on this + /** @var SerializedImage */ private $image; /** @var int */