facing, clockwise: true); } public function onNearbyBlockChange() : void{ //NOOP - disable default self-destruct behaviour } protected function recalculateCollisionBoxes() : array{ //only the cross bar is collidable return [AxisAlignedBB::one()->trim(Facing::DOWN, 7 / 8)->squash(Facing::axis($this->facing), 3 / 4)]; } public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ if($player === null){ return false; } $attachFace = Facing::axis($face) === Axis::Y ? Facing::rotateY($player->getHorizontalFacing(), clockwise: true) : $face; if($this->canBeSupportedAt($blockReplace->getSide($attachFace), $attachFace)){ $direction = $attachFace; }elseif($this->canBeSupportedAt($blockReplace->getSide($opposite = Facing::opposite($attachFace)), $opposite)){ $direction = $opposite; }else{ return false; } $this->facing = Facing::rotateY(Facing::opposite($direction), clockwise: true); //the front should always face the player if possible if($this->facing === $player->getHorizontalFacing()){ $this->facing = Facing::opposite($this->facing); } return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); } private function canBeSupportedAt(Block $block, int $face) : bool{ return ($block instanceof WallHangingSign && Facing::axis(Facing::rotateY($block->getFacing(), clockwise: true)) === Facing::axis($face)) || $block->getSupportType(Facing::opposite($face)) === SupportType::FULL; } protected function getFacingDegrees() : float{ return match($this->facing){ Facing::SOUTH => 0, Facing::WEST => 90, Facing::NORTH => 180, Facing::EAST => 270, default => throw new AssumptionFailedError("Invalid facing direction: " . $this->facing), }; } }