mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-08 19:02:59 +00:00
Implemented new Inventory windows on Player, Chest and Furnace
This commit is contained in:
@ -21,9 +21,13 @@
|
||||
|
||||
namespace pocketmine\inventory;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\event\entity\EntityInventoryChangeEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\network\protocol\ContainerSetContentPacket;
|
||||
use pocketmine\network\protocol\ContainerSetSlotPacket;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\Server;
|
||||
|
||||
abstract class BaseInventory implements Inventory{
|
||||
|
||||
@ -57,7 +61,7 @@ abstract class BaseInventory implements Inventory{
|
||||
|
||||
//A holder can be a plugin, or an entity
|
||||
if($this->holder instanceof Player){
|
||||
$this->viewers->attach($this->holder);
|
||||
$this->holder->addWindow($this, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -123,18 +127,34 @@ abstract class BaseInventory implements Inventory{
|
||||
}
|
||||
|
||||
public function setItem($index, Item $item){
|
||||
if($index < 0 or $index >= $this->size or $item->getID() === 0){
|
||||
return;
|
||||
if($index < 0 or $index >= $this->size){
|
||||
return false;
|
||||
}elseif($item->getID() === 0){
|
||||
$this->clear($index);
|
||||
}
|
||||
|
||||
$holder = $this->getHolder();
|
||||
if($holder instanceof Entity){
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityInventoryChangeEvent($holder, $this->getItem($index), $item, $index));
|
||||
if($ev->isCancelled()){
|
||||
$this->sendContents($this->getViewers());
|
||||
|
||||
return false;
|
||||
}
|
||||
$item = $ev->getNewItem();
|
||||
}
|
||||
|
||||
$old = $this->slots[$index];
|
||||
$this->slots[$index] = clone $item;
|
||||
$this->onSlotChange($index, $old);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function contains(Item $item){
|
||||
$count = max(1, $item->getCount());
|
||||
$checkDamage = $item->getDamage() === null ? false : true;
|
||||
foreach($this->slots as $i){
|
||||
foreach($this->getContents() as $i){
|
||||
if($item->equals($i, $checkDamage)){
|
||||
$count -= $i->getCount();
|
||||
if($count <= 0){
|
||||
@ -149,7 +169,7 @@ abstract class BaseInventory implements Inventory{
|
||||
public function all(Item $item){
|
||||
$slots = [];
|
||||
$checkDamage = $item->getDamage() === null ? false : true;
|
||||
foreach($this->slots as $index => $i){
|
||||
foreach($this->getContents() as $index => $i){
|
||||
if($item->equals($i, $checkDamage)){
|
||||
$slots[$index] = $i;
|
||||
}
|
||||
@ -160,7 +180,7 @@ abstract class BaseInventory implements Inventory{
|
||||
|
||||
public function remove(Item $item){
|
||||
$checkDamage = $item->getDamage() === null ? false : true;
|
||||
foreach($this->slots as $index => $i){
|
||||
foreach($this->getContents() as $index => $i){
|
||||
if($item->equals($i, $checkDamage)){
|
||||
$this->clear($index);
|
||||
}
|
||||
@ -170,7 +190,7 @@ abstract class BaseInventory implements Inventory{
|
||||
public function first(Item $item){
|
||||
$count = max(1, $item->getCount());
|
||||
$checkDamage = $item->getDamage() === null ? false : true;
|
||||
foreach($this->slots as $index => $i){
|
||||
foreach($this->getContents() as $index => $i){
|
||||
if($item->equals($i, $checkDamage) and $i->getCount() >= $count){
|
||||
return $index;
|
||||
}
|
||||
@ -181,10 +201,7 @@ abstract class BaseInventory implements Inventory{
|
||||
|
||||
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]);
|
||||
if($this->getItem($i)->getID() === Item::AIR){
|
||||
return $i;
|
||||
}
|
||||
}
|
||||
@ -196,11 +213,10 @@ abstract class BaseInventory implements Inventory{
|
||||
/** @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];
|
||||
$item = $this->getItem($i);
|
||||
if($item->getID() === Item::AIR){
|
||||
$item = array_shift($slots);
|
||||
$this->setItem($i, $item);
|
||||
}
|
||||
|
||||
foreach($slots as $index => $slot){
|
||||
@ -230,10 +246,9 @@ abstract class BaseInventory implements Inventory{
|
||||
/** @var Item[] $slots */
|
||||
$slots = func_get_args();
|
||||
for($i = 0; $i < $this->size; ++$i){
|
||||
if(!isset($this->slots[$i])){
|
||||
$item = $this->getItem($i);
|
||||
if($item->getID() === Item::AIR){
|
||||
continue;
|
||||
}else{
|
||||
$item = $this->slots[$i];
|
||||
}
|
||||
|
||||
foreach($slots as $index => $slot){
|
||||
@ -263,14 +278,32 @@ abstract class BaseInventory implements Inventory{
|
||||
|
||||
public function clear($index){
|
||||
if(isset($this->slots[$index])){
|
||||
$item = Item::get(Item::AIR, null, 0);
|
||||
$old = $this->slots[$index];
|
||||
unset($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->sendContents($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(){
|
||||
foreach($this->slots as $index => $i){
|
||||
foreach($this->getContents() as $index => $i){
|
||||
$this->clear($index);
|
||||
}
|
||||
}
|
||||
@ -280,6 +313,7 @@ abstract class BaseInventory implements Inventory{
|
||||
foreach($this->viewers as $viewer){
|
||||
$viewers[] = $viewer;
|
||||
}
|
||||
|
||||
return $viewers;
|
||||
}
|
||||
|
||||
@ -300,12 +334,44 @@ abstract class BaseInventory implements Inventory{
|
||||
}
|
||||
|
||||
public function onSlotChange($index, $before){
|
||||
$this->sendSlot($index, $this->getViewers());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Player|Player[] $target
|
||||
*/
|
||||
public function sendContents($target){
|
||||
if($target instanceof Player){
|
||||
$target = [$target];
|
||||
}
|
||||
|
||||
$pk = new ContainerSetContentPacket();
|
||||
$pk->slots = [];
|
||||
for($i = 0; $i < $this->getSize(); ++$i){
|
||||
$pk->slots[$i] = $this->getItem($i);
|
||||
}
|
||||
|
||||
foreach($target as $player){
|
||||
$pk->windowid = $player->getWindowId($this);
|
||||
$player->dataPacket(clone $pk);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $index
|
||||
* @param Player|Player[] $target
|
||||
*/
|
||||
public function sendSlot($index, $target){
|
||||
if($target instanceof Player){
|
||||
$target = [$target];
|
||||
}
|
||||
|
||||
$pk = new ContainerSetSlotPacket;
|
||||
$pk->slot = $index;
|
||||
$pk->item = clone $this->getItem($index);
|
||||
|
||||
/** @var Player $player */
|
||||
foreach($this->getViewers() as $player){
|
||||
foreach($target as $player){
|
||||
$pk->windowid = $player->getWindowId($this);
|
||||
$player->dataPacket(clone $pk);
|
||||
}
|
||||
|
67
src/pocketmine/inventory/ChestInventory.php
Normal file
67
src/pocketmine/inventory/ChestInventory.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\inventory;
|
||||
|
||||
use pocketmine\network\protocol\TileEventPacket;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\tile\Chest;
|
||||
|
||||
class ChestInventory extends ContainerInventory{
|
||||
public function __construct(Chest $tile){
|
||||
parent::__construct($tile, InventoryType::get(InventoryType::CHEST));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Chest
|
||||
*/
|
||||
public function getHolder(){
|
||||
return $this->holder;
|
||||
}
|
||||
|
||||
public function onOpen(Player $who){
|
||||
parent::onOpen($who);
|
||||
|
||||
if(count($this->getViewers()) === 1){
|
||||
$pk = new TileEventPacket;
|
||||
$pk->x = $this->getHolder()->getX();
|
||||
$pk->y = $this->getHolder()->getY();
|
||||
$pk->z = $this->getHolder()->getZ();
|
||||
$pk->case1 = 1;
|
||||
$pk->case2 = 2;
|
||||
Player::broadcastPacket($this->getHolder()->getLevel()->getPlayers(), $pk);
|
||||
}
|
||||
}
|
||||
|
||||
public function onClose(Player $who){
|
||||
parent::onClose($who);
|
||||
|
||||
if(count($this->getViewers()) === 1){
|
||||
$pk = new TileEventPacket;
|
||||
$pk->x = $this->getHolder()->getX();
|
||||
$pk->y = $this->getHolder()->getY();
|
||||
$pk->z = $this->getHolder()->getZ();
|
||||
$pk->case1 = 1;
|
||||
$pk->case2 = 0;
|
||||
Player::broadcastPacket($this->getHolder()->getLevel()->getPlayers(), $pk);
|
||||
}
|
||||
}
|
||||
}
|
55
src/pocketmine/inventory/ContainerInventory.php
Normal file
55
src/pocketmine/inventory/ContainerInventory.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\inventory;
|
||||
|
||||
use pocketmine\network\protocol\ContainerClosePacket;
|
||||
use pocketmine\network\protocol\ContainerOpenPacket;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\tile\Chest;
|
||||
use pocketmine\tile\Furnace;
|
||||
|
||||
abstract class ContainerInventory extends BaseInventory{
|
||||
|
||||
/**
|
||||
* @return Chest|Furnace
|
||||
*/
|
||||
public function getHolder(){
|
||||
return $this->holder;
|
||||
}
|
||||
|
||||
public function onOpen(Player $who){
|
||||
$pk = new ContainerOpenPacket;
|
||||
$pk->windowid = $who->getWindowId($this);
|
||||
$pk->type = 0;
|
||||
$pk->slots = $this->getSize();
|
||||
$pk->x = $this->getHolder()->getX();
|
||||
$pk->y = $this->getHolder()->getY();
|
||||
$pk->z = $this->getHolder()->getZ();
|
||||
$who->dataPacket($pk);
|
||||
}
|
||||
|
||||
public function onClose(Player $who){
|
||||
$pk = new ContainerClosePacket;
|
||||
$pk->windowid = $who->getWindowId($this);
|
||||
$who->dataPacket($pk);
|
||||
}
|
||||
}
|
101
src/pocketmine/inventory/DoubleChestInventory.php
Normal file
101
src/pocketmine/inventory/DoubleChestInventory.php
Normal file
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\inventory;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\tile\Chest;
|
||||
|
||||
class DoubleChestInventory extends ChestInventory implements InventoryHolder{
|
||||
/** @var ChestInventory */
|
||||
private $left;
|
||||
/** @var ChestInventory */
|
||||
private $right;
|
||||
|
||||
public function __construct(Chest $left, Chest $right){
|
||||
$this->left = $left->getRealInventory();
|
||||
$this->right = $right->getRealInventory();
|
||||
BaseInventory::__construct($this, InventoryType::get(InventoryType::DOUBLE_CHEST));
|
||||
}
|
||||
|
||||
//TODO
|
||||
public function getInventory(){
|
||||
return $this;
|
||||
}
|
||||
|
||||
//TODO
|
||||
public function getHolder(){
|
||||
return $this->left;
|
||||
}
|
||||
|
||||
public function getItem($index){
|
||||
return $index < $this->left->getSize() ? $this->left->getItem($index) : $this->right->getItem($index - $this->right->getSize());
|
||||
}
|
||||
|
||||
public function setItem($index, Item $item){
|
||||
return $index < $this->left->getSize() ? $this->left->setItem($index, $item) : $this->right->setItem($index - $this->right->getSize(), $item);
|
||||
}
|
||||
|
||||
public function clear($index){
|
||||
return $index < $this->left->getSize() ? $this->left->clear($index) : $this->right->clear($index - $this->right->getSize());
|
||||
}
|
||||
|
||||
public function getContents(){
|
||||
$contents = [];
|
||||
for($i = 0; $i < $this->getSize(); ++$i){
|
||||
$contents[$i] = $this->getItem($i);
|
||||
}
|
||||
|
||||
return $contents;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Item[] $items
|
||||
*/
|
||||
public function setContents(array $items){
|
||||
if(count($items) > $this->size){
|
||||
$items = array_slice($items, 0, $this->size, true);
|
||||
}
|
||||
|
||||
parent::setContents($items);
|
||||
|
||||
$leftItems = array_slice($items, 0, $this->left->getSize(), true);
|
||||
$this->left->setContents($leftItems);
|
||||
if(count($items) > $this->left->getSize()){
|
||||
$rightItems = array_slice($items, $this->left->getSize() - 1, $this->right->getSize(), true);
|
||||
$this->right->setContents($rightItems);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ChestInventory
|
||||
*/
|
||||
public function getLeftSide(){
|
||||
return $this->left;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ChestInventory
|
||||
*/
|
||||
public function getRightSide(){
|
||||
return $this->right;
|
||||
}
|
||||
}
|
92
src/pocketmine/inventory/FurnaceInventory.php
Normal file
92
src/pocketmine/inventory/FurnaceInventory.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\inventory;
|
||||
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\tile\Furnace;
|
||||
|
||||
class FurnaceInventory extends ContainerInventory{
|
||||
public function __construct(Furnace $tile){
|
||||
parent::__construct($tile, InventoryType::get(InventoryType::FURNACE));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Furnace
|
||||
*/
|
||||
public function getHolder(){
|
||||
return $this->holder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Item
|
||||
*/
|
||||
public function getResult(){
|
||||
return $this->getItem(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Item
|
||||
*/
|
||||
public function getFuel(){
|
||||
return $this->getItem(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Item
|
||||
*/
|
||||
public function getSmelting(){
|
||||
return $this->getItem(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Item $item
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setResult(Item $item){
|
||||
return $this->setItem(2, $item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Item $item
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setFuel(Item $item){
|
||||
return $this->setItem(1, $item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Item $item
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setSmelting(Item $item){
|
||||
return $this->setItem(0, $item);
|
||||
}
|
||||
|
||||
public function onSlotChange($index, $before){
|
||||
parent::onSlotChange($index, $before);
|
||||
//TODO: implement Furnace scheduled update
|
||||
}
|
||||
}
|
@ -50,6 +50,15 @@ interface Inventory{
|
||||
*/
|
||||
public function getItem($index);
|
||||
|
||||
/**
|
||||
* Puts an Item in a slot.
|
||||
* If a plugin refuses the update or $index is invalid, it'll return false
|
||||
*
|
||||
* @param int $index
|
||||
* @param Item $item
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setItem($index, Item $item);
|
||||
|
||||
/**
|
||||
@ -127,6 +136,8 @@ interface Inventory{
|
||||
* Will clear a specific slot
|
||||
*
|
||||
* @param int $index
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function clear($index);
|
||||
|
||||
@ -164,7 +175,7 @@ interface Inventory{
|
||||
public function onClose(Player $who);
|
||||
|
||||
/**
|
||||
* @param int $index
|
||||
* @param int $index
|
||||
* @param Item|null $before
|
||||
*/
|
||||
public function onSlotChange($index, $before);
|
||||
|
@ -26,10 +26,11 @@ namespace pocketmine\inventory;
|
||||
*/
|
||||
class InventoryType{
|
||||
const CHEST = 0;
|
||||
const PLAYER = 1;
|
||||
const FURNACE = 2;
|
||||
const CRAFTING = 3;
|
||||
const WORKBENCH = 4;
|
||||
const DOUBLE_CHEST = 1;
|
||||
const PLAYER = 2;
|
||||
const FURNACE = 3;
|
||||
const CRAFTING = 4;
|
||||
const WORKBENCH = 5;
|
||||
|
||||
private static $default = [];
|
||||
|
||||
@ -46,6 +47,7 @@ class InventoryType{
|
||||
}
|
||||
|
||||
static::$default[static::CHEST] = new InventoryType(27, "Chest");
|
||||
static::$default[static::DOUBLE_CHEST] = new InventoryType(27 + 27, "Double Chest");
|
||||
static::$default[static::PLAYER] = new InventoryType(31, "Player"); //27 CONTAINER, 4 ARMOR (9 reference HOTBAR slots)
|
||||
static::$default[static::FURNACE] = new InventoryType(3, "Furnace");
|
||||
static::$default[static::CRAFTING] = new InventoryType(5, "Crafting"); //4 CRAFTING slots, 1 RESULT
|
||||
@ -53,7 +55,7 @@ class InventoryType{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $defaultSize
|
||||
* @param int $defaultSize
|
||||
* @param string $defaultTitle
|
||||
*/
|
||||
private function __construct($defaultSize, $defaultTitle){
|
||||
|
@ -22,11 +22,15 @@
|
||||
namespace pocketmine\inventory;
|
||||
|
||||
use pocketmine\entity\Human;
|
||||
use pocketmine\event\entity\EntityArmorChangeEvent;
|
||||
use pocketmine\event\player\PlayerItemHeldEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\network\protocol\ContainerSetContentPacket;
|
||||
use pocketmine\network\protocol\ContainerSetSlotPacket;
|
||||
use pocketmine\network\protocol\PlayerArmorEquipmentPacket;
|
||||
use pocketmine\network\protocol\PlayerEquipmentPacket;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\Server;
|
||||
|
||||
class PlayerInventory extends BaseInventory{
|
||||
|
||||
@ -83,8 +87,13 @@ class PlayerInventory extends BaseInventory{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Item $item
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setItemInHand(Item $item){
|
||||
$this->setItem($this->getHeldItemSlot(), $item);
|
||||
return $this->setItem($this->getHeldItemSlot(), $item);
|
||||
}
|
||||
|
||||
public function getHeldItemSlot(){
|
||||
@ -93,16 +102,47 @@ class PlayerInventory extends BaseInventory{
|
||||
|
||||
public function setHeldItemSlot($slot){
|
||||
if($slot >= 0 and $slot < $this->getSize()){
|
||||
$item = $this->getItem($slot);
|
||||
if($this->getHolder() instanceof Player){
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev = new PlayerItemHeldEvent($this->getHolder(), $item, $slot, 0));
|
||||
if($ev->isCancelled()){
|
||||
$this->sendHeldItem($this->getHolder());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$this->setHotbarSlotIndex($this->itemInHandIndex, $slot);
|
||||
$item = $this->getItemInHand();
|
||||
$this->sendHeldItem($this->getHolder()->getViewers());
|
||||
|
||||
$pk = new PlayerEquipmentPacket;
|
||||
$pk->eid = $this->getHolder()->getID();
|
||||
$pk->item = $item->getID();
|
||||
$pk->meta = $item->getDamage();
|
||||
$pk->slot = 0;
|
||||
if($this->getHolder() instanceof Player){
|
||||
$this->sendHeldItem($this->getHolder());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach($this->getHolder()->getViewers() as $player){
|
||||
/**
|
||||
* @param Player|Player[] $target
|
||||
*/
|
||||
public function sendHeldItem($target){
|
||||
if($target instanceof Player){
|
||||
$target = [$target];
|
||||
}
|
||||
|
||||
$item = $this->getItemInHand();
|
||||
|
||||
$pk = new PlayerEquipmentPacket;
|
||||
$pk->eid = $this->getHolder()->getID();
|
||||
$pk->item = $item->getID();
|
||||
$pk->meta = $item->getDamage();
|
||||
$pk->slot = 0;
|
||||
|
||||
foreach($target as $player){
|
||||
if($player === $this->getHolder()){
|
||||
//TODO: Check if Mojang enabled sending a single slot this
|
||||
//$this->sendSlot($this->getHeldItemSlot());
|
||||
$this->sendContents($this->getHolder());
|
||||
}else{
|
||||
$player->dataPacket(clone $pk);
|
||||
}
|
||||
}
|
||||
@ -112,34 +152,11 @@ class PlayerInventory extends BaseInventory{
|
||||
parent::onSlotChange($index, $before);
|
||||
|
||||
if($index >= $this->getSize()){
|
||||
$armor = $this->getArmorContents();
|
||||
$slots = [];
|
||||
$this->sendArmorContents($this->getHolder()->getViewers());
|
||||
}
|
||||
|
||||
foreach($armor as $i => $slot){
|
||||
if($slot->getID() === Item::AIR){
|
||||
$slots[$i] = 255;
|
||||
}else{
|
||||
$slots[$i] = $slot->getID();
|
||||
}
|
||||
}
|
||||
|
||||
$pk = new PlayerArmorEquipmentPacket;
|
||||
$pk->eid = $this->getHolder()->getID();
|
||||
$pk->slots = $slots;
|
||||
|
||||
if($index >= $this->getSize()){ //Armor change
|
||||
foreach($this->getHolder()->getViewers() as $player){
|
||||
if($player === $this->getHolder()){
|
||||
/** @var Player $player */
|
||||
$pk2 = new ContainerSetContentPacket;
|
||||
$pk2->windowid = 0x78; //Armor window id constant
|
||||
$pk2->slots = $armor;
|
||||
$player->dataPacket($pk2);
|
||||
}else{
|
||||
$player->dataPacket(clone $pk);
|
||||
}
|
||||
}
|
||||
}
|
||||
if($this->getHolder() instanceof Player){
|
||||
$this->sendArmorContents($this->getHolder());
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,6 +164,14 @@ class PlayerInventory extends BaseInventory{
|
||||
return 9;
|
||||
}
|
||||
|
||||
public function getArmorItem($index){
|
||||
return $this->getItem($this->getSize() + $index);
|
||||
}
|
||||
|
||||
public function setArmorItem($index, Item $item){
|
||||
return $this->setItem($this->getSize() + $index, $item);
|
||||
}
|
||||
|
||||
public function getHelmet(){
|
||||
return $this->getItem($this->getSize() + 3);
|
||||
}
|
||||
@ -164,19 +189,66 @@ class PlayerInventory extends BaseInventory{
|
||||
}
|
||||
|
||||
public function setHelmet(Item $helmet){
|
||||
$this->setItem($this->getSize() + 3, $helmet);
|
||||
return $this->setItem($this->getSize() + 3, $helmet);
|
||||
}
|
||||
|
||||
public function setChestplate(Item $chestplate){
|
||||
$this->setItem($this->getSize() + 2, $chestplate);
|
||||
return $this->setItem($this->getSize() + 2, $chestplate);
|
||||
}
|
||||
|
||||
public function setLeggings(Item $leggings){
|
||||
$this->setItem($this->getSize() + 1, $leggings);
|
||||
return $this->setItem($this->getSize() + 1, $leggings);
|
||||
}
|
||||
|
||||
public function setBoots(Item $boots){
|
||||
$this->setItem($this->getSize(), $boots);
|
||||
return $this->setItem($this->getSize(), $boots);
|
||||
}
|
||||
|
||||
public function setItem($index, Item $item){
|
||||
if($index < 0 or $index >= $this->size){
|
||||
return false;
|
||||
}
|
||||
|
||||
if($index >= $this->getSize()){ //Armor change
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityArmorChangeEvent($this->getHolder(), $this->getItem($index), $item, $index));
|
||||
if($ev->isCancelled()){
|
||||
$this->sendArmorContents($this);
|
||||
$this->sendContents($this);
|
||||
|
||||
return false;
|
||||
}
|
||||
$item = $ev->getNewItem();
|
||||
}
|
||||
|
||||
$old = $this->slots[$index];
|
||||
$this->slots[$index] = clone $item;
|
||||
$this->onSlotChange($index, $old);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function clear($index){
|
||||
if(isset($this->slots[$index])){
|
||||
$item = Item::get(Item::AIR, null, 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()){
|
||||
$this->sendArmorContents($this);
|
||||
$this->sendContents($this);
|
||||
|
||||
return;
|
||||
}
|
||||
$item = $ev->getNewItem();
|
||||
}
|
||||
if($item->getID() !== Item::AIR){
|
||||
$this->slots[$index] = clone $item;
|
||||
}else{
|
||||
unset($this->slots[$index]);
|
||||
}
|
||||
|
||||
$this->onSlotChange($index, $old);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -192,6 +264,41 @@ class PlayerInventory extends BaseInventory{
|
||||
return $armor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Player|Player[] $target
|
||||
*/
|
||||
public function sendArmorContents($target){
|
||||
if($target instanceof Player){
|
||||
$target = [$target];
|
||||
}
|
||||
$armor = $this->getArmorContents();
|
||||
$slots = [];
|
||||
|
||||
foreach($armor as $i => $slot){
|
||||
if($slot->getID() === Item::AIR){
|
||||
$slots[$i] = 255;
|
||||
}else{
|
||||
$slots[$i] = $slot->getID();
|
||||
}
|
||||
}
|
||||
|
||||
$pk = new PlayerArmorEquipmentPacket;
|
||||
$pk->eid = $this->getHolder()->getID();
|
||||
$pk->slots = $slots;
|
||||
|
||||
foreach($target as $player){
|
||||
if($player === $this->getHolder()){
|
||||
/** @var Player $player */
|
||||
$pk2 = new ContainerSetContentPacket;
|
||||
$pk2->windowid = 0x78; //Armor window id constant
|
||||
$pk2->slots = $armor;
|
||||
$player->dataPacket($pk2);
|
||||
}else{
|
||||
$player->dataPacket(clone $pk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Item[] $items
|
||||
*/
|
||||
@ -209,6 +316,62 @@ class PlayerInventory extends BaseInventory{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Player|Player[] $target
|
||||
*/
|
||||
public function sendContents($target){
|
||||
if($target instanceof Player){
|
||||
$target = [$target];
|
||||
}
|
||||
|
||||
$holder = $this->getHolder();
|
||||
if($holder instanceof Player and ($holder->getGamemode() & 0x01) === 1){
|
||||
return;
|
||||
}
|
||||
|
||||
$pk = new ContainerSetContentPacket();
|
||||
$pk->slots = [];
|
||||
for($i = 0; $i < $this->getSize(); ++$i){ //Do not send armor by error here
|
||||
$pk->slots[$i] = $this->getItem($i);
|
||||
}
|
||||
|
||||
foreach($target as $player){
|
||||
$pk->hotbar = [];
|
||||
if($player === $this->getHolder()){
|
||||
for($i = 0; $i < $this->getHotbarSize(); ++$i){
|
||||
$index = $this->getHotbarSlotIndex($i);
|
||||
$pk->hotbar[] = $index <= -1 ? -1 : $index + 9;
|
||||
}
|
||||
}
|
||||
$pk->windowid = $player->getWindowId($this);
|
||||
$player->dataPacket(clone $pk);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $index
|
||||
* @param Player|Player[] $target
|
||||
*/
|
||||
public function sendSlot($index, $target){
|
||||
if($target instanceof Player){
|
||||
$target = [$target];
|
||||
}
|
||||
|
||||
$pk = new ContainerSetSlotPacket;
|
||||
$pk->slot = $index;
|
||||
$pk->item = clone $this->getItem($index);
|
||||
|
||||
foreach($target as $player){
|
||||
if($player === $this->getHolder()){
|
||||
//TODO: Check if Mojang has implemented this (for the player inventory) on Minecraft: PE 0.9.0
|
||||
$this->sendContents($player);
|
||||
}else{
|
||||
$pk->windowid = $player->getWindowId($this);
|
||||
$player->dataPacket(clone $pk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Human
|
||||
*/
|
||||
|
Reference in New Issue
Block a user