diff --git a/src/pocketmine/tile/Chest.php b/src/pocketmine/tile/Chest.php index 7bee9843b..1b723dad0 100644 --- a/src/pocketmine/tile/Chest.php +++ b/src/pocketmine/tile/Chest.php @@ -36,7 +36,7 @@ use pocketmine\nbt\tag\ListTag; use pocketmine\Player; class Chest extends Spawnable implements InventoryHolder, Container, Nameable{ - use NameableTrait; + use NameableTrait, ContainerTrait; const TAG_PAIRX = "pairx"; const TAG_PAIRZ = "pairz"; @@ -50,14 +50,7 @@ class Chest extends Spawnable implements InventoryHolder, Container, Nameable{ public function __construct(Level $level, CompoundTag $nbt){ parent::__construct($level, $nbt); $this->inventory = new ChestInventory($this); - - if(!$this->namedtag->hasTag("Items", ListTag::class)){ - $this->namedtag->setTag(new ListTag("Items", [], NBT::TAG_Compound)); - } - - for($i = 0; $i < $this->getSize(); ++$i){ - $this->inventory->setItem($i, $this->getItem($i), false); - } + $this->loadItems(); } public function close() : void{ @@ -78,10 +71,7 @@ class Chest extends Spawnable implements InventoryHolder, Container, Nameable{ public function saveNBT() : void{ parent::saveNBT(); - $this->namedtag->setTag(new ListTag("Items", [], NBT::TAG_Compound)); - for($index = 0; $index < $this->getSize(); ++$index){ - $this->setItem($index, $this->inventory->getItem($index)); - } + $this->saveItems(); } /** @@ -91,72 +81,6 @@ class Chest extends Spawnable implements InventoryHolder, Container, Nameable{ return 27; } - /** - * @param $index - * - * @return int - */ - protected function getSlotIndex(int $index) : int{ - $items = $this->namedtag->getListTag("Items"); - assert($items instanceof ListTag); - foreach($items as $i => $slot){ - /** @var CompoundTag $slot */ - if($slot->getByte("Slot") === $index){ - return (int) $i; - } - } - - return -1; - } - - /** - * This method should not be used by plugins, use the Inventory - * - * @param int $index - * - * @return Item - */ - public function getItem(int $index) : Item{ - $i = $this->getSlotIndex($index); - if($i < 0){ - return ItemFactory::get(Item::AIR, 0, 0); - }else{ - return Item::nbtDeserialize($this->namedtag->getListTag("Items")[$i]); - } - } - - /** - * This method should not be used by plugins, use the Inventory - * - * @param int $index - * @param Item $item - */ - public function setItem(int $index, Item $item){ - $i = $this->getSlotIndex($index); - - $d = $item->nbtSerialize($index); - - $items = $this->namedtag->getListTag("Items"); - assert($items instanceof ListTag); - - if($item->isNull()){ - if($i >= 0){ - unset($items[$i]); - } - }elseif($i < 0){ - for($i = 0; $i <= $this->getSize(); ++$i){ - if(!isset($items[$i])){ - break; - } - } - $items[$i] = $d; - }else{ - $items[$i] = $d; - } - - $this->namedtag->setTag($items); - } - /** * @return ChestInventory|DoubleChestInventory */ diff --git a/src/pocketmine/tile/Container.php b/src/pocketmine/tile/Container.php index 261e057b9..34e358237 100644 --- a/src/pocketmine/tile/Container.php +++ b/src/pocketmine/tile/Container.php @@ -27,6 +27,7 @@ use pocketmine\inventory\Inventory; use pocketmine\item\Item; interface Container{ + const TAG_ITEMS = "Items"; /** * @param int $index diff --git a/src/pocketmine/tile/ContainerTrait.php b/src/pocketmine/tile/ContainerTrait.php new file mode 100644 index 000000000..1b472c864 --- /dev/null +++ b/src/pocketmine/tile/ContainerTrait.php @@ -0,0 +1,135 @@ +getNBT()->getListTag(Container::TAG_ITEMS) as $i => $slot){ + /** @var CompoundTag $slot */ + if($slot->getByte("Slot") === $index){ + return (int) $i; + } + } + + return -1; + } + + /** + * This method should not be used by plugins, use the Inventory + * + * @param int $index + * + * @return Item + */ + public function getItem(int $index) : Item{ + $i = $this->getSlotIndex($index); + /** @var CompoundTag|null $itemTag */ + $itemTag = $this->getNBT()->getListTag(Container::TAG_ITEMS)[$i] ?? null; + if($itemTag !== null){ + return Item::nbtDeserialize($itemTag); + } + + return ItemFactory::get(Item::AIR, 0, 0); + } + + /** + * This method should not be used by plugins, use the Inventory + * + * @param int $index + * @param Item $item + */ + public function setItem(int $index, Item $item) : void{ + $i = $this->getSlotIndex($index); + + $d = $item->nbtSerialize($index); + + $items = $this->getNBT()->getListTag(Container::TAG_ITEMS); + assert($items instanceof ListTag); + + if($item->isNull()){ + if($i >= 0){ + unset($items[$i]); + } + }elseif($i < 0){ + for($i = 0; $i <= $this->getSize(); ++$i){ + if(!isset($items[$i])){ + break; + } + } + $items[$i] = $d; + }else{ + $items[$i] = $d; + } + + $this->getNBT()->setTag($items); + } + + protected function loadItems() : void{ + if(!$this->getNBT()->hasTag(Container::TAG_ITEMS, ListTag::class)){ + $this->getNBT()->setTag(new ListTag(Container::TAG_ITEMS, [], NBT::TAG_Compound)); + } + + $inventory = $this->getInventory(); + for($i = 0, $size = $this->getSize(); $i < $size; ++$i){ + $inventory->setItem($i, $this->getItem($i)); + } + } + + protected function saveItems() : void{ + $this->getNBT()->setTag(new ListTag(Container::TAG_ITEMS, [], NBT::TAG_Compound)); + + $inventory = $this->getInventory(); + for($i = 0, $size = $this->getSize(); $i < $size; ++$i){ + $this->setItem($i, $inventory->getItem($i)); + } + } +} \ No newline at end of file diff --git a/src/pocketmine/tile/Furnace.php b/src/pocketmine/tile/Furnace.php index d17518e75..9b91a93a0 100644 --- a/src/pocketmine/tile/Furnace.php +++ b/src/pocketmine/tile/Furnace.php @@ -42,7 +42,7 @@ use pocketmine\network\mcpe\protocol\ContainerSetDataPacket; use pocketmine\Player; class Furnace extends Spawnable implements InventoryHolder, Container, Nameable{ - use NameableTrait; + use NameableTrait, ContainerTrait; const TAG_BURN_TIME = "BurnTime"; const TAG_COOK_TIME = "CookTime"; @@ -76,14 +76,7 @@ class Furnace extends Spawnable implements InventoryHolder, Container, Nameable{ parent::__construct($level, $nbt); $this->inventory = new FurnaceInventory($this); - - if(!($this->namedtag->getTag("Items") instanceof ListTag)){ - $this->namedtag->setTag(new ListTag("Items", [], NBT::TAG_Compound)); - } - - for($i = 0; $i < $this->getSize(); ++$i){ - $this->inventory->setItem($i, $this->getItem($i), false); - } + $this->loadItems(); if($this->namedtag->getShort(self::TAG_BURN_TIME) > 0){ $this->scheduleUpdate(); @@ -108,10 +101,7 @@ class Furnace extends Spawnable implements InventoryHolder, Container, Nameable{ public function saveNBT() : void{ parent::saveNBT(); - $this->namedtag->setTag(new ListTag("Items", [], NBT::TAG_Compound)); - for($index = 0; $index < $this->getSize(); ++$index){ - $this->setItem($index, $this->inventory->getItem($index)); - } + $this->saveItems(); } /** @@ -121,70 +111,6 @@ class Furnace extends Spawnable implements InventoryHolder, Container, Nameable{ return 3; } - /** - * @param $index - * - * @return int - */ - protected function getSlotIndex(int $index) : int{ - foreach($this->namedtag->getListTag("Items") as $i => $slot){ - /** @var CompoundTag $slot */ - if($slot->getByte("Slot") === $index){ - return (int) $i; - } - } - - return -1; - } - - /** - * This method should not be used by plugins, use the Inventory - * - * @param int $index - * - * @return Item - */ - public function getItem(int $index) : Item{ - $i = $this->getSlotIndex($index); - if($i < 0){ - return ItemFactory::get(Item::AIR, 0, 0); - }else{ - return Item::nbtDeserialize($this->namedtag->getListTag("Items")[$i]); - } - } - - /** - * This method should not be used by plugins, use the Inventory - * - * @param int $index - * @param Item $item - */ - public function setItem(int $index, Item $item){ - $i = $this->getSlotIndex($index); - - $d = $item->nbtSerialize($index); - - $items = $this->namedtag->getListTag("Items"); - assert($items instanceof ListTag); - - if($item->isNull()){ - if($i >= 0){ - unset($items[$i]); - } - }elseif($i < 0){ - for($i = 0; $i <= $this->getSize(); ++$i){ - if(!isset($items[$i])){ - break; - } - } - $items[$i] = $d; - }else{ - $items[$i] = $d; - } - - $this->namedtag->setTag($items); - } - /** * @return FurnaceInventory */