mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-09 03:06:55 +00:00
Separate inventory holder info from container & player inventories (#6533)
This PR breaks the cyclic dependency between `Inventory` and its holder, which unblocks a lot of new developments. ### Related issues & PRs - Fixes #5033 - Removes a blocker for #6147 (which in turn means that async tasks will eventually be able to work with tiles) - Removes a blocker for #2684 ## Changes ### API changes - `Player->getCurrentWindow()` now returns `?InventoryWindow` instead of `?Inventory` - `Player->setCurrentWindow()` now accepts `?InventoryWindow` instead of `?Inventory` - `InventoryWindow` introduced, which is created for each player viewing the inventory, provides decorative information like holder info for `InventoryTransactionEvent`, and is destroyed when the window is closed, eliminating cyclic references - Added: - `player\InventoryWindow` - `player\PlayerInventoryWindow` - wraps all permanent inventories of Player with type info for transactions - `inventory\Hotbar` - replaces all hotbar usages in `PlayerInventory` - `Human->getHotbar()` - `Human->getMainHandItem()`, `Human->setMainHandItem()`, `Human->getOffHandItem()`, `Human->setOffHandItem()` - `block\utils\AnimatedContainerLike` & `block\utils\AnimatedContainerLikeTrait` (for chests, shulkerboxes, etc) - `block\utils\Container` & `block\utils\ContainerTrait` for blocks containing items (chests, etc) - `block\utils\MenuAccessor` implemented by all blocks that can open inventory menus - `block\utils\MenuAccessorTrait` used by blocks with menus but without inventories (anvils, crafting tables etc) - Removed: - `inventory\DelegateInventory` (only used for ender chests) - `inventory\PlayerInventory`, - `inventory\PlayerOffHandInventory`, - `inventory\PlayerCraftingInventory`, - `inventory\PlayerCursorInventory` - these have all been internally replaced by `SimpleInventory` & they will appear as `PlayerInventoryWindow` in transactions (check `getType()` against the `PlayerInventoryWindow::TYPE_*` constants to identify them) - `block\inventory\AnimatedBlockInventoryTrait`, (blocks now handle this logic directly using `AnimatedContainer` and `AnimatedContainerTrait`) - `block\inventory\BlockInventoryTrait`, - `block\inventory\BlockInventory` - Most `BlockInventory` classes have been transitioned to `InventoryWindow` wrappers - Tiles now all use `SimpleInventory` internally (no cyclic references) except for `Chest` (which uses `CombinedInventory`, without holder info) - `InventoryOpenEvent` and `InventoryCloseEvent` now provide `InventoryWindow` instead of `Inventory` (to provide type information) - `InventoryTransaction` and `SlotChangeAction` now provide `InventoryWindow` instead of `Inventory` - Renamed `TransactionBuilderInventory` to `SlotChangeActionBuilder` - `TransactionBuilderInventory->getBuilder()` now accepts `InventoryWindow` instead of `Inventory` - `DoubleChestInventory` superseded by `CombinedInventory` - this new class allows combining any number of inventories behind a single object; mainly used for double chests but plugins could use it to do lots of fun things ### Impacts to plugins Plugins can now do the following: ```php $block = $world->getBlockAt($x, $y, $z); if($block instanceof MenuAccessor){ $block->openToUnchecked($player); } ``` As compared to the old way: ```php $tile = $world->getTileAt($x, $y, $z); if($tile instanceof Container){ $player->setCurrentWindow($tile->getInventory()); } ``` #### Advantages - No tile access needed - Works for menu blocks without inventories as well as container blocks - Less code ### Behavioural changes Inventories no longer keep permanent cyclic references to their holders. ## Backwards compatibility This makes significant BC breaks. However, all changes are able to be adapted to and the same amount of information is present on all APIs and events. ## Follow-up - Implement #6147 - Support inventory inheritance when copying blocks from one position to another
This commit is contained in:
@ -1,67 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\sound\Sound;
|
||||
use function count;
|
||||
|
||||
trait AnimatedBlockInventoryTrait{
|
||||
use BlockInventoryTrait;
|
||||
|
||||
public function getViewerCount() : int{
|
||||
return count($this->getViewers());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Player[]
|
||||
* @phpstan-return array<int, Player>
|
||||
*/
|
||||
abstract public function getViewers() : array;
|
||||
|
||||
abstract protected function getOpenSound() : Sound;
|
||||
|
||||
abstract protected function getCloseSound() : Sound;
|
||||
|
||||
public function onOpen(Player $who) : void{
|
||||
parent::onOpen($who);
|
||||
|
||||
if($this->holder->isValid() && $this->getViewerCount() === 1){
|
||||
//TODO: this crap really shouldn't be managed by the inventory
|
||||
$this->animateBlock(true);
|
||||
$this->holder->getWorld()->addSound($this->holder->add(0.5, 0.5, 0.5), $this->getOpenSound());
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected function animateBlock(bool $isOpen) : void;
|
||||
|
||||
public function onClose(Player $who) : void{
|
||||
if($this->holder->isValid() && $this->getViewerCount() === 1){
|
||||
//TODO: this crap really shouldn't be managed by the inventory
|
||||
$this->animateBlock(false);
|
||||
$this->holder->getWorld()->addSound($this->holder->add(0.5, 0.5, 0.5), $this->getCloseSound());
|
||||
}
|
||||
parent::onClose($who);
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
|
||||
use pocketmine\block\Barrel;
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\world\Position;
|
||||
use pocketmine\world\sound\BarrelCloseSound;
|
||||
use pocketmine\world\sound\BarrelOpenSound;
|
||||
use pocketmine\world\sound\Sound;
|
||||
|
||||
class BarrelInventory extends SimpleInventory implements BlockInventory{
|
||||
use AnimatedBlockInventoryTrait;
|
||||
|
||||
public function __construct(Position $holder){
|
||||
$this->holder = $holder;
|
||||
parent::__construct(27);
|
||||
}
|
||||
|
||||
protected function getOpenSound() : Sound{
|
||||
return new BarrelOpenSound();
|
||||
}
|
||||
|
||||
protected function getCloseSound() : Sound{
|
||||
return new BarrelCloseSound();
|
||||
}
|
||||
|
||||
protected function animateBlock(bool $isOpen) : void{
|
||||
$holder = $this->getHolder();
|
||||
$world = $holder->getWorld();
|
||||
$block = $world->getBlock($holder);
|
||||
if($block instanceof Barrel){
|
||||
$world->setBlock($holder, $block->setOpen($isOpen));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
|
||||
use pocketmine\world\Position;
|
||||
|
||||
trait BlockInventoryTrait{
|
||||
protected Position $holder;
|
||||
|
||||
public function getHolder() : Position{
|
||||
return $this->holder;
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\inventory\TemporaryInventory;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
final class CartographyTableInventory extends SimpleInventory implements BlockInventory, TemporaryInventory{
|
||||
use BlockInventoryTrait;
|
||||
|
||||
public function __construct(Position $holder){
|
||||
$this->holder = $holder;
|
||||
parent::__construct(2);
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\network\mcpe\protocol\BlockEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\BlockPosition;
|
||||
use pocketmine\world\Position;
|
||||
use pocketmine\world\sound\ChestCloseSound;
|
||||
use pocketmine\world\sound\ChestOpenSound;
|
||||
use pocketmine\world\sound\Sound;
|
||||
|
||||
class ChestInventory extends SimpleInventory implements BlockInventory{
|
||||
use AnimatedBlockInventoryTrait;
|
||||
|
||||
public function __construct(Position $holder){
|
||||
$this->holder = $holder;
|
||||
parent::__construct(27);
|
||||
}
|
||||
|
||||
protected function getOpenSound() : Sound{
|
||||
return new ChestOpenSound();
|
||||
}
|
||||
|
||||
protected function getCloseSound() : Sound{
|
||||
return new ChestCloseSound();
|
||||
}
|
||||
|
||||
public function animateBlock(bool $isOpen) : void{
|
||||
$holder = $this->getHolder();
|
||||
|
||||
//event ID is always 1 for a chest
|
||||
$holder->getWorld()->broadcastPacketToViewers($holder, BlockEventPacket::create(BlockPosition::fromVector3($holder), 1, $isOpen ? 1 : 0));
|
||||
}
|
||||
}
|
@ -1,118 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
|
||||
use pocketmine\inventory\BaseInventory;
|
||||
use pocketmine\inventory\InventoryHolder;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\world\sound\ChestCloseSound;
|
||||
use pocketmine\world\sound\ChestOpenSound;
|
||||
use pocketmine\world\sound\Sound;
|
||||
|
||||
class DoubleChestInventory extends BaseInventory implements BlockInventory, InventoryHolder{
|
||||
use AnimatedBlockInventoryTrait;
|
||||
|
||||
public function __construct(
|
||||
private ChestInventory $left,
|
||||
private ChestInventory $right
|
||||
){
|
||||
$this->holder = $this->left->getHolder();
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function getInventory() : self{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSize() : int{
|
||||
return $this->left->getSize() + $this->right->getSize();
|
||||
}
|
||||
|
||||
public function getItem(int $index) : Item{
|
||||
return $index < $this->left->getSize() ? $this->left->getItem($index) : $this->right->getItem($index - $this->left->getSize());
|
||||
}
|
||||
|
||||
protected function internalSetItem(int $index, Item $item) : void{
|
||||
$index < $this->left->getSize() ? $this->left->setItem($index, $item) : $this->right->setItem($index - $this->left->getSize(), $item);
|
||||
}
|
||||
|
||||
public function getContents(bool $includeEmpty = false) : array{
|
||||
$result = $this->left->getContents($includeEmpty);
|
||||
$leftSize = $this->left->getSize();
|
||||
|
||||
foreach($this->right->getContents($includeEmpty) as $i => $item){
|
||||
$result[$i + $leftSize] = $item;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function internalSetContents(array $items) : void{
|
||||
$leftSize = $this->left->getSize();
|
||||
|
||||
$leftContents = [];
|
||||
$rightContents = [];
|
||||
|
||||
foreach($items as $i => $item){
|
||||
if($i < $this->left->getSize()){
|
||||
$leftContents[$i] = $item;
|
||||
}else{
|
||||
$rightContents[$i - $leftSize] = $item;
|
||||
}
|
||||
}
|
||||
$this->left->setContents($leftContents);
|
||||
$this->right->setContents($rightContents);
|
||||
}
|
||||
|
||||
protected function getMatchingItemCount(int $slot, Item $test, bool $checkTags) : int{
|
||||
$leftSize = $this->left->getSize();
|
||||
return $slot < $leftSize ?
|
||||
$this->left->getMatchingItemCount($slot, $test, $checkTags) :
|
||||
$this->right->getMatchingItemCount($slot - $leftSize, $test, $checkTags);
|
||||
}
|
||||
|
||||
public function isSlotEmpty(int $index) : bool{
|
||||
$leftSize = $this->left->getSize();
|
||||
return $index < $leftSize ?
|
||||
$this->left->isSlotEmpty($index) :
|
||||
$this->right->isSlotEmpty($index - $leftSize);
|
||||
}
|
||||
|
||||
protected function getOpenSound() : Sound{ return new ChestOpenSound(); }
|
||||
|
||||
protected function getCloseSound() : Sound{ return new ChestCloseSound(); }
|
||||
|
||||
protected function animateBlock(bool $isOpen) : void{
|
||||
$this->left->animateBlock($isOpen);
|
||||
$this->right->animateBlock($isOpen);
|
||||
}
|
||||
|
||||
public function getLeftSide() : ChestInventory{
|
||||
return $this->left;
|
||||
}
|
||||
|
||||
public function getRightSide() : ChestInventory{
|
||||
return $this->right;
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
|
||||
use pocketmine\event\player\PlayerEnchantingOptionsRequestEvent;
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\inventory\TemporaryInventory;
|
||||
use pocketmine\item\enchantment\EnchantingHelper as Helper;
|
||||
use pocketmine\item\enchantment\EnchantingOption;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\world\Position;
|
||||
use function array_values;
|
||||
use function count;
|
||||
|
||||
class EnchantInventory extends SimpleInventory implements BlockInventory, TemporaryInventory{
|
||||
use BlockInventoryTrait;
|
||||
|
||||
public const SLOT_INPUT = 0;
|
||||
public const SLOT_LAPIS = 1;
|
||||
|
||||
/**
|
||||
* @var EnchantingOption[] $options
|
||||
* @phpstan-var list<EnchantingOption>
|
||||
*/
|
||||
private array $options = [];
|
||||
|
||||
public function __construct(Position $holder){
|
||||
$this->holder = $holder;
|
||||
parent::__construct(2);
|
||||
}
|
||||
|
||||
protected function onSlotChange(int $index, Item $before) : void{
|
||||
if($index === self::SLOT_INPUT){
|
||||
foreach($this->viewers as $viewer){
|
||||
$this->options = [];
|
||||
$item = $this->getInput();
|
||||
$options = Helper::generateOptions($this->holder, $item, $viewer->getEnchantmentSeed());
|
||||
|
||||
$event = new PlayerEnchantingOptionsRequestEvent($viewer, $this, $options);
|
||||
$event->call();
|
||||
if(!$event->isCancelled() && count($event->getOptions()) > 0){
|
||||
$this->options = array_values($event->getOptions());
|
||||
$viewer->getNetworkSession()->getInvManager()?->syncEnchantingTableOptions($this->options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parent::onSlotChange($index, $before);
|
||||
}
|
||||
|
||||
public function getInput() : Item{
|
||||
return $this->getItem(self::SLOT_INPUT);
|
||||
}
|
||||
|
||||
public function getLapis() : Item{
|
||||
return $this->getItem(self::SLOT_LAPIS);
|
||||
}
|
||||
|
||||
public function getOutput(int $optionId) : ?Item{
|
||||
$option = $this->getOption($optionId);
|
||||
return $option === null ? null : Helper::enchantItem($this->getInput(), $option->getEnchantments());
|
||||
}
|
||||
|
||||
public function getOption(int $optionId) : ?EnchantingOption{
|
||||
return $this->options[$optionId] ?? null;
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
|
||||
use pocketmine\block\tile\EnderChest;
|
||||
use pocketmine\inventory\DelegateInventory;
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\inventory\PlayerEnderInventory;
|
||||
use pocketmine\network\mcpe\protocol\BlockEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\BlockPosition;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\Position;
|
||||
use pocketmine\world\sound\EnderChestCloseSound;
|
||||
use pocketmine\world\sound\EnderChestOpenSound;
|
||||
use pocketmine\world\sound\Sound;
|
||||
|
||||
/**
|
||||
* EnderChestInventory is not a real inventory; it's just a gateway to the player's ender inventory.
|
||||
*/
|
||||
class EnderChestInventory extends DelegateInventory implements BlockInventory{
|
||||
use AnimatedBlockInventoryTrait {
|
||||
onClose as animatedBlockInventoryTrait_onClose;
|
||||
}
|
||||
|
||||
public function __construct(
|
||||
Position $holder,
|
||||
private PlayerEnderInventory $inventory
|
||||
){
|
||||
parent::__construct($inventory);
|
||||
$this->holder = $holder;
|
||||
}
|
||||
|
||||
public function getEnderInventory() : PlayerEnderInventory{
|
||||
return $this->inventory;
|
||||
}
|
||||
|
||||
public function getViewerCount() : int{
|
||||
$enderChest = $this->getHolder()->getWorld()->getTile($this->getHolder());
|
||||
if(!$enderChest instanceof EnderChest){
|
||||
return 0;
|
||||
}
|
||||
return $enderChest->getViewerCount();
|
||||
}
|
||||
|
||||
protected function getOpenSound() : Sound{
|
||||
return new EnderChestOpenSound();
|
||||
}
|
||||
|
||||
protected function getCloseSound() : Sound{
|
||||
return new EnderChestCloseSound();
|
||||
}
|
||||
|
||||
protected function animateBlock(bool $isOpen) : void{
|
||||
$holder = $this->getHolder();
|
||||
|
||||
//event ID is always 1 for a chest
|
||||
$holder->getWorld()->broadcastPacketToViewers($holder, BlockEventPacket::create(BlockPosition::fromVector3($holder), 1, $isOpen ? 1 : 0));
|
||||
}
|
||||
|
||||
public function onClose(Player $who) : void{
|
||||
$this->animatedBlockInventoryTrait_onClose($who);
|
||||
$enderChest = $this->getHolder()->getWorld()->getTile($this->getHolder());
|
||||
if($enderChest instanceof EnderChest){
|
||||
$enderChest->setViewerCount($enderChest->getViewerCount() - 1);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
|
||||
use pocketmine\block\BlockTypeIds;
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemTypeIds;
|
||||
use pocketmine\network\mcpe\protocol\BlockEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\BlockPosition;
|
||||
use pocketmine\world\Position;
|
||||
use pocketmine\world\sound\ShulkerBoxCloseSound;
|
||||
use pocketmine\world\sound\ShulkerBoxOpenSound;
|
||||
use pocketmine\world\sound\Sound;
|
||||
|
||||
class ShulkerBoxInventory extends SimpleInventory implements BlockInventory{
|
||||
use AnimatedBlockInventoryTrait;
|
||||
|
||||
public function __construct(Position $holder){
|
||||
$this->holder = $holder;
|
||||
parent::__construct(27);
|
||||
}
|
||||
|
||||
protected function getOpenSound() : Sound{
|
||||
return new ShulkerBoxOpenSound();
|
||||
}
|
||||
|
||||
protected function getCloseSound() : Sound{
|
||||
return new ShulkerBoxCloseSound();
|
||||
}
|
||||
|
||||
public function canAddItem(Item $item) : bool{
|
||||
$blockTypeId = ItemTypeIds::toBlockTypeId($item->getTypeId());
|
||||
if($blockTypeId === BlockTypeIds::SHULKER_BOX || $blockTypeId === BlockTypeIds::DYED_SHULKER_BOX){
|
||||
return false;
|
||||
}
|
||||
return parent::canAddItem($item);
|
||||
}
|
||||
|
||||
protected function animateBlock(bool $isOpen) : void{
|
||||
$holder = $this->getHolder();
|
||||
|
||||
//event ID is always 1 for a chest
|
||||
$holder->getWorld()->broadcastPacketToViewers($holder, BlockEventPacket::create(BlockPosition::fromVector3($holder), 1, $isOpen ? 1 : 0));
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\inventory\TemporaryInventory;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
final class SmithingTableInventory extends SimpleInventory implements BlockInventory, TemporaryInventory{
|
||||
use BlockInventoryTrait;
|
||||
|
||||
public function __construct(Position $holder){
|
||||
$this->holder = $holder;
|
||||
parent::__construct(3);
|
||||
}
|
||||
}
|
@ -21,20 +21,21 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
namespace pocketmine\block\inventory\window;
|
||||
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\inventory\TemporaryInventory;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\player\TemporaryInventoryWindow;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
class AnvilInventory extends SimpleInventory implements BlockInventory, TemporaryInventory{
|
||||
use BlockInventoryTrait;
|
||||
|
||||
final class AnvilInventoryWindow extends BlockInventoryWindow implements TemporaryInventoryWindow{
|
||||
public const SLOT_INPUT = 0;
|
||||
public const SLOT_MATERIAL = 1;
|
||||
|
||||
public function __construct(Position $holder){
|
||||
$this->holder = $holder;
|
||||
parent::__construct(2);
|
||||
public function __construct(
|
||||
Player $viewer,
|
||||
Position $holder
|
||||
){
|
||||
parent::__construct($viewer, new SimpleInventory(2), $holder);
|
||||
}
|
||||
}
|
59
src/block/inventory/window/BlockInventoryWindow.php
Normal file
59
src/block/inventory/window/BlockInventoryWindow.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory\window;
|
||||
|
||||
use pocketmine\block\utils\AnimatedContainerLike;
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\player\InventoryWindow;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
class BlockInventoryWindow extends InventoryWindow{
|
||||
|
||||
public function __construct(
|
||||
Player $viewer,
|
||||
Inventory $inventory,
|
||||
protected Position $holder
|
||||
){
|
||||
parent::__construct($viewer, $inventory);
|
||||
}
|
||||
|
||||
public function getHolder() : Position{ return $this->holder; }
|
||||
|
||||
public function onOpen() : void{
|
||||
parent::onOpen();
|
||||
$block = $this->holder->getWorld()->getBlock($this->holder);
|
||||
if($block instanceof AnimatedContainerLike){
|
||||
$block->onViewerAdded();
|
||||
}
|
||||
}
|
||||
|
||||
public function onClose() : void{
|
||||
$block = $this->holder->getWorld()->getBlock($this->holder);
|
||||
if($block instanceof AnimatedContainerLike){
|
||||
$block->onViewerRemoved();
|
||||
}
|
||||
parent::onClose();
|
||||
}
|
||||
}
|
@ -21,22 +21,12 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
class BrewingStandInventory extends SimpleInventory implements BlockInventory{
|
||||
use BlockInventoryTrait;
|
||||
namespace pocketmine\block\inventory\window;
|
||||
|
||||
final class BrewingStandInventoryWindow extends BlockInventoryWindow{
|
||||
public const SLOT_INGREDIENT = 0;
|
||||
public const SLOT_BOTTLE_LEFT = 1;
|
||||
public const SLOT_BOTTLE_MIDDLE = 2;
|
||||
public const SLOT_BOTTLE_RIGHT = 3;
|
||||
public const SLOT_FUEL = 4;
|
||||
|
||||
public function __construct(Position $holder, int $size = 5){
|
||||
$this->holder = $holder;
|
||||
parent::__construct($size);
|
||||
}
|
||||
}
|
@ -21,20 +21,19 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
namespace pocketmine\block\inventory\window;
|
||||
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\player\TemporaryInventoryWindow;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
class CampfireInventory extends SimpleInventory implements BlockInventory{
|
||||
use BlockInventoryTrait;
|
||||
final class CartographyTableInventoryWindow extends BlockInventoryWindow implements TemporaryInventoryWindow{
|
||||
|
||||
public function __construct(Position $holder){
|
||||
$this->holder = $holder;
|
||||
parent::__construct(4);
|
||||
}
|
||||
|
||||
public function getMaxStackSize() : int{
|
||||
return 1;
|
||||
public function __construct(
|
||||
Player $viewer,
|
||||
Position $holder
|
||||
){
|
||||
parent::__construct($viewer, new SimpleInventory(2), $holder);
|
||||
}
|
||||
}
|
@ -21,17 +21,19 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
namespace pocketmine\block\inventory\window;
|
||||
|
||||
use pocketmine\crafting\CraftingGrid;
|
||||
use pocketmine\inventory\TemporaryInventory;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
final class CraftingTableInventory extends CraftingGrid implements BlockInventory, TemporaryInventory{
|
||||
use BlockInventoryTrait;
|
||||
final class CraftingTableInventoryWindow extends BlockInventoryWindow{
|
||||
|
||||
public function __construct(Position $holder){
|
||||
$this->holder = $holder;
|
||||
parent::__construct(CraftingGrid::SIZE_BIG);
|
||||
public function __construct(
|
||||
Player $viewer,
|
||||
Position $holder
|
||||
){
|
||||
//TODO: generics would be good for this, since it has special methods
|
||||
parent::__construct($viewer, new CraftingGrid(CraftingGrid::SIZE_BIG), $holder);
|
||||
}
|
||||
}
|
44
src/block/inventory/window/DoubleChestInventoryWindow.php
Normal file
44
src/block/inventory/window/DoubleChestInventoryWindow.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory\window;
|
||||
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
final class DoubleChestInventoryWindow extends BlockInventoryWindow{
|
||||
|
||||
public function __construct(
|
||||
Player $viewer,
|
||||
Inventory $inventory,
|
||||
private Position $left,
|
||||
private Position $right
|
||||
){
|
||||
parent::__construct($viewer, $inventory, $this->left);
|
||||
}
|
||||
|
||||
public function getLeft() : Position{ return $this->left; }
|
||||
|
||||
public function getRight() : Position{ return $this->right; }
|
||||
}
|
104
src/block/inventory/window/EnchantingTableInventoryWindow.php
Normal file
104
src/block/inventory/window/EnchantingTableInventoryWindow.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory\window;
|
||||
|
||||
use pocketmine\event\player\PlayerEnchantingOptionsRequestEvent;
|
||||
use pocketmine\inventory\CallbackInventoryListener;
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\inventory\InventoryListener;
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\item\enchantment\EnchantingHelper as Helper;
|
||||
use pocketmine\item\enchantment\EnchantingOption;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\Position;
|
||||
use function array_values;
|
||||
use function count;
|
||||
|
||||
final class EnchantingTableInventoryWindow extends BlockInventoryWindow{
|
||||
public const SLOT_INPUT = 0;
|
||||
public const SLOT_LAPIS = 1;
|
||||
|
||||
/** @var EnchantingOption[] $options */
|
||||
private array $options = [];
|
||||
|
||||
private InventoryListener $listener;
|
||||
|
||||
public function __construct(
|
||||
Player $viewer,
|
||||
Position $holder
|
||||
){
|
||||
parent::__construct($viewer, new SimpleInventory(2), $holder);
|
||||
|
||||
/** @phpstan-var \WeakReference<$this> $weakThis */
|
||||
$weakThis = \WeakReference::create($this);
|
||||
$this->listener = new CallbackInventoryListener(
|
||||
onSlotChange: static function(Inventory $_, int $slot) use ($weakThis) : void{ //remaining params unneeded
|
||||
if($slot === self::SLOT_INPUT && ($strongThis = $weakThis->get()) !== null){
|
||||
$strongThis->regenerateOptions();
|
||||
}
|
||||
},
|
||||
onContentChange: static function() use ($weakThis) : void{
|
||||
if(($strongThis = $weakThis->get()) !== null){
|
||||
$strongThis->regenerateOptions();
|
||||
}
|
||||
}
|
||||
);
|
||||
$this->inventory->getListeners()->add($this->listener);
|
||||
}
|
||||
|
||||
public function __destruct(){
|
||||
$this->inventory->getListeners()->remove($this->listener);
|
||||
}
|
||||
|
||||
private function regenerateOptions() : void{
|
||||
$this->options = [];
|
||||
$item = $this->getInput();
|
||||
$options = Helper::generateOptions($this->holder, $item, $this->viewer->getEnchantmentSeed());
|
||||
|
||||
$event = new PlayerEnchantingOptionsRequestEvent($this->viewer, $this, $options);
|
||||
$event->call();
|
||||
if(!$event->isCancelled() && count($event->getOptions()) > 0){
|
||||
$this->options = array_values($event->getOptions());
|
||||
$this->viewer->getNetworkSession()->getInvManager()?->syncEnchantingTableOptions($this->options);
|
||||
}
|
||||
}
|
||||
|
||||
public function getInput() : Item{
|
||||
return $this->inventory->getItem(self::SLOT_INPUT);
|
||||
}
|
||||
|
||||
public function getLapis() : Item{
|
||||
return $this->inventory->getItem(self::SLOT_LAPIS);
|
||||
}
|
||||
|
||||
public function getOutput(int $optionId) : ?Item{
|
||||
$option = $this->getOption($optionId);
|
||||
return $option === null ? null : Helper::enchantItem($this->getInput(), $option->getEnchantments());
|
||||
}
|
||||
|
||||
public function getOption(int $optionId) : ?EnchantingOption{
|
||||
return $this->options[$optionId] ?? null;
|
||||
}
|
||||
}
|
@ -21,51 +21,51 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
namespace pocketmine\block\inventory\window;
|
||||
|
||||
use pocketmine\crafting\FurnaceType;
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
class FurnaceInventory extends SimpleInventory implements BlockInventory{
|
||||
use BlockInventoryTrait;
|
||||
|
||||
final class FurnaceInventoryWindow extends BlockInventoryWindow{
|
||||
public const SLOT_INPUT = 0;
|
||||
public const SLOT_FUEL = 1;
|
||||
public const SLOT_RESULT = 2;
|
||||
|
||||
public function __construct(
|
||||
Player $viewer,
|
||||
Inventory $inventory,
|
||||
Position $holder,
|
||||
private FurnaceType $furnaceType
|
||||
){
|
||||
$this->holder = $holder;
|
||||
parent::__construct(3);
|
||||
parent::__construct($viewer, $inventory, $holder);
|
||||
}
|
||||
|
||||
public function getFurnaceType() : FurnaceType{ return $this->furnaceType; }
|
||||
|
||||
public function getResult() : Item{
|
||||
return $this->getItem(self::SLOT_RESULT);
|
||||
return $this->inventory->getItem(self::SLOT_RESULT);
|
||||
}
|
||||
|
||||
public function getFuel() : Item{
|
||||
return $this->getItem(self::SLOT_FUEL);
|
||||
return $this->inventory->getItem(self::SLOT_FUEL);
|
||||
}
|
||||
|
||||
public function getSmelting() : Item{
|
||||
return $this->getItem(self::SLOT_INPUT);
|
||||
return $this->inventory->getItem(self::SLOT_INPUT);
|
||||
}
|
||||
|
||||
public function setResult(Item $item) : void{
|
||||
$this->setItem(self::SLOT_RESULT, $item);
|
||||
$this->inventory->setItem(self::SLOT_RESULT, $item);
|
||||
}
|
||||
|
||||
public function setFuel(Item $item) : void{
|
||||
$this->setItem(self::SLOT_FUEL, $item);
|
||||
$this->inventory->setItem(self::SLOT_FUEL, $item);
|
||||
}
|
||||
|
||||
public function setSmelting(Item $item) : void{
|
||||
$this->setItem(self::SLOT_INPUT, $item);
|
||||
$this->inventory->setItem(self::SLOT_INPUT, $item);
|
||||
}
|
||||
}
|
@ -21,10 +21,8 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
namespace pocketmine\block\inventory\window;
|
||||
|
||||
use pocketmine\world\Position;
|
||||
final class HopperInventoryWindow extends BlockInventoryWindow{
|
||||
|
||||
interface BlockInventory{
|
||||
public function getHolder() : Position;
|
||||
}
|
@ -21,21 +21,23 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
namespace pocketmine\block\inventory\window;
|
||||
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\inventory\TemporaryInventory;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\player\TemporaryInventoryWindow;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
final class LoomInventory extends SimpleInventory implements BlockInventory, TemporaryInventory{
|
||||
use BlockInventoryTrait;
|
||||
final class LoomInventoryWindow extends BlockInventoryWindow implements TemporaryInventoryWindow{
|
||||
|
||||
public const SLOT_BANNER = 0;
|
||||
public const SLOT_DYE = 1;
|
||||
public const SLOT_PATTERN = 2;
|
||||
|
||||
public function __construct(Position $holder, int $size = 3){
|
||||
$this->holder = $holder;
|
||||
parent::__construct($size);
|
||||
public function __construct(
|
||||
Player $viewer,
|
||||
Position $holder
|
||||
){
|
||||
parent::__construct($viewer, new SimpleInventory(3), $holder);
|
||||
}
|
||||
}
|
@ -21,16 +21,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
namespace pocketmine\block\inventory\window;
|
||||
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\player\TemporaryInventoryWindow;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
class HopperInventory extends SimpleInventory implements BlockInventory{
|
||||
use BlockInventoryTrait;
|
||||
|
||||
public function __construct(Position $holder, int $size = 5){
|
||||
$this->holder = $holder;
|
||||
parent::__construct($size);
|
||||
final class SmithingTableInventoryWindow extends BlockInventoryWindow implements TemporaryInventoryWindow{
|
||||
public function __construct(Player $viewer, Position $holder){
|
||||
parent::__construct($viewer, new SimpleInventory(3), $holder);
|
||||
}
|
||||
}
|
@ -21,19 +21,17 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\inventory;
|
||||
namespace pocketmine\block\inventory\window;
|
||||
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\inventory\TemporaryInventory;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\player\TemporaryInventoryWindow;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
class StonecutterInventory extends SimpleInventory implements BlockInventory, TemporaryInventory{
|
||||
use BlockInventoryTrait;
|
||||
|
||||
final class StonecutterInventoryWindow extends BlockInventoryWindow implements TemporaryInventoryWindow{
|
||||
public const SLOT_INPUT = 0;
|
||||
|
||||
public function __construct(Position $holder){
|
||||
$this->holder = $holder;
|
||||
parent::__construct(1);
|
||||
public function __construct(Player $viewer, Position $holder){
|
||||
parent::__construct($viewer, new SimpleInventory(1), $holder);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user