49    public static function getNetworkTypeId() : 
string{ 
return EntityIds::ARROW; }
 
   51    public const PICKUP_NONE = 0;
 
   52    public const PICKUP_ANY = 1;
 
   53    public const PICKUP_CREATIVE = 2;
 
   55    private const TAG_PICKUP = 
"pickup"; 
 
   56    public const TAG_CRIT = 
"crit"; 
 
   57    private const TAG_LIFE = 
"life"; 
 
   59    protected float $damage = 2.0;
 
   60    protected int $pickupMode = self::PICKUP_ANY;
 
   61    protected float $punchKnockback = 0.0;
 
   62    protected int $collideTicks = 0;
 
   63    protected bool $critical = 
false;
 
   66        parent::__construct($location, $shootingEntity, $nbt);
 
   67        $this->setCritical($critical);
 
   76    protected function initEntity(
CompoundTag $nbt) : void{
 
   77        parent::initEntity($nbt);
 
   79        $this->pickupMode = $nbt->getByte(self::TAG_PICKUP, self::PICKUP_ANY);
 
   80        $this->critical = $nbt->getByte(self::TAG_CRIT, 0) === 1;
 
   81        $this->collideTicks = $nbt->getShort(self::TAG_LIFE, $this->collideTicks);
 
   85        $nbt = parent::saveNBT();
 
   86        $nbt->
setByte(self::TAG_PICKUP, $this->pickupMode);
 
   87        $nbt->
setByte(self::TAG_CRIT, $this->critical ? 1 : 0);
 
   88        $nbt->
setShort(self::TAG_LIFE, $this->collideTicks);
 
   92    public function isCritical() : bool{
 
   93        return $this->critical;
 
   96    public function setCritical(
bool $value = 
true) : void{
 
   97        $this->critical = $value;
 
   98        $this->networkPropertiesDirty = 
true;
 
  102        $base = (int) ceil($this->motion->length() * parent::getResultDamage());
 
  103        if($this->isCritical()){
 
  104            return ($base + mt_rand(0, (
int) ($base / 2) + 1));
 
 
  110    public function getPunchKnockback() : float{
 
  111        return $this->punchKnockback;
 
  114    public function setPunchKnockback(
float $punchKnockback) : void{
 
  115        $this->punchKnockback = $punchKnockback;
 
  118    protected function entityBaseTick(
int $tickDiff = 1) : bool{
 
  123        $hasUpdate = parent::entityBaseTick($tickDiff);
 
  125        if($this->blockHit !== 
null){
 
  126            $this->collideTicks += $tickDiff;
 
  127            if($this->collideTicks > 1200){
 
  128                $this->flagForDespawn();
 
  132            $this->collideTicks = 0;
 
  139        $this->setCritical(false);
 
 
  144        parent::onHitBlock($blockHit, $hitResult);
 
 
  149        parent::onHitEntity($entityHit, $hitResult);
 
  150        if($this->punchKnockback > 0){
 
  151            $horizontalSpeed = sqrt($this->motion->x ** 2 + $this->motion->z ** 2);
 
  152            if($horizontalSpeed > 0){
 
  153                $multiplier = $this->punchKnockback * 0.6 / $horizontalSpeed;
 
  154                $entityHit->setMotion($entityHit->getMotion()->add($this->motion->x * $multiplier, 0.1, $this->motion->z * $multiplier));
 
 
  159    public function getPickupMode() : int{
 
  160        return $this->pickupMode;
 
  163    public function setPickupMode(
int $pickupMode) : void{
 
  164        $this->pickupMode = $pickupMode;
 
  167    public function onCollideWithPlayer(Player $player) : void{
 
  168        if($this->blockHit === null){
 
  172        $item = VanillaItems::ARROW();
 
  173        $playerInventory = match(
true){
 
  174            !$player->hasFiniteResources() => 
null, 
 
  175            $player->getOffHandInventory()->getItem(0)->canStackWith($item) && $player->getOffHandInventory()->canAddItem($item) => $player->getOffHandInventory(),
 
  176            $player->getInventory()->canAddItem($item) => $player->getInventory(),
 
  180        $ev = 
new EntityItemPickupEvent($player, $this, $item, $playerInventory);
 
  181        if($player->hasFiniteResources() && $playerInventory === 
null){
 
  184        if($this->pickupMode === self::PICKUP_NONE || ($this->pickupMode === self::PICKUP_CREATIVE && !$player->isCreative())){
 
  189        if($ev->isCancelled()){
 
  193        NetworkBroadcastUtils::broadcastEntityEvent(
 
  195            fn(EntityEventBroadcaster $broadcaster, array $recipients) => $broadcaster->onPickUpItem($recipients, $player, $this)
 
  198        $ev->getInventory()?->addItem($ev->getItem());
 
  199        $this->flagForDespawn();
 
  202    protected function syncNetworkData(EntityMetadataCollection $properties) : void{
 
  203        parent::syncNetworkData($properties);
 
  205        $properties->setGenericFlag(EntityMetadataFlags::CRITICAL, $this->critical);