Improved Beds, fixed bed tiles not getting removed for other halves

relates to #880
This commit is contained in:
Dylan K. Taylor 2017-05-23 11:01:42 +01:00
parent 253db40a11
commit 2d626d1d90

View File

@ -38,6 +38,8 @@ use pocketmine\tile\Tile;
use pocketmine\utils\TextFormat;
class Bed extends Transparent{
const BITFLAG_OCCUPIED = 0x04;
const BITFLAG_HEAD = 0x08;
protected $id = self::BED_BLOCK;
@ -64,8 +66,62 @@ class Bed extends Transparent{
);
}
public function onActivate(Item $item, Player $player = null){
public function isHeadPart() : bool{
return ($this->meta & self::BITFLAG_HEAD) !== 0;
}
/**
* @return bool
*/
public function isOccupied() : bool{
return ($this->meta & self::BITFLAG_OCCUPIED) !== 0;
}
/**
* @param int $meta
* @param bool $isHead
*
* @return int
*/
public static function getOtherHalfSide(int $meta, bool $isHead = false) : int{
$rotation = $meta & 0x03;
$side = -1;
switch($rotation){
case 0x00: //South
$side = Vector3::SIDE_SOUTH;
break;
case 0x01: //West
$side = Vector3::SIDE_WEST;
break;
case 0x02: //North
$side = Vector3::SIDE_NORTH;
break;
case 0x03: //East
$side = Vector3::SIDE_EAST;
break;
}
if($isHead){
$side = Vector3::getOppositeSide($side);
}
return $side;
}
/**
* @return Bed|null
*/
public function getOtherHalf(){
$other = $this->getSide(self::getOtherHalfSide($this->meta, $this->isHeadPart()));
if($other instanceof Bed and $other->getId() === $this->getId() and $other->isHeadPart() !== $this->isHeadPart() and (($other->getDamage() & 0x03) === ($this->getDamage() & 0x03))){
return $other;
}
return null;
}
public function onActivate(Item $item, Player $player = null){
$time = $this->getLevel()->getTime() % Level::TIME_FULL;
$isNight = ($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE);
@ -75,31 +131,19 @@ class Bed extends Transparent{
return true;
}
$blockNorth = $this->getSide(2); //Gets the blocks around them
$blockSouth = $this->getSide(3);
$blockEast = $this->getSide(5);
$blockWest = $this->getSide(4);
if(($this->meta & 0x08) === 0x08){ //This is the Top part of bed
$b = $this;
}else{ //Bottom Part of Bed
if($blockNorth->getId() === $this->id and ($blockNorth->meta & 0x08) === 0x08){
$b = $blockNorth;
}elseif($blockSouth->getId() === $this->id and ($blockSouth->meta & 0x08) === 0x08){
$b = $blockSouth;
}elseif($blockEast->getId() === $this->id and ($blockEast->meta & 0x08) === 0x08){
$b = $blockEast;
}elseif($blockWest->getId() === $this->id and ($blockWest->meta & 0x08) === 0x08){
$b = $blockWest;
}else{
if($player instanceof Player){
$player->sendMessage(TextFormat::GRAY . "This bed is incomplete");
}
return true;
$other = $this->getOtherHalf();
if($other === null){
if($player instanceof Player){
$player->sendMessage(TextFormat::GRAY . "This bed is incomplete");
}
return true;
}
$b = ($this->isHeadPart() ? $this : $other);
if($player instanceof Player and $player->sleepOn($b) === false){
//TODO: change this to use the meta bitflags
$player->sendMessage(new TranslationContainer(TextFormat::GRAY . "%tile.bed.occupied"));
}
@ -108,20 +152,12 @@ class Bed extends Transparent{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->isTransparent() === false){
$faces = [
0 => 3,
1 => 4,
2 => 2,
3 => 5,
];
$d = $player instanceof Player ? $player->getDirection() : 0;
$next = $this->getSide($faces[($d + 3) % 4]);
$downNext = $next->getSide(Vector3::SIDE_DOWN);
if($next->canBeReplaced() === true and $downNext->isTransparent() === false){
$meta = (($d + 3) % 4) & 0x03;
if(!$down->isTransparent()){
$meta = (($player instanceof Player ? $player->getDirection() : 0) - 1) & 0x03;
$next = $this->getSide(self::getOtherHalfSide($meta));
if($next->canBeReplaced() === true and !$next->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->setBlock($block, Block::get($this->id, $meta), true, true);
$this->getLevel()->setBlock($next, Block::get($this->id, $meta | 0x08), true, true);
$this->getLevel()->setBlock($next, Block::get($this->id, $meta | self::BITFLAG_HEAD), true, true);
$nbt = new CompoundTag("", [
new StringTag("id", Tile::BED),
@ -146,47 +182,28 @@ class Bed extends Transparent{
}
public function onBreak(Item $item){
$blockNorth = $this->getSide(2); //Gets the blocks around them
$blockSouth = $this->getSide(3);
$blockEast = $this->getSide(5);
$blockWest = $this->getSide(4);
if(($this->meta & 0x08) === 0x08){ //This is the Top part of bed
if($blockNorth->getId() === $this->id and $blockNorth->meta !== 0x08){ //Checks if the block ID and meta are right
$this->getLevel()->setBlock($blockNorth, new Air(), true, true);
}elseif($blockSouth->getId() === $this->id and $blockSouth->meta !== 0x08){
$this->getLevel()->setBlock($blockSouth, new Air(), true, true);
}elseif($blockEast->getId() === $this->id and $blockEast->meta !== 0x08){
$this->getLevel()->setBlock($blockEast, new Air(), true, true);
}elseif($blockWest->getId() === $this->id and $blockWest->meta !== 0x08){
$this->getLevel()->setBlock($blockWest, new Air(), true, true);
}
}else{ //Bottom Part of Bed
if($blockNorth->getId() === $this->id and ($blockNorth->meta & 0x08) === 0x08){
$this->getLevel()->setBlock($blockNorth, new Air(), true, true);
}elseif($blockSouth->getId() === $this->id and ($blockSouth->meta & 0x08) === 0x08){
$this->getLevel()->setBlock($blockSouth, new Air(), true, true);
}elseif($blockEast->getId() === $this->id and ($blockEast->meta & 0x08) === 0x08){
$this->getLevel()->setBlock($blockEast, new Air(), true, true);
}elseif($blockWest->getId() === $this->id and ($blockWest->meta & 0x08) === 0x08){
$this->getLevel()->setBlock($blockWest, new Air(), true, true);
}
$this->getLevel()->setBlock($this, Block::get(Block::AIR), true, true);
if(($other = $this->getOtherHalf()) !== null){
$this->getLevel()->useBreakOn($other); //make sure tiles get removed
}
$this->getLevel()->setBlock($this, new Air(), true, true);
return true;
}
public function getDrops(Item $item){
$tile = $this->getLevel()->getTile($this);
if($tile instanceof TileBed){
return [
[Item::BED, $tile->getColor(), 1]
];
if($this->isHeadPart()){
$tile = $this->getLevel()->getTile($this);
if($tile instanceof TileBed){
return [
[Item::BED, $tile->getColor(), 1]
];
}else{
return [
[Item::BED, 14, 1] //Red
];
}
}else{
return [
[Item::BED, 14, 1] //Red
];
return [];
}
}