Add Shulker Boxes (#3678)

this implementation is working, although incomplete:

- The shulker close sound should not be played until the end of the shulker closing animation, which takes approximately 1 second.
- An open shulker box has a different collision box than a closed one - it should be +0.5 in whichever direction the shulker is facing. (During the animation, the bounding box also dynamically changes size - you can see this in vanilla by shooting an arrow into the top of an open shulkerbox facing UP, and then closing it - the arrow will fall and collide with the lid multiple times.

However, resolving both of these issues requires significant internal changes which are beyond the scope of this PR.
This commit is contained in:
Aericio
2021-07-10 08:48:38 -10:00
committed by GitHub
parent 3997e612b1
commit fc090e238d
10 changed files with 393 additions and 4 deletions

95
src/block/ShulkerBox.php Normal file
View File

@ -0,0 +1,95 @@
<?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/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\tile\ShulkerBox as TileShulkerBox;
use pocketmine\block\utils\AnyFacingTrait;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
class ShulkerBox extends Opaque{
use AnyFacingTrait;
public function writeStateToWorld() : void{
parent::writeStateToWorld();
$shulker = $this->pos->getWorld()->getTile($this->pos);
if($shulker instanceof TileShulkerBox){
$shulker->setFacing($this->facing);
}
}
public function readStateFromWorld() : void{
parent::readStateFromWorld();
$shulker = $this->pos->getWorld()->getTile($this->pos);
if($shulker instanceof TileShulkerBox){
$this->facing = $shulker->getFacing();
}
}
public function getMaxStackSize() : int{
return 1;
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function asItem() : Item{
$item = parent::asItem();
$shulker = $this->pos->getWorld()->getTile($this->pos);
if($shulker instanceof TileShulkerBox){
$shulkerNBT = $shulker->getCleanedNBT();
if($shulkerNBT !== null){
$item->setNamedTag($shulkerNBT);
}
if($shulker->hasName()){
$item->setCustomName($shulker->getName());
}
}
return $item;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player instanceof Player){
$shulker = $this->pos->getWorld()->getTile($this->pos);
if($shulker instanceof TileShulkerBox){
if(
$this->getSide($this->facing)->getId() !== BlockLegacyIds::AIR or
!$shulker->canOpenWith($item->getCustomName())
){
return true;
}
$player->setCurrentWindow($shulker->getInventory());
}
}
return true;
}
}