42 use HorizontalFacingTrait;
44 private BellAttachmentType $attachmentType = BellAttachmentType::FLOOR;
47 $w->enum($this->attachmentType);
48 $w->horizontalFacing($this->facing);
52 if($this->attachmentType === BellAttachmentType::FLOOR){
54 AxisAlignedBB::one()->squash(Facing::axis($this->facing), 1 / 4)->trim(Facing::UP, 3 / 16)
57 if($this->attachmentType === BellAttachmentType::CEILING){
59 AxisAlignedBB::one()->contract(1 / 4, 0, 1 / 4)->trim(Facing::DOWN, 1 / 4)
63 $box = AxisAlignedBB::one()
64 ->squash(Facing::axis(Facing::rotateY($this->facing,
true)), 1 / 4)
65 ->trim(Facing::UP, 1 / 16)
66 ->trim(Facing::DOWN, 1 / 4);
69 $this->attachmentType === BellAttachmentType::ONE_WALL ? $box->trim($this->facing, 3 / 16) : $box
74 return SupportType::NONE;
77 public function getAttachmentType() : BellAttachmentType{ return $this->attachmentType; }
81 $this->attachmentType = $attachmentType;
85 private function canBeSupportedAt(
Block $block,
int $face) : bool{
86 return $block->getAdjacentSupportType($face) !== SupportType::NONE;
90 if(!$this->canBeSupportedAt($blockReplace,
Facing::opposite($face))){
93 if($face === Facing::UP){
95 $this->setFacing(Facing::opposite($player->getHorizontalFacing()));
97 $this->setAttachmentType(BellAttachmentType::FLOOR);
98 }elseif($face === Facing::DOWN){
99 $this->setAttachmentType(BellAttachmentType::CEILING);
101 $this->setFacing($face);
102 $this->setAttachmentType(
103 $this->canBeSupportedAt($blockReplace, $face) ?
104 BellAttachmentType::TWO_WALLS :
105 BellAttachmentType::ONE_WALL
108 return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
112 foreach(match($this->attachmentType){
113 BellAttachmentType::CEILING => [Facing::UP],
114 BellAttachmentType::FLOOR => [Facing::DOWN],
115 BellAttachmentType::ONE_WALL => [Facing::opposite($this->facing)],
116 BellAttachmentType::TWO_WALLS => [$this->facing, Facing::opposite($this->facing)]
117 } as $supportBlockDirection){
118 if(!$this->canBeSupportedAt($this, $supportBlockDirection)){
119 $this->position->getWorld()->useBreakOn($this->position);
126 if($player !== null){
127 $faceHit = Facing::opposite($player->getHorizontalFacing());
128 if($this->isValidFaceToRing($faceHit)){
129 $this->ring($faceHit);
138 $faceHit =
Facing::opposite($projectile->getHorizontalFacing());
139 if($this->isValidFaceToRing($faceHit)){
140 $this->ring($faceHit);
144 public function ring(
int $faceHit) : void{
145 $world = $this->position->getWorld();
146 $world->addSound($this->position,
new BellRingSound());
147 $tile = $world->getTile($this->position);
148 if($tile instanceof TileBell){
149 $world->broadcastPacketToViewers($this->position, $tile->createFakeUpdatePacket($faceHit));
154 return [$this->asItem()];
157 private function isValidFaceToRing(
int $faceHit) : bool{
158 return match($this->attachmentType){
159 BellAttachmentType::CEILING =>
true,
160 BellAttachmentType::FLOOR => Facing::axis($faceHit) === Facing::axis($this->facing),
161 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)