mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-07-03 00:29:54 +00:00
Use SplFixedArrays in inventory, added more typehints and cleaned up some duplicated code
This commit is contained in:
parent
75644b5df2
commit
260179197b
@ -49,6 +49,7 @@ class AnvilInventory extends ContainerInventory{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This override is here for documentation and code completion purposes only.
|
||||||
* @return FakeBlockMenu
|
* @return FakeBlockMenu
|
||||||
*/
|
*/
|
||||||
public function getHolder(){
|
public function getHolder(){
|
||||||
|
@ -36,13 +36,11 @@ abstract class BaseInventory implements Inventory{
|
|||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
protected $maxStackSize = Inventory::MAX_STACK;
|
protected $maxStackSize = Inventory::MAX_STACK;
|
||||||
/** @var int */
|
|
||||||
protected $size;
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $name;
|
protected $name;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $title;
|
protected $title;
|
||||||
/** @var Item[] */
|
/** @var \SplFixedArray<Item> */
|
||||||
protected $slots = [];
|
protected $slots = [];
|
||||||
/** @var Player[] */
|
/** @var Player[] */
|
||||||
protected $viewers = [];
|
protected $viewers = [];
|
||||||
@ -58,7 +56,7 @@ abstract class BaseInventory implements Inventory{
|
|||||||
public function __construct(InventoryHolder $holder, array $items = [], int $size = null, string $title = null){
|
public function __construct(InventoryHolder $holder, array $items = [], int $size = null, string $title = null){
|
||||||
$this->holder = $holder;
|
$this->holder = $holder;
|
||||||
|
|
||||||
$this->size = $size ?? $this->getDefaultSize();
|
$this->slots = new \SplFixedArray($size ?? $this->getDefaultSize());
|
||||||
$this->title = $title ?? $this->getName();
|
$this->title = $title ?? $this->getName();
|
||||||
|
|
||||||
$this->setContents($items);
|
$this->setContents($items);
|
||||||
@ -76,12 +74,22 @@ abstract class BaseInventory implements Inventory{
|
|||||||
*/
|
*/
|
||||||
abstract public function getNetworkType() : int;
|
abstract public function getNetworkType() : int;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the size of the inventory.
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
public function getSize() : 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){
|
public function setSize(int $size){
|
||||||
$this->size = $size;
|
$this->slots->setSize($size);
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract public function getDefaultSize() : int;
|
abstract public function getDefaultSize() : int;
|
||||||
@ -91,41 +99,41 @@ abstract class BaseInventory implements Inventory{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getItem(int $index) : Item{
|
public function getItem(int $index) : Item{
|
||||||
assert($index >= 0, "Inventory slot should not be negative");
|
return $this->slots[$index] !== null ? clone $this->slots[$index] : Item::get(Item::AIR, 0, 0);
|
||||||
return isset($this->slots[$index]) ? clone $this->slots[$index] : Item::get(Item::AIR, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getContents() : array{
|
public function getContents() : array{
|
||||||
return $this->slots;
|
return $this->slots->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Item[] $items
|
* @param Item[] $items
|
||||||
*/
|
*/
|
||||||
public function setContents(array $items){
|
public function setContents(array $items){
|
||||||
if(count($items) > $this->size){
|
if(count($items) > $this->getSize()){
|
||||||
$items = array_slice($items, 0, $this->size, true);
|
$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($items[$i])){
|
||||||
if(isset($this->slots[$i])){
|
if($this->slots[$i] !== null){
|
||||||
$this->clear($i);
|
$this->clear($i, false);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if(!$this->setItem($i, $items[$i])){
|
if(!$this->setItem($i, $items[$i], false)){
|
||||||
$this->clear($i);
|
$this->clear($i, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->sendContents($this->getViewers());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setItem(int $index, Item $item) : bool{
|
public function setItem(int $index, Item $item, bool $send = true) : bool{
|
||||||
$item = clone $item;
|
if($item->isNull()){
|
||||||
if($index < 0 or $index >= $this->size){
|
$item = Item::get(Item::AIR, 0, 0);
|
||||||
return false;
|
}else{
|
||||||
}elseif($item->getId() === 0 or $item->getCount() <= 0){
|
$item = clone $item;
|
||||||
return $this->clear($index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$holder = $this->getHolder();
|
$holder = $this->getHolder();
|
||||||
@ -139,8 +147,8 @@ abstract class BaseInventory implements Inventory{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$old = $this->getItem($index);
|
$old = $this->getItem($index);
|
||||||
$this->slots[$index] = clone $item;
|
$this->slots[$index] = $item->isNull() ? null : $item;
|
||||||
$this->onSlotChange($index, $old);
|
$this->onSlotChange($index, $old, $send);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -200,8 +208,8 @@ abstract class BaseInventory implements Inventory{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function firstEmpty() : int{
|
public function firstEmpty() : int{
|
||||||
for($i = 0; $i < $this->size; ++$i){
|
foreach($this->slots as $i => $slot){
|
||||||
if($this->getItem($i)->getId() === Item::AIR){
|
if($slot === null or $slot->isNull()){
|
||||||
return $i;
|
return $i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -324,35 +332,16 @@ abstract class BaseInventory implements Inventory{
|
|||||||
return $itemSlots;
|
return $itemSlots;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function clear(int $index) : bool{
|
public function clear(int $index, bool $send = true) : bool{
|
||||||
if(isset($this->slots[$index])){
|
return $this->setItem($index, Item::get(Item::AIR, 0, 0), $send);
|
||||||
$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 clearAll(){
|
public function clearAll(){
|
||||||
foreach($this->getContents() as $index => $i){
|
for($i = 0, $size = $this->getSize(); $i < $size; ++$i){
|
||||||
$this->clear($index);
|
$this->clear($i, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->sendContents($this->getViewers());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -392,8 +381,10 @@ abstract class BaseInventory implements Inventory{
|
|||||||
unset($this->viewers[spl_object_hash($who)]);
|
unset($this->viewers[spl_object_hash($who)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onSlotChange($index, $before){
|
public function onSlotChange(int $index, Item $before, bool $send){
|
||||||
$this->sendSlot($index, $this->getViewers());
|
if($send){
|
||||||
|
$this->sendSlot($index, $this->getViewers());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -424,7 +415,7 @@ abstract class BaseInventory implements Inventory{
|
|||||||
* @param int $index
|
* @param int $index
|
||||||
* @param Player|Player[] $target
|
* @param Player|Player[] $target
|
||||||
*/
|
*/
|
||||||
public function sendSlot($index, $target){
|
public function sendSlot(int $index, $target){
|
||||||
if($target instanceof Player){
|
if($target instanceof Player){
|
||||||
$target = [$target];
|
$target = [$target];
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ class ChestInventory extends ContainerInventory{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This override is here for documentation and code completion purposes only.
|
||||||
* @return Chest
|
* @return Chest
|
||||||
*/
|
*/
|
||||||
public function getHolder(){
|
public function getHolder(){
|
||||||
|
@ -54,6 +54,9 @@ class DoubleChestInventory extends ChestInventory implements InventoryHolder{
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Chest
|
||||||
|
*/
|
||||||
public function getHolder(){
|
public function getHolder(){
|
||||||
return $this->left->getHolder();
|
return $this->left->getHolder();
|
||||||
}
|
}
|
||||||
@ -62,17 +65,17 @@ class DoubleChestInventory extends ChestInventory implements InventoryHolder{
|
|||||||
return $index < $this->left->getSize() ? $this->left->getItem($index) : $this->right->getItem($index - $this->right->getSize());
|
return $index < $this->left->getSize() ? $this->left->getItem($index) : $this->right->getItem($index - $this->right->getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setItem(int $index, Item $item) : bool{
|
public function setItem(int $index, Item $item, bool $send = true) : bool{
|
||||||
return $index < $this->left->getSize() ? $this->left->setItem($index, $item) : $this->right->setItem($index - $this->right->getSize(), $item);
|
return $index < $this->left->getSize() ? $this->left->setItem($index, $item, $send) : $this->right->setItem($index - $this->right->getSize(), $item, $send);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function clear(int $index) : bool{
|
public function clear(int $index, bool $send = true) : bool{
|
||||||
return $index < $this->left->getSize() ? $this->left->clear($index) : $this->right->clear($index - $this->right->getSize());
|
return $index < $this->left->getSize() ? $this->left->clear($index, $send) : $this->right->clear($index - $this->right->getSize(), $send);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getContents() : array{
|
public function getContents() : array{
|
||||||
$contents = [];
|
$contents = [];
|
||||||
for($i = 0; $i < $this->getSize(); ++$i){
|
for($i = 0, $size = $this->getSize(); $i < $size; ++$i){
|
||||||
$contents[$i] = $this->getItem($i);
|
$contents[$i] = $this->getItem($i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,24 +86,24 @@ class DoubleChestInventory extends ChestInventory implements InventoryHolder{
|
|||||||
* @param Item[] $items
|
* @param Item[] $items
|
||||||
*/
|
*/
|
||||||
public function setContents(array $items){
|
public function setContents(array $items){
|
||||||
if(count($items) > $this->size){
|
$size = $this->getSize();
|
||||||
$items = array_slice($items, 0, $this->size, true);
|
if(count($items) > $size){
|
||||||
|
$items = array_slice($items, 0, $size, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$leftSize = $this->left->getSize();
|
||||||
|
|
||||||
for($i = 0; $i < $this->size; ++$i){
|
for($i = 0; $i < $size; ++$i){
|
||||||
if(!isset($items[$i])){
|
if(!isset($items[$i])){
|
||||||
if($i < $this->left->size){
|
if(($i < $leftSize and isset($this->left->slots[$i])) or isset($this->right->slots[$i - $leftSize])){
|
||||||
if(isset($this->left->slots[$i])){
|
$this->clear($i, false);
|
||||||
$this->clear($i);
|
|
||||||
}
|
|
||||||
}elseif(isset($this->right->slots[$i - $this->left->size])){
|
|
||||||
$this->clear($i);
|
|
||||||
}
|
}
|
||||||
}elseif(!$this->setItem($i, $items[$i])){
|
}elseif(!$this->setItem($i, $items[$i], false)){
|
||||||
$this->clear($i);
|
$this->clear($i, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->sendContents($this->getViewers());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onOpen(Player $who){
|
public function onOpen(Player $who){
|
||||||
|
@ -49,6 +49,7 @@ class EnchantInventory extends ContainerInventory{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This override is here for documentation and code completion purposes only.
|
||||||
* @return FakeBlockMenu
|
* @return FakeBlockMenu
|
||||||
*/
|
*/
|
||||||
public function getHolder(){
|
public function getHolder(){
|
||||||
|
@ -48,6 +48,7 @@ class FurnaceInventory extends ContainerInventory{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This override is here for documentation and code completion purposes only.
|
||||||
* @return Furnace
|
* @return Furnace
|
||||||
*/
|
*/
|
||||||
public function getHolder(){
|
public function getHolder(){
|
||||||
@ -102,8 +103,8 @@ class FurnaceInventory extends ContainerInventory{
|
|||||||
return $this->setItem(0, $item);
|
return $this->setItem(0, $item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onSlotChange($index, $before){
|
public function onSlotChange(int $index, Item $before, bool $send){
|
||||||
parent::onSlotChange($index, $before);
|
parent::onSlotChange($index, $before, $send);
|
||||||
|
|
||||||
$this->getHolder()->scheduleUpdate();
|
$this->getHolder()->scheduleUpdate();
|
||||||
}
|
}
|
||||||
|
@ -70,10 +70,11 @@ interface Inventory{
|
|||||||
*
|
*
|
||||||
* @param int $index
|
* @param int $index
|
||||||
* @param Item $item
|
* @param Item $item
|
||||||
|
* @param bool $send
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function setItem(int $index, Item $item) : bool;
|
public function setItem(int $index, Item $item, bool $send = true) : bool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the given Items in the inventory. This will try to fill
|
* Stores the given Items in the inventory. This will try to fill
|
||||||
@ -125,7 +126,7 @@ interface Inventory{
|
|||||||
* @param int $index
|
* @param int $index
|
||||||
* @param Player|Player[] $target
|
* @param Player|Player[] $target
|
||||||
*/
|
*/
|
||||||
public function sendSlot($index, $target);
|
public function sendSlot(int $index, $target);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the inventory contains any Item with the same material data.
|
* Checks if the inventory contains any Item with the same material data.
|
||||||
@ -174,11 +175,12 @@ interface Inventory{
|
|||||||
/**
|
/**
|
||||||
* Will clear a specific slot
|
* Will clear a specific slot
|
||||||
*
|
*
|
||||||
* @param int $index
|
* @param int $index
|
||||||
|
* @param bool $send
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function clear(int $index) : bool;
|
public function clear(int $index, bool $send = true) : bool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all the slots
|
* Clears all the slots
|
||||||
@ -222,6 +224,7 @@ interface Inventory{
|
|||||||
/**
|
/**
|
||||||
* @param int $index
|
* @param int $index
|
||||||
* @param Item $before
|
* @param Item $before
|
||||||
|
* @param bool $send
|
||||||
*/
|
*/
|
||||||
public function onSlotChange($index, $before);
|
public function onSlotChange(int $index, Item $before, bool $send);
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,11 @@ use pocketmine\Server;
|
|||||||
|
|
||||||
class PlayerInventory extends BaseInventory{
|
class PlayerInventory extends BaseInventory{
|
||||||
|
|
||||||
|
/** @var Human */
|
||||||
|
protected $holder;
|
||||||
|
|
||||||
protected $itemInHandIndex = 0;
|
protected $itemInHandIndex = 0;
|
||||||
/** @var int[] */
|
/** @var \SplFixedArray<int> */
|
||||||
protected $hotbar;
|
protected $hotbar;
|
||||||
|
|
||||||
public function __construct(Human $player){
|
public function __construct(Human $player){
|
||||||
@ -74,12 +77,12 @@ class PlayerInventory extends BaseInventory{
|
|||||||
* Called when a client equips a hotbar slot. This method should not be used by plugins.
|
* Called when a client equips a hotbar slot. This method should not be used by plugins.
|
||||||
* This method will call PlayerItemHeldEvent.
|
* This method will call PlayerItemHeldEvent.
|
||||||
*
|
*
|
||||||
* @param int $hotbarSlot Number of the hotbar slot to equip.
|
* @param int $hotbarSlot Number of the hotbar slot to equip.
|
||||||
* @param int|null $inventorySlot Inventory slot to map to the specified hotbar slot. Supply null to make no change to the link.
|
* @param int|null $inventorySlot Inventory slot to map to the specified hotbar slot. Supply null to make no change to the link.
|
||||||
*
|
*
|
||||||
* @return bool if the equipment change was successful, false if not.
|
* @return bool if the equipment change was successful, false if not.
|
||||||
*/
|
*/
|
||||||
public function equipItem(int $hotbarSlot, $inventorySlot = null) : bool{
|
public function equipItem(int $hotbarSlot, int $inventorySlot = null) : bool{
|
||||||
if($inventorySlot === null){
|
if($inventorySlot === null){
|
||||||
$inventorySlot = $this->getHotbarSlotIndex($hotbarSlot);
|
$inventorySlot = $this->getHotbarSlotIndex($hotbarSlot);
|
||||||
}
|
}
|
||||||
@ -110,11 +113,12 @@ class PlayerInventory extends BaseInventory{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the index of the inventory slot mapped to the specified hotbar slot, or -1 if the hotbar slot does not exist.
|
* Returns the index of the inventory slot mapped to the specified hotbar slot, or -1 if the hotbar slot does not exist.
|
||||||
|
*
|
||||||
* @param int $index
|
* @param int $index
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getHotbarSlotIndex($index){
|
public function getHotbarSlotIndex(int $index) : int{
|
||||||
return $this->hotbar[$index] ?? -1;
|
return $this->hotbar[$index] ?? -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,15 +130,16 @@ class PlayerInventory extends BaseInventory{
|
|||||||
*
|
*
|
||||||
* @param int $hotbarSlot
|
* @param int $hotbarSlot
|
||||||
* @param int $inventorySlot
|
* @param int $inventorySlot
|
||||||
|
*
|
||||||
|
* @throws \RuntimeException if the hotbar slot is out of range
|
||||||
|
* @throws \InvalidArgumentException if the inventory slot is out of range
|
||||||
*/
|
*/
|
||||||
public function setHotbarSlotIndex($hotbarSlot, $inventorySlot){
|
public function setHotbarSlotIndex(int $hotbarSlot, int $inventorySlot){
|
||||||
if($hotbarSlot < 0 or $hotbarSlot >= $this->getHotbarSize()){
|
if($inventorySlot < -1 or $inventorySlot >= $this->getSize()){
|
||||||
throw new \InvalidArgumentException("Hotbar slot index \"$hotbarSlot\" is out of range");
|
|
||||||
}elseif($inventorySlot < -1 or $inventorySlot >= $this->getSize()){
|
|
||||||
throw new \InvalidArgumentException("Inventory slot index \"$inventorySlot\" is out of range");
|
throw new \InvalidArgumentException("Inventory slot index \"$inventorySlot\" is out of range");
|
||||||
}
|
}
|
||||||
|
|
||||||
if($inventorySlot !== -1 and ($alreadyEquippedIndex = array_search($inventorySlot, $this->hotbar)) !== false){
|
if($inventorySlot !== -1 and ($alreadyEquippedIndex = array_search($inventorySlot, $this->getHotbar(), true)) !== false){
|
||||||
/* Swap the slots
|
/* Swap the slots
|
||||||
* This assumes that the equipped slot can only be equipped in one other slot
|
* This assumes that the equipped slot can only be equipped in one other slot
|
||||||
* it will not account for ancient bugs where the same slot ended up linked to several hotbar slots.
|
* it will not account for ancient bugs where the same slot ended up linked to several hotbar slots.
|
||||||
@ -161,35 +166,49 @@ class PlayerInventory extends BaseInventory{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getHotbar() : array{
|
||||||
|
return $this->hotbar->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets hotbar links to their original defaults.
|
* Resets hotbar links to their original defaults.
|
||||||
* @param bool $send Whether to send changes to the holder.
|
* @param bool $send Whether to send changes to the holder.
|
||||||
*/
|
*/
|
||||||
public function resetHotbar(bool $send = true){
|
public function resetHotbar(bool $send = true){
|
||||||
$this->hotbar = range(0, $this->getHotbarSize() - 1, 1);
|
$this->hotbar = \SplFixedArray::fromArray(range(0, $this->getHotbarSize() - 1, 1));
|
||||||
if($send){
|
if($send){
|
||||||
$this->sendContents($this->getHolder());
|
$this->sendContents($this->getHolder());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function sendHotbar(){
|
||||||
|
$pk = new PlayerHotbarPacket();
|
||||||
|
$pk->windowId = ContainerIds::INVENTORY;
|
||||||
|
$pk->selectedSlot = $this->getHeldItemIndex();
|
||||||
|
$pk->slots = array_map(function(int $link){ return $link + $this->getHotbarSize(); }, $this->getHotbar());
|
||||||
|
$this->getHolder()->dataPacket($pk);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the hotbar slot number the holder is currently holding.
|
* Returns the hotbar slot number the holder is currently holding.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getHeldItemIndex(){
|
public function getHeldItemIndex() : int{
|
||||||
return $this->itemInHandIndex;
|
return $this->itemInHandIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets which hotbar slot the player is currently loading.
|
* Sets which hotbar slot the player is currently loading.
|
||||||
*
|
*
|
||||||
* @param int $index 0-8 index of the hotbar slot to hold
|
* @param int $hotbarSlot 0-8 index of the hotbar slot to hold
|
||||||
* @param bool $send Whether to send updates back to the inventory holder. This should usually be true for plugin calls.
|
* @param bool $send Whether to send updates back to the inventory holder. This should usually be true for plugin calls.
|
||||||
* It should only be false to prevent feedback loops of equipment packets between client and server.
|
* It should only be false to prevent feedback loops of equipment packets between client and server.
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException if the hotbar slot is out of range
|
||||||
*/
|
*/
|
||||||
public function setHeldItemIndex($index, $send = true){
|
public function setHeldItemIndex(int $hotbarSlot, bool $send = true){
|
||||||
if($index >= 0 and $index < $this->getHotbarSize()){
|
if($hotbarSlot >= 0 and $hotbarSlot < $this->getHotbarSize()){
|
||||||
$this->itemInHandIndex = $index;
|
$this->itemInHandIndex = $hotbarSlot;
|
||||||
|
|
||||||
if($this->getHolder() instanceof Player and $send){
|
if($this->getHolder() instanceof Player and $send){
|
||||||
$this->sendHeldItem($this->getHolder());
|
$this->sendHeldItem($this->getHolder());
|
||||||
@ -197,7 +216,7 @@ class PlayerInventory extends BaseInventory{
|
|||||||
|
|
||||||
$this->sendHeldItem($this->getHolder()->getViewers());
|
$this->sendHeldItem($this->getHolder()->getViewers());
|
||||||
}else{
|
}else{
|
||||||
throw new \InvalidArgumentException("Hotbar slot index \"$index\" is out of range");
|
throw new \InvalidArgumentException("Hotbar slot index \"$hotbarSlot\" is out of range");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,26 +225,26 @@ class PlayerInventory extends BaseInventory{
|
|||||||
*
|
*
|
||||||
* @return Item
|
* @return Item
|
||||||
*/
|
*/
|
||||||
public function getItemInHand(){
|
public function getItemInHand() : Item{
|
||||||
return $this->getHotbarSlotItem($this->itemInHandIndex);
|
return $this->getHotbarSlotItem($this->itemInHandIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the item in the currently-held slot to the specified item.
|
* Sets the item in the currently-held slot to the specified item.
|
||||||
|
*
|
||||||
* @param Item $item
|
* @param Item $item
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function setItemInHand(Item $item){
|
public function setItemInHand(Item $item) : bool{
|
||||||
return $this->setItem($this->getHeldItemSlot(), $item);
|
return $this->setItem($this->getHeldItemSlot(), $item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the hotbar slot number currently held.
|
* Returns the hotbar slot number currently held.
|
||||||
*
|
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getHeldItemSlot(){
|
public function getHeldItemSlot() : int{
|
||||||
return $this->getHotbarSlotIndex($this->itemInHandIndex);
|
return $this->getHotbarSlotIndex($this->itemInHandIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,7 +254,7 @@ class PlayerInventory extends BaseInventory{
|
|||||||
*
|
*
|
||||||
* @param int $slot
|
* @param int $slot
|
||||||
*/
|
*/
|
||||||
public function setHeldItemSlot($slot){
|
public function setHeldItemSlot(int $slot){
|
||||||
if($slot >= -1 and $slot < $this->getSize()){
|
if($slot >= -1 and $slot < $this->getSize()){
|
||||||
$this->setHotbarSlotIndex($this->getHeldItemIndex(), $slot);
|
$this->setHotbarSlotIndex($this->getHeldItemIndex(), $slot);
|
||||||
}
|
}
|
||||||
@ -268,7 +287,7 @@ class PlayerInventory extends BaseInventory{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onSlotChange($index, $before){
|
public function onSlotChange(int $index, Item $before, bool $send){
|
||||||
$holder = $this->getHolder();
|
$holder = $this->getHolder();
|
||||||
if($holder instanceof Player and !$holder->spawned){
|
if($holder instanceof Player and !$holder->spawned){
|
||||||
return;
|
return;
|
||||||
@ -279,7 +298,7 @@ class PlayerInventory extends BaseInventory{
|
|||||||
$this->sendArmorSlot($index, $this->getHolder()->getViewers());
|
$this->sendArmorSlot($index, $this->getHolder()->getViewers());
|
||||||
}else{
|
}else{
|
||||||
//Do not send armor by accident here.
|
//Do not send armor by accident here.
|
||||||
parent::onSlotChange($index, $before);
|
parent::onSlotChange($index, $before, $send);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,57 +306,51 @@ class PlayerInventory extends BaseInventory{
|
|||||||
* Returns the number of slots in the hotbar.
|
* Returns the number of slots in the hotbar.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getHotbarSize(){
|
public function getHotbarSize() : int{
|
||||||
return 9;
|
return 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getArmorItem($index){
|
public function getArmorItem(int $index) : Item{
|
||||||
return $this->getItem($this->getSize() + $index);
|
return $this->getItem($this->getSize() + $index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setArmorItem($index, Item $item){
|
public function setArmorItem(int $index, Item $item) : bool{
|
||||||
return $this->setItem($this->getSize() + $index, $item);
|
return $this->setItem($this->getSize() + $index, $item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHelmet(){
|
public function getHelmet() : Item{
|
||||||
return $this->getItem($this->getSize());
|
return $this->getItem($this->getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getChestplate(){
|
public function getChestplate() : Item{
|
||||||
return $this->getItem($this->getSize() + 1);
|
return $this->getItem($this->getSize() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLeggings(){
|
public function getLeggings() : Item{
|
||||||
return $this->getItem($this->getSize() + 2);
|
return $this->getItem($this->getSize() + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBoots(){
|
public function getBoots() : Item{
|
||||||
return $this->getItem($this->getSize() + 3);
|
return $this->getItem($this->getSize() + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setHelmet(Item $helmet){
|
public function setHelmet(Item $helmet) : bool{
|
||||||
return $this->setItem($this->getSize(), $helmet);
|
return $this->setItem($this->getSize(), $helmet);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setChestplate(Item $chestplate){
|
public function setChestplate(Item $chestplate) : bool{
|
||||||
return $this->setItem($this->getSize() + 1, $chestplate);
|
return $this->setItem($this->getSize() + 1, $chestplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setLeggings(Item $leggings){
|
public function setLeggings(Item $leggings) : bool{
|
||||||
return $this->setItem($this->getSize() + 2, $leggings);
|
return $this->setItem($this->getSize() + 2, $leggings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setBoots(Item $boots){
|
public function setBoots(Item $boots) : bool{
|
||||||
return $this->setItem($this->getSize() + 3, $boots);
|
return $this->setItem($this->getSize() + 3, $boots);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setItem(int $index, Item $item) : bool{
|
public function setItem(int $index, Item $item, bool $send = true) : bool{
|
||||||
if($index < 0 or $index >= $this->size){
|
|
||||||
return false;
|
|
||||||
}elseif($item->getId() === 0 or $item->getCount() <= 0){
|
|
||||||
return $this->clear($index);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($index >= $this->getSize()){ //Armor change
|
if($index >= $this->getSize()){ //Armor change
|
||||||
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityArmorChangeEvent($this->getHolder(), $this->getItem($index), $item, $index));
|
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityArmorChangeEvent($this->getHolder(), $this->getItem($index), $item, $index));
|
||||||
if($ev->isCancelled() and $this->getHolder() instanceof Human){
|
if($ev->isCancelled() and $this->getHolder() instanceof Human){
|
||||||
@ -357,54 +370,25 @@ class PlayerInventory extends BaseInventory{
|
|||||||
|
|
||||||
$old = $this->getItem($index);
|
$old = $this->getItem($index);
|
||||||
$this->slots[$index] = clone $item;
|
$this->slots[$index] = clone $item;
|
||||||
$this->onSlotChange($index, $old);
|
$this->onSlotChange($index, $old, $send);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function clear(int $index) : bool{
|
public function clearAll(){
|
||||||
if(isset($this->slots[$index])){
|
parent::clearAll();
|
||||||
$item = Item::get(Item::AIR, 0, 0);
|
|
||||||
$old = $this->slots[$index];
|
|
||||||
if($index >= $this->getSize() and $index < $this->size){ //Armor change
|
|
||||||
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityArmorChangeEvent($this->getHolder(), $old, $item, $index));
|
|
||||||
if($ev->isCancelled()){
|
|
||||||
if($index >= $this->size){
|
|
||||||
$this->sendArmorSlot($index, $this->getViewers());
|
|
||||||
}else{
|
|
||||||
$this->sendSlot($index, $this->getViewers());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$item = $ev->getNewItem();
|
|
||||||
}else{
|
|
||||||
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityInventoryChangeEvent($this->getHolder(), $old, $item, $index));
|
|
||||||
if($ev->isCancelled()){
|
|
||||||
if($index >= $this->size){
|
|
||||||
$this->sendArmorSlot($index, $this->getViewers());
|
|
||||||
}else{
|
|
||||||
$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);
|
for($i = $this->getSize(), $m = $i + 4; $i < $m; ++$i){
|
||||||
|
$this->clear($i, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
$this->sendArmorContents($this->getViewers());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Item[]
|
* @return Item[]
|
||||||
*/
|
*/
|
||||||
public function getArmorContents(){
|
public function getArmorContents() : array{
|
||||||
$armor = [];
|
$armor = [];
|
||||||
|
|
||||||
for($i = 0; $i < 4; ++$i){
|
for($i = 0; $i < 4; ++$i){
|
||||||
@ -414,13 +398,6 @@ class PlayerInventory extends BaseInventory{
|
|||||||
return $armor;
|
return $armor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function clearAll(){
|
|
||||||
$limit = $this->getSize() + 4;
|
|
||||||
for($index = 0; $index < $limit; ++$index){
|
|
||||||
$this->clear($index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Player|Player[] $target
|
* @param Player|Player[] $target
|
||||||
*/
|
*/
|
||||||
@ -457,12 +434,10 @@ class PlayerInventory extends BaseInventory{
|
|||||||
$items[$i] = Item::get(Item::AIR, 0, 0);
|
$items[$i] = Item::get(Item::AIR, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($items[$i]->getId() === Item::AIR){
|
$this->setItem($this->getSize() + $i, $items[$i], false);
|
||||||
$this->clear($this->getSize() + $i);
|
|
||||||
}else{
|
|
||||||
$this->setItem($this->getSize() + $i, $items[$i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->sendArmorContents($this->getViewers());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -470,7 +445,7 @@ class PlayerInventory extends BaseInventory{
|
|||||||
* @param int $index
|
* @param int $index
|
||||||
* @param Player|Player[] $target
|
* @param Player|Player[] $target
|
||||||
*/
|
*/
|
||||||
public function sendArmorSlot($index, $target){
|
public function sendArmorSlot(int $index, $target){
|
||||||
if($target instanceof Player){
|
if($target instanceof Player){
|
||||||
$target = [$target];
|
$target = [$target];
|
||||||
}
|
}
|
||||||
@ -520,11 +495,7 @@ class PlayerInventory extends BaseInventory{
|
|||||||
$player->dataPacket(clone $pk);
|
$player->dataPacket(clone $pk);
|
||||||
|
|
||||||
if($player === $this->getHolder()){
|
if($player === $this->getHolder()){
|
||||||
$pk = new PlayerHotbarPacket();
|
$this->sendHotbar();
|
||||||
$pk->slots = array_map(function(int $i){ return $i + $this->getHotbarSize(); }, $this->hotbar);
|
|
||||||
$pk->selectedSlot = $this->getHeldItemIndex();
|
|
||||||
$pk->windowId = ContainerIds::INVENTORY;
|
|
||||||
$player->dataPacket($pk);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -545,7 +516,7 @@ class PlayerInventory extends BaseInventory{
|
|||||||
* @param int $index
|
* @param int $index
|
||||||
* @param Player|Player[] $target
|
* @param Player|Player[] $target
|
||||||
*/
|
*/
|
||||||
public function sendSlot($index, $target){
|
public function sendSlot(int $index, $target){
|
||||||
if($target instanceof Player){
|
if($target instanceof Player){
|
||||||
$target = [$target];
|
$target = [$target];
|
||||||
}
|
}
|
||||||
@ -571,10 +542,11 @@ class PlayerInventory extends BaseInventory{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This override is here for documentation and code completion purposes only.
|
||||||
* @return Human|Player
|
* @return Human|Player
|
||||||
*/
|
*/
|
||||||
public function getHolder(){
|
public function getHolder(){
|
||||||
return parent::getHolder();
|
return $this->holder;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -828,6 +828,10 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
$this->count = $count;
|
$this->count = $count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isNull() : bool{
|
||||||
|
return $this->count <= 0 or $this->id === Item::AIR;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of the item, or the custom name if it is set.
|
* Returns the name of the item, or the custom name if it is set.
|
||||||
* @return string
|
* @return string
|
||||||
|
Loading…
x
Reference in New Issue
Block a user