diff --git a/build-data/paper.at b/build-data/paper.at index fc06d593c438..49c31d722d92 100644 --- a/build-data/paper.at +++ b/build-data/paper.at @@ -452,6 +452,7 @@ public net.minecraft.world.entity.player.Player getFireImmuneTicks()I public net.minecraft.world.entity.player.Player hurtDir public net.minecraft.world.entity.player.Player removeEntitiesOnShoulder()V public net.minecraft.world.entity.player.Player sleepCounter +public net.minecraft.world.entity.player.Player canCriticalAttack(Lnet/minecraft/world/entity/Entity;)Z public net.minecraft.world.entity.projectile.EvokerFangs warmupDelayTicks public net.minecraft.world.entity.projectile.EyeOfEnder life public net.minecraft.world.entity.projectile.EyeOfEnder surviveAfterDeath diff --git a/paper-api/src/main/java/org/bukkit/entity/HumanEntity.java b/paper-api/src/main/java/org/bukkit/entity/HumanEntity.java index 2be5f6ba8eeb..7b3f86510cfd 100644 --- a/paper-api/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/paper-api/src/main/java/org/bukkit/entity/HumanEntity.java @@ -536,6 +536,17 @@ default Location getPotentialBedLocation() { */ public void startRiptideAttack(int duration, float attackStrength, @Nullable ItemStack attackItem); + /** + * Check if the player can critical attack the target {@link Entity} + *
+ * Note: When hitting an entity, Minecraft also checks that the result of {@link #getAttackCooldown()} is {@code > 0.9F} + * to determine if the critical attack will happen. + * + * @param entity target entity to check if can critical attack. + * @return Whether they can critical attack the target entity. + */ + public boolean canCriticalAttack(Entity entity); + /** * Gets the location of the bed the player is currently sleeping in * diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java index 0c98e3ec53b4..328069c03765 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java @@ -57,6 +57,7 @@ import org.bukkit.craftbukkit.inventory.util.CraftMenus; import org.bukkit.craftbukkit.util.CraftLocation; import org.bukkit.craftbukkit.util.CraftNamespacedKey; +import org.bukkit.entity.Entity; import org.bukkit.entity.Firework; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Item; @@ -227,6 +228,13 @@ public void startRiptideAttack(int duration, float damage, ItemStack attackItem) this.getHandle().startAutoSpinAttack(duration, damage, CraftItemStack.asNMSCopy(attackItem)); } + @Override + public boolean canCriticalAttack(Entity entity) { + Preconditions.checkArgument(entity != null, "entity cannot be null"); + + return this.getHandle().canCriticalAttack(((CraftEntity) entity).getHandle()) && !this.getHandle().level().paperConfig().entities.behavior.disablePlayerCrits; + } + @Override public Location getBedLocation() { Preconditions.checkState(this.isSleeping(), "Not sleeping");