diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index 5a0536bed..a58d64ac1 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -30,6 +30,7 @@ use pocketmine\event\entity\EntityRegainHealthEvent; use pocketmine\event\player\PlayerExhaustEvent; use pocketmine\event\player\PlayerExperienceChangeEvent; use pocketmine\inventory\EnderChestInventory; +use pocketmine\inventory\EntityInventoryEventProcessor; use pocketmine\inventory\InventoryHolder; use pocketmine\inventory\PlayerInventory; use pocketmine\item\Consumable; @@ -570,6 +571,9 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ $inventoryTag = $this->namedtag->getListTag("Inventory"); if($inventoryTag !== null){ + $armorListener = $this->armorInventory->getEventProcessor(); + $this->armorInventory->setEventProcessor(null); + /** @var CompoundTag $item */ foreach($inventoryTag as $i => $item){ $slot = $item->getByte("Slot"); @@ -581,6 +585,8 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ $this->inventory->setItem($slot - 9, Item::nbtDeserialize($item)); } } + + $this->armorInventory->setEventProcessor($armorListener); } $enderChestInventoryTag = $this->namedtag->getListTag("EnderChestInventory"); @@ -593,6 +599,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ $this->inventory->setHeldItemIndex($this->namedtag->getInt("SelectedInventorySlot", 0), false); + $this->inventory->setEventProcessor(new EntityInventoryEventProcessor($this)); $this->setFood((float) $this->namedtag->getInt("foodLevel", (int) $this->getFood(), true)); $this->setExhaustion($this->namedtag->getFloat("foodExhaustionLevel", $this->getExhaustion(), true)); diff --git a/src/pocketmine/entity/Living.php b/src/pocketmine/entity/Living.php index cc7b91c9a..55c2a03ae 100644 --- a/src/pocketmine/entity/Living.php +++ b/src/pocketmine/entity/Living.php @@ -31,6 +31,7 @@ use pocketmine\event\entity\EntityDeathEvent; use pocketmine\event\entity\EntityEffectAddEvent; use pocketmine\event\entity\EntityEffectRemoveEvent; use pocketmine\inventory\ArmorInventory; +use pocketmine\inventory\ArmorInventoryEventProcessor; use pocketmine\item\Armor; use pocketmine\item\Consumable; use pocketmine\item\enchantment\Enchantment; @@ -76,6 +77,8 @@ abstract class Living extends Entity implements Damageable{ parent::initEntity(); $this->armorInventory = new ArmorInventory($this); + //TODO: load/save armor inventory contents + $this->armorInventory->setEventProcessor(new ArmorInventoryEventProcessor($this)); $health = $this->getMaxHealth(); diff --git a/src/pocketmine/inventory/ArmorInventory.php b/src/pocketmine/inventory/ArmorInventory.php index 1072c361d..e894de67d 100644 --- a/src/pocketmine/inventory/ArmorInventory.php +++ b/src/pocketmine/inventory/ArmorInventory.php @@ -24,13 +24,11 @@ declare(strict_types=1); namespace pocketmine\inventory; use pocketmine\entity\Living; -use pocketmine\event\entity\EntityArmorChangeEvent; use pocketmine\item\Item; use pocketmine\network\mcpe\protocol\InventoryContentPacket; use pocketmine\network\mcpe\protocol\InventorySlotPacket; use pocketmine\network\mcpe\protocol\MobArmorEquipmentPacket; use pocketmine\Player; -use pocketmine\Server; class ArmorInventory extends BaseInventory{ public const SLOT_HEAD = 0; @@ -90,15 +88,6 @@ class ArmorInventory extends BaseInventory{ return $this->setItem(self::SLOT_FEET, $boots); } - protected function doSetItemEvents(int $index, Item $newItem) : ?Item{ - Server::getInstance()->getPluginManager()->callEvent($ev = new EntityArmorChangeEvent($this->getHolder(), $this->getItem($index), $newItem, $index)); - if($ev->isCancelled()){ - return null; - } - - return $ev->getNewItem(); - } - public function sendSlot(int $index, $target) : void{ if($target instanceof Player){ $target = [$target]; diff --git a/src/pocketmine/inventory/ArmorInventoryEventProcessor.php b/src/pocketmine/inventory/ArmorInventoryEventProcessor.php new file mode 100644 index 000000000..e7e5ea119 --- /dev/null +++ b/src/pocketmine/inventory/ArmorInventoryEventProcessor.php @@ -0,0 +1,47 @@ +entity = $entity; + } + + public function onSlotChange(Inventory $inventory, int $slot, Item $oldItem, Item $newItem) : ?Item{ + Server::getInstance()->getPluginManager()->callEvent($ev = new EntityArmorChangeEvent($this->entity, $oldItem, $newItem, $slot)); + if($ev->isCancelled()){ + return null; + } + + return $ev->getNewItem(); + } +} diff --git a/src/pocketmine/inventory/BaseInventory.php b/src/pocketmine/inventory/BaseInventory.php index 6905bad75..337b3b80a 100644 --- a/src/pocketmine/inventory/BaseInventory.php +++ b/src/pocketmine/inventory/BaseInventory.php @@ -45,6 +45,8 @@ abstract class BaseInventory implements Inventory{ protected $slots = []; /** @var Player[] */ protected $viewers = []; + /** @var InventoryEventProcessor */ + protected $eventProcessor; /** * @param Item[] $items @@ -153,10 +155,6 @@ abstract class BaseInventory implements Inventory{ $this->clearAll(); } - protected function doSetItemEvents(int $index, Item $newItem) : ?Item{ - return $newItem; - } - public function setItem(int $index, Item $item, bool $send = true) : bool{ if($item->isNull()){ $item = ItemFactory::get(Item::AIR, 0, 0); @@ -164,14 +162,18 @@ abstract class BaseInventory implements Inventory{ $item = clone $item; } - $newItem = $this->doSetItemEvents($index, $item); - if($newItem === null){ - return false; + $oldItem = $this->getItem($index); + if($this->eventProcessor !== null){ + $newItem = $this->eventProcessor->onSlotChange($this, $index, $oldItem, $item); + if($newItem === null){ + return false; + } + }else{ + $newItem = $item; } - $old = $this->getItem($index); $this->slots[$index] = $newItem->isNull() ? null : $newItem; - $this->onSlotChange($index, $old, $send); + $this->onSlotChange($index, $oldItem, $send); return true; } @@ -471,4 +473,12 @@ abstract class BaseInventory implements Inventory{ public function slotExists(int $slot) : bool{ return $slot >= 0 and $slot < $this->slots->getSize(); } + + public function getEventProcessor() : ?InventoryEventProcessor{ + return $this->eventProcessor; + } + + public function setEventProcessor(?InventoryEventProcessor $eventProcessor) : void{ + $this->eventProcessor = $eventProcessor; + } } diff --git a/src/pocketmine/inventory/EntityInventory.php b/src/pocketmine/inventory/EntityInventoryEventProcessor.php similarity index 68% rename from src/pocketmine/inventory/EntityInventory.php rename to src/pocketmine/inventory/EntityInventoryEventProcessor.php index 28c4e7583..7e71afed9 100644 --- a/src/pocketmine/inventory/EntityInventory.php +++ b/src/pocketmine/inventory/EntityInventoryEventProcessor.php @@ -28,28 +28,20 @@ use pocketmine\event\entity\EntityInventoryChangeEvent; use pocketmine\item\Item; use pocketmine\Server; -abstract class EntityInventory extends BaseInventory{ +class EntityInventoryEventProcessor implements InventoryEventProcessor{ /** @var Entity */ - protected $holder; + private $entity; - public function __construct(Entity $holder, array $items = [], int $size = null, string $title = null){ - $this->holder = $holder; - parent::__construct($items, $size, $title); + public function __construct(Entity $entity){ + $this->entity = $entity; } - protected function doSetItemEvents(int $index, Item $newItem) : ?Item{ - Server::getInstance()->getPluginManager()->callEvent($ev = new EntityInventoryChangeEvent($this->getHolder(), $this->getItem($index), $newItem, $index)); + public function onSlotChange(Inventory $inventory, int $slot, Item $oldItem, Item $newItem) : ?Item{ + Server::getInstance()->getPluginManager()->callEvent($ev = new EntityInventoryChangeEvent($this->entity, $oldItem, $newItem, $slot)); if($ev->isCancelled()){ return null; } return $ev->getNewItem(); } - - /** - * @return Entity - */ - public function getHolder(){ - return $this->holder; - } } diff --git a/src/pocketmine/inventory/FurnaceInventory.php b/src/pocketmine/inventory/FurnaceInventory.php index 14a1138ff..00f876b76 100644 --- a/src/pocketmine/inventory/FurnaceInventory.php +++ b/src/pocketmine/inventory/FurnaceInventory.php @@ -102,10 +102,4 @@ class FurnaceInventory extends ContainerInventory{ public function setSmelting(Item $item) : bool{ return $this->setItem(0, $item); } - - public function onSlotChange(int $index, Item $before, bool $send) : void{ - parent::onSlotChange($index, $before, $send); - - $this->getHolder()->scheduleUpdate(); - } } diff --git a/src/pocketmine/inventory/Inventory.php b/src/pocketmine/inventory/Inventory.php index ab1e29374..199b7b04a 100644 --- a/src/pocketmine/inventory/Inventory.php +++ b/src/pocketmine/inventory/Inventory.php @@ -247,4 +247,14 @@ interface Inventory{ * @return bool */ public function slotExists(int $slot) : bool; + + /** + * @return null|InventoryEventProcessor + */ + public function getEventProcessor() : ?InventoryEventProcessor; + + /** + * @param null|InventoryEventProcessor $eventProcessor + */ + public function setEventProcessor(?InventoryEventProcessor $eventProcessor) : void; } diff --git a/src/pocketmine/inventory/InventoryEventProcessor.php b/src/pocketmine/inventory/InventoryEventProcessor.php new file mode 100644 index 000000000..0ecafec3c --- /dev/null +++ b/src/pocketmine/inventory/InventoryEventProcessor.php @@ -0,0 +1,48 @@ +holder = $player; + parent::__construct(); } public function getName() : string{ @@ -210,5 +211,4 @@ class PlayerInventory extends EntityInventory{ public function getHolder(){ return $this->holder; } - } diff --git a/src/pocketmine/tile/Furnace.php b/src/pocketmine/tile/Furnace.php index 6a78db168..3920b4026 100644 --- a/src/pocketmine/tile/Furnace.php +++ b/src/pocketmine/tile/Furnace.php @@ -29,6 +29,8 @@ use pocketmine\event\inventory\FurnaceBurnEvent; use pocketmine\event\inventory\FurnaceSmeltEvent; use pocketmine\inventory\FurnaceInventory; use pocketmine\inventory\FurnaceRecipe; +use pocketmine\inventory\Inventory; +use pocketmine\inventory\InventoryEventProcessor; use pocketmine\inventory\InventoryHolder; use pocketmine\item\Item; use pocketmine\item\ItemFactory; @@ -79,6 +81,20 @@ class Furnace extends Spawnable implements InventoryHolder, Container, Nameable{ $this->inventory = new FurnaceInventory($this); $this->loadItems($nbt); + + $this->inventory->setEventProcessor(new class($this) implements InventoryEventProcessor{ + /** @var Furnace */ + private $furnace; + + public function __construct(Furnace $furnace){ + $this->furnace = $furnace; + } + + public function onSlotChange(Inventory $inventory, int $slot, Item $oldItem, Item $newItem) : ?Item{ + $this->furnace->scheduleUpdate(); + return $newItem; + } + }); } protected function writeSaveData(CompoundTag $nbt) : void{