Files
PocketMine-MP/src/block/tile/ChiseledBookshelf.php
Dylan K. Taylor ef3d16597a Revert "Chest block now has responsibility for configuring double chest inventories"
This reverts commit 1d2b52732e.

I hadn't considered that the likes of plugins and hoppers need to be
able to interact with double chest inventories as well as players.

If we were to move this logic to the Block side, we'd have to expose
APIs on the Chest block to get the correct inventory lazily. I'm not
sure I want to commit to having getInventory() on the block right now,
as we can't guarantee it's available (see problems around Campfire
inventory on the block).

Short term, it'll probably be better to just expose the logic in
block\Chest for deciding which side the inventories should be on.
2024-12-07 16:04:50 +00:00

140 lines
4.2 KiB
PHP

<?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\tile;
use pocketmine\block\utils\ChiseledBookshelfSlot;
use pocketmine\data\bedrock\item\SavedItemData;
use pocketmine\data\bedrock\item\SavedItemStackData;
use pocketmine\data\SavedDataLoadingException;
use pocketmine\inventory\SimpleInventory;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\world\World;
use function count;
class ChiseledBookshelf extends Tile implements ContainerTile{
use ContainerTileTrait;
private const TAG_LAST_INTERACTED_SLOT = "LastInteractedSlot"; //TAG_Int
private SimpleInventory $inventory;
private ?ChiseledBookshelfSlot $lastInteractedSlot = null;
public function __construct(World $world, Vector3 $pos){
parent::__construct($world, $pos);
$this->inventory = new SimpleInventory(count(ChiseledBookshelfSlot::cases()));
}
public function getInventory() : SimpleInventory{
return $this->inventory;
}
public function getRealInventory() : SimpleInventory{
return $this->inventory;
}
public function getLastInteractedSlot() : ?ChiseledBookshelfSlot{
return $this->lastInteractedSlot;
}
public function setLastInteractedSlot(?ChiseledBookshelfSlot $lastInteractedSlot) : void{
$this->lastInteractedSlot = $lastInteractedSlot;
}
public function readSaveData(CompoundTag $nbt) : void{
$this->loadItems($nbt);
$lastInteractedSlot = $nbt->getInt(self::TAG_LAST_INTERACTED_SLOT, 0);
if($lastInteractedSlot !== 0){
$this->lastInteractedSlot = ChiseledBookshelfSlot::tryFrom($lastInteractedSlot - 1);
}
}
protected function writeSaveData(CompoundTag $nbt) : void{
$this->saveItems($nbt);
$nbt->setInt(self::TAG_LAST_INTERACTED_SLOT, $this->lastInteractedSlot !== null ?
$this->lastInteractedSlot->value + 1 :
0
);
}
protected function loadItems(CompoundTag $tag) : void{
if(($inventoryTag = $tag->getTag(ContainerTile::TAG_ITEMS)) instanceof ListTag && $inventoryTag->getTagType() === NBT::TAG_Compound){
$inventory = $this->getRealInventory();
$listeners = $inventory->getListeners()->toArray();
$inventory->getListeners()->remove(...$listeners); //prevent any events being fired by initialization
$newContents = [];
/** @var CompoundTag $itemNBT */
foreach($inventoryTag as $slot => $itemNBT){
try{
$count = $itemNBT->getByte(SavedItemStackData::TAG_COUNT);
if($count === 0){
continue;
}
$newContents[$slot] = Item::nbtDeserialize($itemNBT);
}catch(SavedDataLoadingException $e){
//TODO: not the best solution
\GlobalLogger::get()->logException($e);
continue;
}
}
$inventory->setContents($newContents);
$inventory->getListeners()->add(...$listeners);
}
if(($lockTag = $tag->getTag(ContainerTile::TAG_LOCK)) instanceof StringTag){
$this->lock = $lockTag->getValue();
}
}
protected function saveItems(CompoundTag $tag) : void{
$items = [];
foreach($this->getRealInventory()->getContents(true) as $slot => $item){
if($item->isNull()){
$items[$slot] = CompoundTag::create()
->setByte(SavedItemStackData::TAG_COUNT, 0)
->setShort(SavedItemData::TAG_DAMAGE, 0)
->setString(SavedItemData::TAG_NAME, "")
->setByte(SavedItemStackData::TAG_WAS_PICKED_UP, 0);
}else{
$items[$slot] = $item->nbtSerialize();
}
}
$tag->setTag(ContainerTile::TAG_ITEMS, new ListTag($items, NBT::TAG_Compound));
if($this->lock !== null){
$tag->setString(ContainerTile::TAG_LOCK, $this->lock);
}
}
}