diff --git a/paper-api/src/main/java/org/bukkit/entity/AbstractArrow.java b/paper-api/src/main/java/org/bukkit/entity/AbstractArrow.java
index e63353ff70..1c2c9ed0d5 100644
--- a/paper-api/src/main/java/org/bukkit/entity/AbstractArrow.java
+++ b/paper-api/src/main/java/org/bukkit/entity/AbstractArrow.java
@@ -5,6 +5,8 @@ import org.bukkit.inventory.ItemStack;
 import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.Unmodifiable;
+import java.util.List;
 
 /**
  * Represents an arrow.
@@ -99,10 +101,23 @@ public interface AbstractArrow extends Projectile {
      * Gets the block to which this arrow is attached.
      *
      * @return the attached block or null if not attached
+     * @deprecated can be attached to multiple blocks use {@link AbstractArrow#getAttachedBlocks()} instead
      */
     @Nullable
+    @Deprecated(since = "1.21.4")
     public Block getAttachedBlock();
 
+    /**
+     * Gets the block(s) which this arrow is attached to.
+     * All the returned blocks are responsible for preventing
+     * the arrow from falling.
+     *
+     * @return the attached block(s) or an empty list if not attached
+     */
+    @NotNull
+    @Unmodifiable
+    List<Block> getAttachedBlocks();
+
     /**
      * Gets the current pickup status of this arrow.
      *
diff --git a/paper-server/patches/sources/net/minecraft/world/entity/projectile/AbstractArrow.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/projectile/AbstractArrow.java.patch
index cf61cc49d2..6bb662ba7c 100644
--- a/paper-server/patches/sources/net/minecraft/world/entity/projectile/AbstractArrow.java.patch
+++ b/paper-server/patches/sources/net/minecraft/world/entity/projectile/AbstractArrow.java.patch
@@ -77,7 +77,7 @@
                  this.hasImpulse = true;
                  if (this.getPierceLevel() > 0 && projectileDeflection == ProjectileDeflection.NONE) {
                      continue;
-@@ -313,6 +_,19 @@
+@@ -313,13 +_,26 @@
          }
      }
  
@@ -97,6 +97,14 @@
      @Override
      protected double getDefaultGravity() {
          return 0.05;
+     }
+ 
+     private boolean shouldFall() {
+-        return this.isInGround() && this.level().noCollision(new AABB(this.position(), this.position()).inflate(0.06));
++        return this.isInGround() && this.level().noCollision(new AABB(this.position(), this.position()).inflate(0.06)); // Paper - getAttachedBlocks api; diff on change
+     }
+ 
+     private void startFalling() {
 @@ -329,7 +_,7 @@
          this.life = 0;
      }
diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java
index af2c1ad8cd..66db4132be 100644
--- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java
+++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java
@@ -1,15 +1,20 @@
 package org.bukkit.craftbukkit.entity;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
 import net.minecraft.core.BlockPos;
+import net.minecraft.world.entity.Entity;
 import net.minecraft.world.item.Items;
+import net.minecraft.world.level.BlockCollisions;
+import net.minecraft.world.phys.AABB;
 import org.bukkit.block.Block;
 import org.bukkit.craftbukkit.CraftServer;
+import org.bukkit.craftbukkit.block.CraftBlock;
 import org.bukkit.craftbukkit.inventory.CraftItemStack;
 import org.bukkit.entity.AbstractArrow;
-import org.bukkit.entity.Entity;
 import org.bukkit.inventory.ItemStack;
-import org.bukkit.projectiles.ProjectileSource;
+import java.util.List;
 
 public class CraftAbstractArrow extends AbstractProjectile implements AbstractArrow {
 
@@ -68,12 +73,16 @@ public class CraftAbstractArrow extends AbstractProjectile implements AbstractAr
 
     @Override
     public Block getAttachedBlock() {
+        return Iterables.getFirst(getAttachedBlocks(), null);
+    }
+
+    @Override
+    public List<Block> getAttachedBlocks() {
         if (!this.isInBlock()) {
-            return null;
+            return ImmutableList.of();
         }
 
-        BlockPos pos = this.getHandle().blockPosition();
-        return this.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+        return ImmutableList.copyOf(new BlockCollisions<>(this.getHandle().level(), (Entity) null, new AABB(this.getHandle().position(), this.getHandle().position()).inflate(0.06), false, (mutableBlockPos, voxelShape) -> CraftBlock.at(this.getHandle().level(), mutableBlockPos)));
     }
 
     @Override