Inventory: Split up armor and player inventory (#1957)

* Inventory: Split up PlayerInventory and armour handling
* Fixed other players don't see armour changes. This bug also exists on master.
This commit is contained in:
Dylan K. Taylor
2018-01-23 20:01:26 +00:00
committed by GitHub
parent 0bf5ab76fb
commit 6543d96910
8 changed files with 198 additions and 235 deletions

View File

@ -24,17 +24,12 @@ declare(strict_types=1);
namespace pocketmine\inventory;
use pocketmine\entity\Human;
use pocketmine\event\entity\EntityArmorChangeEvent;
use pocketmine\event\player\PlayerItemHeldEvent;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\network\mcpe\protocol\InventoryContentPacket;
use pocketmine\network\mcpe\protocol\InventorySlotPacket;
use pocketmine\network\mcpe\protocol\MobArmorEquipmentPacket;
use pocketmine\network\mcpe\protocol\MobEquipmentPacket;
use pocketmine\network\mcpe\protocol\types\ContainerIds;
use pocketmine\Player;
use pocketmine\Server;
class PlayerInventory extends EntityInventory{
@ -56,16 +51,7 @@ class PlayerInventory extends EntityInventory{
}
public function getDefaultSize() : int{
return 40; //36 inventory, 4 armor
}
public function getSize() : int{
return parent::getSize() - 4; //Remove armor slots
}
public function setSize(int $size){
parent::setSize($size + 4);
$this->sendContents($this->getViewers());
return 36;
}
/**
@ -204,23 +190,6 @@ class PlayerInventory extends EntityInventory{
}
}
public function onSlotChange(int $index, Item $before, bool $send) : void{
$holder = $this->getHolder();
if($holder instanceof Player and !$holder->spawned){
return;
}
if($index >= $this->getSize()){
if($send){
$this->sendArmorSlot($index, $this->getViewers());
$this->sendArmorSlot($index, $this->getHolder()->getViewers());
}
}else{
//Do not send armor by accident here.
parent::onSlotChange($index, $before, $send);
}
}
/**
* Returns the number of slots in the hotbar.
* @return int
@ -229,158 +198,6 @@ class PlayerInventory extends EntityInventory{
return 9;
}
public function getArmorItem(int $index) : Item{
return $this->getItem($this->getSize() + $index);
}
public function setArmorItem(int $index, Item $item) : bool{
return $this->setItem($this->getSize() + $index, $item);
}
public function getHelmet() : Item{
return $this->getItem($this->getSize());
}
public function getChestplate() : Item{
return $this->getItem($this->getSize() + 1);
}
public function getLeggings() : Item{
return $this->getItem($this->getSize() + 2);
}
public function getBoots() : Item{
return $this->getItem($this->getSize() + 3);
}
public function setHelmet(Item $helmet) : bool{
return $this->setItem($this->getSize(), $helmet);
}
public function setChestplate(Item $chestplate) : bool{
return $this->setItem($this->getSize() + 1, $chestplate);
}
public function setLeggings(Item $leggings) : bool{
return $this->setItem($this->getSize() + 2, $leggings);
}
public function setBoots(Item $boots) : bool{
return $this->setItem($this->getSize() + 3, $boots);
}
protected function doSetItemEvents(int $index, Item $newItem) : ?Item{
if($index >= $this->getSize()){
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityArmorChangeEvent($this->getHolder(), $this->getItem($index), $newItem, $index));
if($ev->isCancelled()){
return null;
}
return $ev->getNewItem();
}
return parent::doSetItemEvents($index, $newItem);
}
public function clearAll(bool $send = true) : void{
parent::clearAll($send);
for($i = $this->getSize(), $m = $i + 4; $i < $m; ++$i){
$this->clear($i, false);
}
if($send){
$this->sendArmorContents($this->getViewers());
}
}
/**
* @return Item[]
*/
public function getArmorContents() : array{
$armor = [];
for($i = 0; $i < 4; ++$i){
$armor[$i] = $this->getItem($this->getSize() + $i);
}
return $armor;
}
/**
* @param Player|Player[] $target
*/
public function sendArmorContents($target){
if($target instanceof Player){
$target = [$target];
}
$armor = $this->getArmorContents();
$pk = new MobArmorEquipmentPacket();
$pk->entityRuntimeId = $this->getHolder()->getId();
$pk->slots = $armor;
$pk->encode();
foreach($target as $player){
if($player === $this->getHolder()){
$pk2 = new InventoryContentPacket();
$pk2->windowId = ContainerIds::ARMOR;
$pk2->items = $armor;
$player->dataPacket($pk2);
}else{
$player->dataPacket($pk);
}
}
}
/**
* @param Item[] $items
*/
public function setArmorContents(array $items){
for($i = 0; $i < 4; ++$i){
if(!isset($items[$i]) or !($items[$i] instanceof Item)){
$items[$i] = ItemFactory::get(Item::AIR, 0, 0);
}
$this->setItem($this->getSize() + $i, $items[$i], false);
}
$this->sendArmorContents($this->getViewers());
}
/**
* @param int $index
* @param Player|Player[] $target
*/
public function sendArmorSlot(int $index, $target){
if($target instanceof Player){
$target = [$target];
}
$armor = $this->getArmorContents();
$pk = new MobArmorEquipmentPacket();
$pk->entityRuntimeId = $this->getHolder()->getId();
$pk->slots = $armor;
$pk->encode();
foreach($target as $player){
if($player === $this->getHolder()){
/** @var Player $player */
$pk2 = new InventorySlotPacket();
$pk2->windowId = ContainerIds::ARMOR;
$pk2->inventorySlot = $index - $this->getSize();
$pk2->item = $this->getItem($index);
$player->dataPacket($pk2);
}else{
$player->dataPacket($pk);
}
}
}
public function sendCreativeContents(){
$pk = new InventoryContentPacket();
$pk->windowId = ContainerIds::CREATIVE;