From 1d999bce8aab9debc723a36aac163ba76c98a8ae Mon Sep 17 00:00:00 2001 From: LeonTG Date: Tue, 26 May 2026 21:56:41 +0200 Subject: [PATCH 1/3] Add API for nms Player.canCriticalAttack(Entity) --- build-data/paper.at | 1 + .../src/main/java/org/bukkit/entity/HumanEntity.java | 8 ++++++++ .../org/bukkit/craftbukkit/entity/CraftHumanEntity.java | 8 ++++++++ 3 files changed, 17 insertions(+) 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..72bcb7dea74f 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,14 @@ default Location getPotentialBedLocation() { */ public void startRiptideAttack(int duration, float attackStrength, @Nullable ItemStack attackItem); + /** + * Check if the player can critical attack the target {@link Entity} + * + * @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..2b557b1a6599 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.checkState(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"); From b633bef8581ef823f59eb2b07cbbd8cfa0c555a0 Mon Sep 17 00:00:00 2001 From: LeonTG Date: Tue, 26 May 2026 22:13:19 +0200 Subject: [PATCH 2/3] Requested Change Co-authored-by: Pedro <3602279+Doc94@users.noreply.github.com> --- .../java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 2b557b1a6599..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 @@ -230,7 +230,7 @@ public void startRiptideAttack(int duration, float damage, ItemStack attackItem) @Override public boolean canCriticalAttack(Entity entity) { - Preconditions.checkState(entity != null, "entity cannot be null"); + Preconditions.checkArgument(entity != null, "entity cannot be null"); return this.getHandle().canCriticalAttack(((CraftEntity) entity).getHandle()) && !this.getHandle().level().paperConfig().entities.behavior.disablePlayerCrits; } From c063ba9ccfc03bc68204b0198c36f0e2b62cae5b Mon Sep 17 00:00:00 2001 From: LeonTG Date: Fri, 29 May 2026 14:19:08 +0200 Subject: [PATCH 3/3] Something like this @Doc94 ? --- paper-api/src/main/java/org/bukkit/entity/HumanEntity.java | 3 +++ 1 file changed, 3 insertions(+) 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 72bcb7dea74f..7b3f86510cfd 100644 --- a/paper-api/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/paper-api/src/main/java/org/bukkit/entity/HumanEntity.java @@ -538,6 +538,9 @@ default Location getPotentialBedLocation() { /** * 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.