Use SplFixedArrays in inventory, added more typehints and cleaned up some duplicated code

This commit is contained in:
Dylan K. Taylor
2017-08-09 13:12:07 +01:00
parent 75644b5df2
commit 260179197b
9 changed files with 152 additions and 175 deletions

View File

@ -36,13 +36,11 @@ abstract class BaseInventory implements Inventory{
/** @var int */
protected $maxStackSize = Inventory::MAX_STACK;
/** @var int */
protected $size;
/** @var string */
protected $name;
/** @var string */
protected $title;
/** @var Item[] */
/** @var \SplFixedArray<Item> */
protected $slots = [];
/** @var Player[] */
protected $viewers = [];
@ -58,7 +56,7 @@ abstract class BaseInventory implements Inventory{
public function __construct(InventoryHolder $holder, array $items = [], int $size = null, string $title = null){
$this->holder = $holder;
$this->size = $size ?? $this->getDefaultSize();
$this->slots = new \SplFixedArray($size ?? $this->getDefaultSize());
$this->title = $title ?? $this->getName();
$this->setContents($items);
@ -76,12 +74,22 @@ abstract class BaseInventory implements Inventory{
*/
abstract public function getNetworkType() : int;
/**
* Returns the size of the inventory.
* @return int
*/
public function getSize() : int{
return $this->size;
return $this->slots->getSize();
}
/**
* Sets the new size of the inventory.
* WARNING: If the size is smaller, any items past the new size will be lost.
*
* @param int $size
*/
public function setSize(int $size){
$this->size = $size;
$this->slots->setSize($size);
}
abstract public function getDefaultSize() : int;
@ -91,41 +99,41 @@ abstract class BaseInventory implements Inventory{
}
public function getItem(int $index) : Item{
assert($index >= 0, "Inventory slot should not be negative");
return isset($this->slots[$index]) ? clone $this->slots[$index] : Item::get(Item::AIR, 0, 0);
return $this->slots[$index] !== null ? clone $this->slots[$index] : Item::get(Item::AIR, 0, 0);
}
public function getContents() : array{
return $this->slots;
return $this->slots->toArray();
}
/**
* @param Item[] $items
*/
public function setContents(array $items){
if(count($items) > $this->size){
$items = array_slice($items, 0, $this->size, true);
if(count($items) > $this->getSize()){
$items = array_slice($items, 0, $this->getSize(), true);
}
for($i = 0; $i < $this->size; ++$i){
for($i = 0, $size = $this->getSize(); $i < $size; ++$i){
if(!isset($items[$i])){
if(isset($this->slots[$i])){
$this->clear($i);
if($this->slots[$i] !== null){
$this->clear($i, false);
}
}else{
if(!$this->setItem($i, $items[$i])){
$this->clear($i);
if(!$this->setItem($i, $items[$i], false)){
$this->clear($i, false);
}
}
}
$this->sendContents($this->getViewers());
}
public function setItem(int $index, Item $item) : bool{
$item = clone $item;
if($index < 0 or $index >= $this->size){
return false;
}elseif($item->getId() === 0 or $item->getCount() <= 0){
return $this->clear($index);
public function setItem(int $index, Item $item, bool $send = true) : bool{
if($item->isNull()){
$item = Item::get(Item::AIR, 0, 0);
}else{
$item = clone $item;
}
$holder = $this->getHolder();
@ -139,8 +147,8 @@ abstract class BaseInventory implements Inventory{
}
$old = $this->getItem($index);
$this->slots[$index] = clone $item;
$this->onSlotChange($index, $old);
$this->slots[$index] = $item->isNull() ? null : $item;
$this->onSlotChange($index, $old, $send);
return true;
}
@ -200,8 +208,8 @@ abstract class BaseInventory implements Inventory{
}
public function firstEmpty() : int{
for($i = 0; $i < $this->size; ++$i){
if($this->getItem($i)->getId() === Item::AIR){
foreach($this->slots as $i => $slot){
if($slot === null or $slot->isNull()){
return $i;
}
}
@ -324,35 +332,16 @@ abstract class BaseInventory implements Inventory{
return $itemSlots;
}
public function clear(int $index) : bool{
if(isset($this->slots[$index])){
$item = Item::get(Item::AIR, 0, 0);
$old = $this->slots[$index];
$holder = $this->getHolder();
if($holder instanceof Entity){
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityInventoryChangeEvent($holder, $old, $item, $index));
if($ev->isCancelled()){
$this->sendSlot($index, $this->getViewers());
return false;
}
$item = $ev->getNewItem();
}
if($item->getId() !== Item::AIR){
$this->slots[$index] = clone $item;
}else{
unset($this->slots[$index]);
}
$this->onSlotChange($index, $old);
}
return true;
public function clear(int $index, bool $send = true) : bool{
return $this->setItem($index, Item::get(Item::AIR, 0, 0), $send);
}
public function clearAll(){
foreach($this->getContents() as $index => $i){
$this->clear($index);
for($i = 0, $size = $this->getSize(); $i < $size; ++$i){
$this->clear($i, false);
}
$this->sendContents($this->getViewers());
}
/**
@ -392,8 +381,10 @@ abstract class BaseInventory implements Inventory{
unset($this->viewers[spl_object_hash($who)]);
}
public function onSlotChange($index, $before){
$this->sendSlot($index, $this->getViewers());
public function onSlotChange(int $index, Item $before, bool $send){
if($send){
$this->sendSlot($index, $this->getViewers());
}
}
@ -424,7 +415,7 @@ abstract class BaseInventory implements Inventory{
* @param int $index
* @param Player|Player[] $target
*/
public function sendSlot($index, $target){
public function sendSlot(int $index, $target){
if($target instanceof Player){
$target = [$target];
}