diff --git a/src/pocketmine/inventory/BaseInventory.php b/src/pocketmine/inventory/BaseInventory.php new file mode 100644 index 000000000..4fda1504d --- /dev/null +++ b/src/pocketmine/inventory/BaseInventory.php @@ -0,0 +1,293 @@ + */ + protected $viewers = []; + /** @var InventoryHolder */ + protected $holder; + + /** + * @param InventoryHolder $holder + * @param InventoryType $type + * @param Item[] $items + * @param int $overrideSize + * @param string $overrideTitle + */ + public function __construct(InventoryHolder $holder, InventoryType $type, array $items = [], $overrideSize = null, $overrideTitle = null){ + $this->holder = $holder; + $this->viewers = new \SplObjectStorage(); + + //A holder can be a plugin, or an entity + if($this->holder instanceof Player){ + $this->viewers->attach($this->holder); + } + + + $this->type = $type; + if($overrideSize !== null){ + $this->size = (int) $overrideSize; + }else{ + $this->size = $this->type->getDefaultSize(); + } + + if($overrideTitle !== null){ + $this->title = $overrideTitle; + }else{ + $this->title = $this->type->getDefaultTitle(); + } + + $this->name = $this->type->getDefaultTitle(); + + $this->setContents($items); + } + + public function getSize(){ + return $this->size; + } + + public function getMaxStackSize(){ + return $this->maxStackSize; + } + + public function getName(){ + return $this->name; + } + + public function getTitle(){ + return $this->title; + } + + public function getItem($index){ + return isset($this->slots[$index]) ? $this->slots[$index] : null; + } + + public function getContents(){ + return $this->slots; + } + + /** + * @param Item[] $items + */ + public function setContents(array $items){ + if(count($items) > $this->size){ + $items = array_slice($items, 0, $this->size, true); + } + + for($i = 0; $i < $this->size; ++$i){ + if(!isset($items[$i])){ + if(isset($this->slots[$i])){ + $this->clear($i); + } + }else{ + $this->setItem($i, $items[$i]); + } + } + } + + public function setItem($index, Item $item){ + if($index < 0 or $index >= $this->size or $item->getID() === 0){ + return; + } + $old = $this->slots[$index]; + $this->slots[$index] = clone $item; + $this->onSlotChange($index, $old); + } + + public function contains(Item $item){ + $count = max(1, $item->getCount()); + $checkDamage = $item->getDamage() === null ? false : true; + foreach($this->slots as $i){ + if($item->equals($i, $checkDamage)){ + $count -= $i->getCount(); + if($count <= 0){ + return true; + } + } + } + + return false; + } + + public function all(Item $item){ + $slots = []; + $checkDamage = $item->getDamage() === null ? false : true; + foreach($this->slots as $index => $i){ + if($item->equals($i, $checkDamage)){ + $slots[$index] = $i; + } + } + + return $slots; + } + + public function remove(Item $item){ + $checkDamage = $item->getDamage() === null ? false : true; + foreach($this->slots as $index => $i){ + if($item->equals($i, $checkDamage)){ + $this->clear($index); + } + } + } + + public function first(Item $item){ + $count = max(1, $item->getCount()); + $checkDamage = $item->getDamage() === null ? false : true; + foreach($this->slots as $index => $i){ + if($item->equals($i, $checkDamage) and $i->getCount() >= $count){ + return $index; + } + } + + return -1; + } + + public function firstEmpty(){ + for($i = 0; $i < $this->size; ++$i){ + if(!isset($this->slots[$i])){ + return $i; + }elseif(!($this->slots[$i] instanceof Item) or $this->slots[$i]->getID() === 0 or $this->slots[$i]->getCount() <= 0){ + unset($this->slots[$i]); + return $i; + } + } + + return -1; + } + + public function addItem(){ + /** @var Item[] $slots */ + $slots = func_get_args(); + for($i = 0; $i < $this->size; ++$i){ + if(!isset($this->slots[$i])){ + $item = $this->slots[$i] = array_shift($slots); + $this->onSlotChange($i, null); + }else{ + $item = $this->slots[$i]; + } + + foreach($slots as $index => $slot){ + if($slot->equals($item, $slot->getDamage() === null ? false : true)){ + if($item->getCount() < $item->getMaxStackSize()){ + $amount = min($item->getMaxStackSize() - $item->getCount(), $slot->getCount()); + $slot->setCount($slot->getCount() - $amount); + $old = clone $item; + $item->setCount($item->getCount() + $amount); + $this->onSlotChange($i, $old); + if($slot->getCount() <= 0){ + unset($slots[$index]); + } + } + } + } + + if(count($slots) === 0){ + break; + } + } + + return $slots; + } + + public function removeItem(){ + /** @var Item[] $slots */ + $slots = func_get_args(); + for($i = 0; $i < $this->size; ++$i){ + if(!isset($this->slots[$i])){ + continue; + }else{ + $item = $this->slots[$i]; + } + + foreach($slots as $index => $slot){ + if($slot->equals($item, $slot->getDamage() === null ? false : true)){ + $amount = min($item->getCount(), $slot->getCount()); + $slot->setCount($slot->getCount() - $amount); + $old = clone $item; + $item->setCount($item->getCount() - $amount); + if($slot->getCount() <= 0){ + unset($slots[$index]); + } + if($item->getCount() <= 0){ + $this->clear($i); + }else{ + $this->onSlotChange($i, $old); + } + } + } + + if(count($slots) === 0){ + break; + } + } + + return $slots; + } + + public function clear($index){ + if(isset($this->slots[$index])){ + $old = $this->slots[$index]; + unset($this->slots[$index]); + $this->onSlotChange($index, $old); + } + } + + public function clearAll(){ + foreach($this->slots as $index => $i){ + $this->clear($index); + } + } + + public function getViewers(){ + $viewers = []; + foreach($this->viewers as $viewer){ + $viewers[] = $viewer; + } + return $viewers; + } + + public function getHolder(){ + return $this->holder; + } + + public function setMaxStackSize($size){ + $this->setMaxStackSize($size); + } + +} \ No newline at end of file diff --git a/src/pocketmine/inventory/Inventory.php b/src/pocketmine/inventory/Inventory.php index fd56c7b71..d602a5974 100644 --- a/src/pocketmine/inventory/Inventory.php +++ b/src/pocketmine/inventory/Inventory.php @@ -58,21 +58,21 @@ interface Inventory{ * * Returns the Items that did not fit * - * @param Item|Item[] $items + * @param Item ...$item * * @return Item[] */ - public function addItem($items); + public function addItem(); /** * Removes the given Item from the inventory. * It will return the Items that couldn't be removed. * - * @param Item|Item[] $items + * @param Item ...$item * * @return Item[] */ - public function removeItem($items); + public function removeItem(); /** * @return Item[] @@ -90,7 +90,8 @@ interface Inventory{ public function contains(Item $item); /** - * Will return all the Items that has the same id and metadata (if not null) + * Will return all the Items that has the same id and metadata (if not null). + * Won't check amount * * @param Item $item * @@ -100,7 +101,7 @@ interface Inventory{ /** * Will return the first slot has the same id and metadata (if not null) as the Item. - * -1 if not found + * -1 if not found, will check amount * * @param Item $item * @@ -152,7 +153,19 @@ interface Inventory{ */ public function getHolder(); + /** + * @param Player $who + */ public function onOpen(Player $who); + /** + * @param Player $who + */ public function onClose(Player $who); + + /** + * @param int $index + * @param Item|null $before + */ + public function onSlotChange($index, $before); }