43 use HorizontalFacingTrait;
45 private BellAttachmentType $attachmentType = BellAttachmentType::FLOOR;
48 $w->enum($this->attachmentType);
49 $w->horizontalFacing($this->facing);
53 if($this->attachmentType === BellAttachmentType::FLOOR){
55 AxisAlignedBB::one()->squash(Facing::axis($this->facing), 1 / 4)->trim(Facing::UP, 3 / 16)
58 if($this->attachmentType === BellAttachmentType::CEILING){
60 AxisAlignedBB::one()->contract(1 / 4, 0, 1 / 4)->trim(Facing::DOWN, 1 / 4)
64 $box = AxisAlignedBB::one()
65 ->squash(Facing::axis(Facing::rotateY($this->facing,
true)), 1 / 4)
66 ->trim(Facing::UP, 1 / 16)
67 ->trim(Facing::DOWN, 1 / 4);
70 $this->attachmentType === BellAttachmentType::ONE_WALL ? $box->trim($this->facing, 3 / 16) : $box
75 return SupportType::NONE;
78 public function getAttachmentType() : BellAttachmentType{ return $this->attachmentType; }
82 $this->attachmentType = $attachmentType;
86 private function canBeSupportedAt(
Block $block,
int $face) : bool{
87 return $block->getAdjacentSupportType($face) !== SupportType::NONE;
91 if(!$this->canBeSupportedAt($blockReplace,
Facing::opposite($face))){
94 if($face === Facing::UP){
96 $this->setFacing(Facing::opposite($player->getHorizontalFacing()));
98 $this->setAttachmentType(BellAttachmentType::FLOOR);
99 }elseif($face === Facing::DOWN){
100 $this->setAttachmentType(BellAttachmentType::CEILING);
102 $this->setFacing($face);
103 $this->setAttachmentType(
104 $this->canBeSupportedAt($blockReplace, $face) ?
105 BellAttachmentType::TWO_WALLS :
106 BellAttachmentType::ONE_WALL
109 return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
113 foreach(match($this->attachmentType){
114 BellAttachmentType::CEILING => [Facing::UP],
115 BellAttachmentType::FLOOR => [Facing::DOWN],
116 BellAttachmentType::ONE_WALL => [Facing::opposite($this->facing)],
117 BellAttachmentType::TWO_WALLS => [$this->facing, Facing::opposite($this->facing)]
118 } as $supportBlockDirection){
119 if(!$this->canBeSupportedAt($this, $supportBlockDirection)){
120 $this->position->getWorld()->useBreakOn($this->position);
127 if($player !== null){
128 $faceHit = Facing::opposite($player->getHorizontalFacing());
129 if($this->isValidFaceToRing($faceHit)){
130 $this->ring($faceHit);
139 $faceHit =
Facing::opposite($projectile->getHorizontalFacing());
140 if($this->isValidFaceToRing($faceHit)){
141 $this->ring($faceHit);
145 public function ring(
int $faceHit) : void{
146 $world = $this->position->getWorld();
147 $world->addSound($this->position,
new BellRingSound());
148 $tile = $world->getTile($this->position);
149 if($tile instanceof TileBell){
150 $world->broadcastPacketToViewers($this->position, $tile->createFakeUpdatePacket($faceHit));
155 return [$this->asItem()];
158 private function isValidFaceToRing(
int $faceHit) : bool{
159 return match($this->attachmentType){
160 BellAttachmentType::CEILING =>
true,
161 BellAttachmentType::FLOOR => Facing::axis($faceHit) === Facing::axis($this->facing),
162 BellAttachmentType::ONE_WALL, BellAttachmentType::TWO_WALLS => $faceHit === Facing::rotateY($this->facing,
false) || $faceHit === Facing::rotateY($this->facing,
true),
place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player=null)