54    private const TAG_FALLING_BLOCK = 
"FallingBlock"; 
 
   55    private const TAG_TILE_ID = 
"TileID"; 
 
   56    private const TAG_TILE = 
"Tile"; 
 
   57    private const TAG_DATA = 
"Data"; 
 
   59    public static function getNetworkTypeId() : 
string{ 
return EntityIds::FALLING_BLOCK; }
 
   61    protected Block $block;
 
   64        $this->block = $block;
 
   65        parent::__construct($location, $nbt);
 
   78        if(($fallingBlockTag = $nbt->
getCompoundTag(self::TAG_FALLING_BLOCK)) !== 
null){
 
   80                $blockStateData = $blockDataUpgrader->upgradeBlockStateNbt($fallingBlockTag);
 
   82                throw new SavedDataLoadingException(
"Invalid falling block blockstate: " . $e->getMessage(), 0, $e);
 
   85            if(($tileIdTag = $nbt->
getTag(self::TAG_TILE_ID)) instanceof 
IntTag){
 
   86                $blockId = $tileIdTag->getValue();
 
   87            }elseif(($tileTag = $nbt->
getTag(self::TAG_TILE)) instanceof ByteTag){
 
   88                $blockId = $tileTag->getValue();
 
   90                throw new SavedDataLoadingException(
"Missing legacy falling block info");
 
   92            $damage = $nbt->getByte(self::TAG_DATA, 0);
 
   95                $blockStateData = $blockDataUpgrader->upgradeIntIdMeta($blockId, $damage);
 
   96            }
catch(BlockStateDeserializeException $e){
 
   97                throw new SavedDataLoadingException(
"Invalid legacy falling block data: " . $e->getMessage(), 0, $e);
 
  102            $blockStateId = GlobalBlockStateHandlers::getDeserializer()->deserialize($blockStateData);
 
  103        }
catch(BlockStateDeserializeException $e){
 
  104            throw new SavedDataLoadingException($e->getMessage(), 0, $e);
 
  107        return $factory->fromStateId($blockStateId);
 
  110    public function canCollideWith(Entity $entity) : bool{
 
  120            parent::attack($source);
 
  124    protected function entityBaseTick(
int $tickDiff = 1) : bool{
 
  129        $hasUpdate = parent::entityBaseTick($tickDiff);
 
  131        if(!$this->isFlaggedForDespawn()){
 
  132            $world = $this->getWorld();
 
  133            $pos = $this->location->add(-$this->size->getWidth() / 2, $this->size->getHeight(), -$this->size->getWidth() / 2)->floor();
 
  135            $this->block->position($world, $pos->x, $pos->y, $pos->z);
 
  138            if($this->block instanceof Fallable){
 
  139                $blockTarget = $this->block->tickFalling();
 
  142            if($this->onGround || $blockTarget !== 
null){
 
  143                $this->flagForDespawn();
 
  145                $blockResult = $blockTarget ?? $this->block;
 
  146                $block = $world->getBlock($pos);
 
  147                if(!$block->
canBeReplaced() || !$world->isInWorld($pos->getFloorX(), $pos->getFloorY(), $pos->getFloorZ()) || ($this->onGround && abs($this->location->y - $this->location->getFloorY()) > 0.001)){
 
  148                    $world->dropItem($this->location, $this->block->asItem());
 
  149                    $world->addSound($pos->add(0.5, 0.5, 0.5), 
new BlockBreakSound($blockResult));
 
  151                    $ev = 
new EntityBlockChangeEvent($this, $block, $blockResult);
 
  153                    if(!$ev->isCancelled()){
 
  155                        $world->setBlock($pos, $b);
 
  156                        if($this->onGround && $b instanceof Fallable && ($sound = $b->getLandSound()) !== 
null){
 
  157                            $world->addSound($pos->add(0.5, 0.5, 0.5), $sound);
 
  169        if($this->block instanceof 
Fallable){
 
  170            $damagePerBlock = $this->block->getFallDamagePerBlock();
 
  171            if($damagePerBlock > 0 && ($fallenBlocks = round($this->fallDistance) - 1) > 0){
 
  172                $damage = min($fallenBlocks * $damagePerBlock, $this->block->getMaxFallDamage());
 
  173                foreach($this->getWorld()->getCollidingEntities($this->getBoundingBox()) as $entity){
 
  174                    if($entity instanceof 
Living){
 
  176                        $entity->attack($ev);
 
  180            if(!$this->block->onHitGround($this)){
 
  181                $this->flagForDespawn();
 
 
  187    public function getBlock() : 
Block{
 
  192        $nbt = parent::saveNBT();
 
  193        $nbt->
setTag(self::TAG_FALLING_BLOCK, GlobalBlockStateHandlers::getSerializer()->serialize($this->block->getStateId())->toNbt());
 
  199        return $this->block->asItem();
 
 
  203        parent::syncNetworkData($properties);
 
  205        $properties->setInt(EntityMetadataProperties::VARIANT, TypeConverter::getInstance()->getBlockTranslator()->internalIdToNetworkId($this->block->getStateId()));
 
  209        return $vector3->add(0, 0.49, 0);