text = new SignText(); } public function __clone(){ parent::__clone(); $this->text = clone $this->text; } public function getId() : int{ return $this->facing === Facing::UP ? parent::getId() : $this->idInfo->getSecondId(); } protected function writeStateToMeta() : int{ if($this->facing === Facing::UP){ return $this->rotation; } return BlockDataSerializer::writeHorizontalFacing($this->facing); } public function readStateFromData(int $id, int $stateMeta) : void{ if($id === $this->idInfo->getSecondId()){ $this->facing = BlockDataSerializer::readHorizontalFacing($stateMeta); }else{ $this->facing = Facing::UP; $this->rotation = $stateMeta; } } public function readStateFromWorld() : void{ parent::readStateFromWorld(); $tile = $this->pos->getWorldNonNull()->getTile($this->pos); if($tile instanceof TileSign){ $this->text = $tile->getText(); } } public function writeStateToWorld() : void{ parent::writeStateToWorld(); $tile = $this->pos->getWorldNonNull()->getTile($this->pos); assert($tile instanceof TileSign); $tile->setText($this->text); } public function getStateBitmask() : int{ return 0b1111; } public function isSolid() : bool{ return false; } /** * @return AxisAlignedBB[] */ protected function recalculateCollisionBoxes() : array{ return []; } public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ if($face !== Facing::DOWN){ $this->facing = $face; if($face === Facing::UP){ $this->rotation = $player !== null ? ((int) floor((($player->getLocation()->getYaw() + 180) * 16 / 360) + 0.5)) & 0x0f : 0; } return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); } return false; } public function onNearbyBlockChange() : void{ if($this->getSide(Facing::opposite($this->facing))->getId() === BlockLegacyIds::AIR){ $this->pos->getWorldNonNull()->useBreakOn($this->pos); } } /** * Returns an object containing information about the sign text. */ public function getText() : SignText{ return $this->text; } /** * Called by the player controller (network session) to update the sign text, firing events as appropriate. * * @return bool if the sign update was successful. * @throws \UnexpectedValueException if the text payload is too large */ public function updateText(Player $author, SignText $text) : bool{ $size = 0; foreach($text->getLines() as $line){ $size += strlen($line); } if($size > 1000){ throw new \UnexpectedValueException($author->getName() . " tried to write $size bytes of text onto a sign (bigger than max 1000)"); } $removeFormat = $author->getRemoveFormat(); $ev = new SignChangeEvent($this, $author, new SignText(array_map(function(string $line) use ($removeFormat) : string{ return TextFormat::clean($line, $removeFormat); }, $text->getLines()))); $ev->call(); if(!$ev->isCancelled()){ $this->text = clone $ev->getNewText(); $this->pos->getWorldNonNull()->setBlock($this->pos, $this); return true; } return false; } }