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