idInfoFlattened = $idInfo; parent::__construct($idInfo, $name, $breakInfo); } public function readStateFromData(int $id, int $stateMeta) : void{ $this->facing = BlockDataSerializer::readCoralFacing($stateMeta >> 2); $this->dead = ($stateMeta & BlockLegacyMetadata::CORAL_FAN_HANG_FLAG_DEAD) !== 0; $coralTypeFlag = $stateMeta & BlockLegacyMetadata::CORAL_FAN_HANG_TYPE_MASK; switch($id){ case $this->idInfoFlattened->getBlockId(): $this->coralType = $coralTypeFlag === BlockLegacyMetadata::CORAL_FAN_HANG_TUBE ? CoralType::TUBE() : CoralType::BRAIN(); break; case $this->idInfoFlattened->getAdditionalId(0): $this->coralType = $coralTypeFlag === BlockLegacyMetadata::CORAL_FAN_HANG2_BUBBLE ? CoralType::BUBBLE() : CoralType::FIRE(); break; case $this->idInfoFlattened->getAdditionalId(1): if($coralTypeFlag !== BlockLegacyMetadata::CORAL_FAN_HANG3_HORN){ throw new InvalidBlockStateException("Invalid CORAL_FAN_HANG3 type"); } $this->coralType = CoralType::HORN(); break; default: throw new \LogicException("ID/meta doesn't match any CORAL_FAN_HANG type"); } } public function getId() : int{ if($this->coralType->equals(CoralType::TUBE()) || $this->coralType->equals(CoralType::BRAIN())){ return $this->idInfoFlattened->getBlockId(); }elseif($this->coralType->equals(CoralType::BUBBLE()) || $this->coralType->equals(CoralType::FIRE())){ return $this->idInfoFlattened->getAdditionalId(0); }elseif($this->coralType->equals(CoralType::HORN())){ return $this->idInfoFlattened->getAdditionalId(1); } throw new AssumptionFailedError("All types of coral should be covered"); } public function writeStateToMeta() : int{ $coralTypeFlag = (function() : int{ switch($this->coralType->id()){ case CoralType::TUBE()->id(): return BlockLegacyMetadata::CORAL_FAN_HANG_TUBE; case CoralType::BRAIN()->id(): return BlockLegacyMetadata::CORAL_FAN_HANG_BRAIN; case CoralType::BUBBLE()->id(): return BlockLegacyMetadata::CORAL_FAN_HANG2_BUBBLE; case CoralType::FIRE()->id(): return BlockLegacyMetadata::CORAL_FAN_HANG2_FIRE; case CoralType::HORN()->id(): return BlockLegacyMetadata::CORAL_FAN_HANG3_HORN; default: throw new AssumptionFailedError("All types of coral should be covered"); } })(); return (BlockDataSerializer::writeCoralFacing($this->facing) << 2) | ($this->dead ? BlockLegacyMetadata::CORAL_FAN_HANG_FLAG_DEAD : 0) | $coralTypeFlag; } protected function writeStateToItemMeta() : int{ return CoralTypeIdMap::getInstance()->toId($this->coralType); } public function getStateBitmask() : int{ return 0b1111; } public function asItem() : Item{ return ItemFactory::getInstance()->get( $this->dead ? ItemIds::CORAL_FAN_DEAD : ItemIds::CORAL_FAN, $this->writeStateToItemMeta() ); } public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ $axis = Facing::axis($face); if(($axis !== Axis::X && $axis !== Axis::Z) || !$this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){ return false; } $this->facing = $face; return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); } public function onNearbyBlockChange() : void{ $world = $this->position->getWorld(); if(!$this->canBeSupportedBy($world->getBlock($this->position->getSide(Facing::opposite($this->facing))), $this->facing)){ $world->useBreakOn($this->position); }else{ parent::onNearbyBlockChange(); } } private function canBeSupportedBy(Block $block, int $face) : bool{ return $block->getSupportType($face)->hasCenterSupport(); } }