From 686e1c447026f63c295a6599bdf824d330b953fc Mon Sep 17 00:00:00 2001 From: JackNoordhuis Date: Thu, 23 Nov 2017 01:25:21 +1100 Subject: [PATCH] Implement ender chest (#1462) --- src/pocketmine/Server.php | 1 + src/pocketmine/block/BlockFactory.php | 2 +- src/pocketmine/block/EnderChest.php | 113 ++++++++++++++++++ src/pocketmine/entity/Human.php | 36 ++++++ .../inventory/EnderChestInventory.php | 73 +++++++++++ src/pocketmine/tile/EnderChest.php | 34 ++++++ src/pocketmine/tile/Tile.php | 2 + 7 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 src/pocketmine/block/EnderChest.php create mode 100644 src/pocketmine/inventory/EnderChestInventory.php create mode 100644 src/pocketmine/tile/EnderChest.php diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index 7a8f88810..78018ca0b 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -774,6 +774,7 @@ class Server{ //new IntTag("SpawnZ", (int) $spawn->z), //new ByteTag("SpawnForced", 1), //TODO new ListTag("Inventory", [], NBT::TAG_Compound), + new ListTag("EnderChestInventory", [], NBT::TAG_Compound), new CompoundTag("Achievements", []), new IntTag("playerGameType", $this->getGamemode()), new ListTag("Motion", [ diff --git a/src/pocketmine/block/BlockFactory.php b/src/pocketmine/block/BlockFactory.php index eed630862..7bf6157fb 100644 --- a/src/pocketmine/block/BlockFactory.php +++ b/src/pocketmine/block/BlockFactory.php @@ -199,7 +199,7 @@ class BlockFactory{ self::registerBlock(new CocoaBlock()); self::registerBlock(new SandstoneStairs()); self::registerBlock(new EmeraldOre()); - //TODO: ENDER_CHEST + self::registerBlock(new EnderChest()); self::registerBlock(new TripwireHook()); self::registerBlock(new Tripwire()); self::registerBlock(new Emerald()); diff --git a/src/pocketmine/block/EnderChest.php b/src/pocketmine/block/EnderChest.php new file mode 100644 index 000000000..36c0f6dd0 --- /dev/null +++ b/src/pocketmine/block/EnderChest.php @@ -0,0 +1,113 @@ + 4, + 1 => 2, + 2 => 5, + 3 => 3 + ]; + + $this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0]; + + $this->getLevel()->setBlock($blockReplace, $this, true, true); + Tile::createTile(Tile::ENDER_CHEST, $this->getLevel(), TileEnderChest::createNBT($this, $face, $item, $player)); + + return true; + } + + public function onBreak(Item $item, Player $player = null) : bool{ + return Block::onBreak($item, $player); + } + + public function onActivate(Item $item, Player $player = null) : bool{ + if($player instanceof Player){ + + $t = $this->getLevel()->getTile($this); + $enderChest = null; + if($t instanceof TileEnderChest){ + $enderChest = $t; + }else{ + $enderChest = Tile::createTile(Tile::ENDER_CHEST, $this->getLevel(), TileEnderChest::createNBT($this)); + } + + if(!$this->getSide(Vector3::SIDE_UP)->isTransparent()){ + return true; + } + + $player->getEnderChestInventory()->setHolderPosition($enderChest); + $player->addWindow($player->getEnderChestInventory()); + } + + return true; + } + + public function getDrops(Item $item) : array{ + if($item->isPickaxe() >= Tool::TIER_WOODEN){ + return [ItemFactory::get(Item::OBSIDIAN, 0, 8)]; + } + + return []; + } + + public function getFuelTime() : int{ + return 0; + } + +} \ No newline at end of file diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index 3ab5f1c62..30a1062de 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -27,6 +27,7 @@ use pocketmine\entity\projectile\ProjectileSource; use pocketmine\event\entity\EntityDamageEvent; use pocketmine\event\entity\EntityRegainHealthEvent; use pocketmine\event\player\PlayerExhaustEvent; +use pocketmine\inventory\EnderChestInventory; use pocketmine\inventory\InventoryHolder; use pocketmine\inventory\PlayerInventory; use pocketmine\item\enchantment\Enchantment; @@ -54,6 +55,9 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ /** @var PlayerInventory */ protected $inventory; + /** @var EnderChestInventory */ + protected $enderChestInventory; + /** @var UUID */ protected $uuid; protected $rawUUID; @@ -309,6 +313,10 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ return $this->inventory; } + public function getEnderChestInventory(){ + return $this->enderChestInventory; + } + /** * For Human entities which are not players, sets their properties such as nametag, skin and UUID from NBT. */ @@ -334,6 +342,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ $this->setDataProperty(self::DATA_PLAYER_BED_POSITION, self::DATA_TYPE_POS, [0, 0, 0], false); $this->inventory = new PlayerInventory($this); + $this->enderChestInventory = new EnderChestInventory($this); $this->initHumanData(); $inventoryTag = $this->namedtag->getListTag("Inventory"); @@ -352,6 +361,14 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ } } + $enderChestInventoryTag = $this->namedtag->getListTag("EnderChestInventory"); + if($enderChestInventoryTag !== null){ + /** @var CompoundTag $item */ + foreach($enderChestInventoryTag as $i => $item){ + $this->enderChestInventory->setItem($item->getByte("Slot"), ItemItem::nbtDeserialize($item)); + } + } + $this->inventory->setHeldItemIndex($this->namedtag->getInt("SelectedInventorySlot", 0), false); parent::initEntity(); @@ -483,6 +500,21 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ $this->namedtag->setInt("SelectedInventorySlot", $this->inventory->getHeldItemIndex()); } + if($this->enderChestInventory !== null){ + /** @var CompoundTag[] $items */ + $items = []; + + $slotCount = $this->enderChestInventory->getSize(); + for($slot = 0; $slot < $slotCount; ++$slot){ + $item = $this->enderChestInventory->getItem($slot); + if(!$item->isNull()){ + $items[] = $item->nbtSerialize($slot); + } + } + + $this->namedtag->setTag(new ListTag("EnderChestInventory", $items, NBT::TAG_Compound)); + } + if($this->skin !== null){ $this->namedtag->setTag(new CompoundTag("Skin", [ //TODO: save cape & geometry @@ -528,6 +560,10 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ $this->inventory->removeAllViewers(true); $this->inventory = null; } + if($this->enderChestInventory !== null){ + $this->enderChestInventory->removeAllViewers(true); + $this->enderChestInventory = null; + } parent::close(); } } diff --git a/src/pocketmine/inventory/EnderChestInventory.php b/src/pocketmine/inventory/EnderChestInventory.php new file mode 100644 index 000000000..8a855603a --- /dev/null +++ b/src/pocketmine/inventory/EnderChestInventory.php @@ -0,0 +1,73 @@ +getPosition())); + } + + public function getNetworkType() : int{ + return WindowTypes::CONTAINER; + } + + public function getName() : string{ + return "EnderChest"; + } + + public function getDefaultSize() : int{ + return 27; + } + + /** + * Set the holder's position to that of a tile + * + * @param EnderChest $enderChest + */ + public function setHolderPosition(EnderChest $enderChest){ + $this->holder->setComponents($enderChest->getX(), $enderChest->getY(), $enderChest->getZ()); + $this->holder->setLevel($enderChest->getLevel()); + } + + /** + * This override is here for documentation and code completion purposes only. + * @return FakeBlockMenu + */ + public function getHolder(){ + return $this->holder; + } + +} \ No newline at end of file diff --git a/src/pocketmine/tile/EnderChest.php b/src/pocketmine/tile/EnderChest.php new file mode 100644 index 000000000..fc8ac5a40 --- /dev/null +++ b/src/pocketmine/tile/EnderChest.php @@ -0,0 +1,34 @@ +