Revert "Chest block now has responsibility for configuring double chest inventories"

This reverts commit 1d2b52732e3c475ddc2bab4e45726d22850e3d5c.

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.
This commit is contained in:
Dylan K. Taylor 2024-12-07 16:04:50 +00:00
parent b5a69c829d
commit ef3d16597a
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
11 changed files with 66 additions and 37 deletions

View File

@ -109,30 +109,22 @@ class Chest extends Transparent implements AnimatedContainer{
$world = $this->position->getWorld();
$chest = $world->getTile($this->position);
if($chest instanceof TileChest){
[$pairOnLeft, $pair] = $this->locatePair($this->position) ?? [false, null];
if(
!$this->getSide(Facing::UP)->isTransparent() ||
(($pair = $chest->getPair()) !== null && !$pair->getBlock()->getSide(Facing::UP)->isTransparent()) ||
($pair !== null && !$pair->getBlock()->getSide(Facing::UP)->isTransparent()) ||
!$chest->canOpenWith($item->getCustomName())
){
return true;
}
$window = null;
if($chest->isPaired()){
$info = $this->locatePair($this->position);
if($info !== null){
[$clockwise, $pair] = $info;
[$left, $right] = $clockwise ? [$pair, $chest] : [$chest, $pair];
if($pair !== null){
[$left, $right] = $pairOnLeft ? [$pair->getPosition(), $this->position] : [$this->position, $pair->getPosition()];
$doubleInventory = $left->getDoubleInventory() ?? $right->getDoubleInventory();
if($doubleInventory === null){
$doubleInventory = new DoubleChestInventory($left->getInventory(), $right->getInventory());
$left->setDoubleInventory($doubleInventory);
$right->setDoubleInventory($doubleInventory);
}
$window = new DoubleChestInventoryWindow($player, $doubleInventory, $left->getPosition(), $right->getPosition());
}
//TODO: we should probably construct DoubleChestInventory here directly too using the same logic
//right now it uses some weird logic in TileChest which produces incorrect results
//however I'm not sure if this is currently possible
$window = new DoubleChestInventoryWindow($player, $chest->getInventory(), $left, $right);
}
$player->setCurrentWindow($window ?? new BlockInventoryWindow($player, $chest->getInventory(), $this->position));
@ -146,15 +138,6 @@ class Chest extends Transparent implements AnimatedContainer{
return 300;
}
protected function getContainerViewerCount() : int{
$tile = $this->position->getWorld()->getTile($this->position);
if($tile instanceof TileChest){
$inventory = $tile->getDoubleInventory() ?? $tile->getInventory();
return count($inventory->getViewers());
}
return 0;
}
protected function getContainerOpenSound() : Sound{
return new ChestOpenSound();
}

View File

@ -54,6 +54,10 @@ class Barrel extends Spawnable implements ContainerTile, Nameable{
return $this->inventory;
}
public function getRealInventory() : Inventory{
return $this->inventory;
}
public function getDefaultName() : string{
return "Barrel";
}

View File

@ -105,6 +105,10 @@ class BrewingStand extends Spawnable implements ContainerTile, Nameable{
return $this->inventory;
}
public function getRealInventory() : Inventory{
return $this->inventory;
}
private function checkFuel(Item $item) : void{
$ev = new BrewingFuelUseEvent($this);
if(!$item->equals(VanillaItems::BLAZE_POWDER(), true, false)){

View File

@ -59,6 +59,10 @@ class Campfire extends Spawnable implements ContainerTile{
return $this->inventory;
}
public function getRealInventory() : Inventory{
return $this->inventory;
}
/**
* @return int[]
* @phpstan-return array<int, int>

View File

@ -113,14 +113,15 @@ class Chest extends Spawnable implements ContainerTile, Nameable{
$this->containerTraitBlockDestroyedHook();
}
public function getInventory() : Inventory{
return $this->inventory;
public function getInventory() : Inventory|DoubleChestInventory{
if($this->isPaired() && $this->doubleInventory === null){
$this->checkPairing();
}
return $this->doubleInventory instanceof DoubleChestInventory ? $this->doubleInventory : $this->inventory;
}
public function getDoubleInventory() : ?DoubleChestInventory{ return $this->doubleInventory; }
public function setDoubleInventory(?DoubleChestInventory $doubleChestInventory) : void{
$this->doubleInventory = $doubleChestInventory;
public function getRealInventory() : Inventory{
return $this->inventory;
}
protected function checkPairing() : void{
@ -131,7 +132,18 @@ class Chest extends Spawnable implements ContainerTile, Nameable{
}elseif(($pair = $this->getPair()) instanceof Chest){
if(!$pair->isPaired()){
$pair->createPair($this);
$this->doubleInventory = $pair->doubleInventory = null;
$pair->checkPairing();
}
if($this->doubleInventory === null){
if($pair->doubleInventory !== null){
$this->doubleInventory = $pair->doubleInventory;
}else{
if(($pair->position->x + ($pair->position->z << 15)) > ($this->position->x + ($this->position->z << 15))){ //Order them correctly
$this->doubleInventory = $pair->doubleInventory = new DoubleChestInventory($pair->inventory, $this->inventory);
}else{
$this->doubleInventory = $pair->doubleInventory = new DoubleChestInventory($this->inventory, $pair->inventory);
}
}
}
}else{
$this->doubleInventory = null;

View File

@ -55,6 +55,10 @@ class ChiseledBookshelf extends Tile implements ContainerTile{
return $this->inventory;
}
public function getRealInventory() : SimpleInventory{
return $this->inventory;
}
public function getLastInteractedSlot() : ?ChiseledBookshelfSlot{
return $this->lastInteractedSlot;
}
@ -83,7 +87,7 @@ class ChiseledBookshelf extends Tile implements ContainerTile{
protected function loadItems(CompoundTag $tag) : void{
if(($inventoryTag = $tag->getTag(ContainerTile::TAG_ITEMS)) instanceof ListTag && $inventoryTag->getTagType() === NBT::TAG_Compound){
$inventory = $this->inventory;
$inventory = $this->getRealInventory();
$listeners = $inventory->getListeners()->toArray();
$inventory->getListeners()->remove(...$listeners); //prevent any events being fired by initialization
@ -114,7 +118,7 @@ class ChiseledBookshelf extends Tile implements ContainerTile{
protected function saveItems(CompoundTag $tag) : void{
$items = [];
foreach($this->inventory->getContents(true) as $slot => $item){
foreach($this->getRealInventory()->getContents(true) as $slot => $item){
if($item->isNull()){
$items[$slot] = CompoundTag::create()
->setByte(SavedItemStackData::TAG_COUNT, 0)

View File

@ -23,12 +23,15 @@ declare(strict_types=1);
namespace pocketmine\block\tile;
use pocketmine\inventory\Inventory;
use pocketmine\inventory\InventoryHolder;
interface ContainerTile extends InventoryHolder{
public const TAG_ITEMS = "Items";
public const TAG_LOCK = "Lock";
public function getRealInventory() : Inventory;
/**
* Returns whether this container can be opened by an item with the given custom name.
*/

View File

@ -25,6 +25,7 @@ namespace pocketmine\block\tile;
use pocketmine\data\bedrock\item\SavedItemStackData;
use pocketmine\data\SavedDataLoadingException;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\CompoundTag;
@ -39,9 +40,11 @@ trait ContainerTileTrait{
/** @var string|null */
private $lock = null;
abstract public function getRealInventory() : Inventory;
protected function loadItems(CompoundTag $tag) : void{
if(($inventoryTag = $tag->getTag(ContainerTile::TAG_ITEMS)) instanceof ListTag && $inventoryTag->getTagType() === NBT::TAG_Compound){
$inventory = $this->getInventory();
$inventory = $this->getRealInventory();
$listeners = $inventory->getListeners()->toArray();
$inventory->getListeners()->remove(...$listeners); //prevent any events being fired by initialization
@ -68,7 +71,7 @@ trait ContainerTileTrait{
protected function saveItems(CompoundTag $tag) : void{
$items = [];
foreach($this->getInventory()->getContents() as $slot => $item){
foreach($this->getRealInventory()->getContents() as $slot => $item){
$items[] = $item->nbtSerialize($slot);
}
@ -95,7 +98,7 @@ trait ContainerTileTrait{
* @see Tile::onBlockDestroyedHook()
*/
protected function onBlockDestroyedHook() : void{
$inv = $this->getInventory();
$inv = $this->getRealInventory();
$pos = $this->getPosition();
$world = $pos->getWorld();

View File

@ -91,6 +91,10 @@ abstract class Furnace extends Spawnable implements ContainerTile, Nameable{
return $this->inventory;
}
public function getRealInventory() : Inventory{
return $this->getInventory();
}
protected function checkFuel(Item $fuel) : void{
$ev = new FurnaceBurnEvent($this, $fuel, $fuel->getFuelTime());
$ev->call();

View File

@ -65,4 +65,8 @@ class Hopper extends Spawnable implements ContainerTile, Nameable{
public function getInventory() : Inventory{
return $this->inventory;
}
public function getRealInventory() : Inventory{
return $this->inventory;
}
}

View File

@ -104,6 +104,10 @@ class ShulkerBox extends Spawnable implements ContainerTile, Nameable{
return $this->inventory;
}
public function getRealInventory() : Inventory{
return $this->inventory;
}
public function getDefaultName() : string{
return "Shulker Box";
}