diff --git a/paper-api/src/main/java/io/papermc/paper/event/entity/EntityKnockbackEvent.java b/paper-api/src/main/java/io/papermc/paper/event/entity/EntityKnockbackEvent.java index 44db373eebb3..2be0c7c05449 100644 --- a/paper-api/src/main/java/io/papermc/paper/event/entity/EntityKnockbackEvent.java +++ b/paper-api/src/main/java/io/papermc/paper/event/entity/EntityKnockbackEvent.java @@ -94,6 +94,10 @@ public enum Cause { * Knockback caused by an attacking entity. */ ENTITY_ATTACK, + /** + * Knockback caused by the sprint bonus applied during an entity attack. + */ + ENTITY_SPRINT_ATTACK, /** * Knockback caused by an explosion. */ diff --git a/paper-api/src/main/java/org/bukkit/event/entity/EntityKnockbackEvent.java b/paper-api/src/main/java/org/bukkit/event/entity/EntityKnockbackEvent.java index c19fe417db05..f71d2e54a69f 100644 --- a/paper-api/src/main/java/org/bukkit/event/entity/EntityKnockbackEvent.java +++ b/paper-api/src/main/java/org/bukkit/event/entity/EntityKnockbackEvent.java @@ -141,6 +141,10 @@ public enum KnockbackCause { * Knockback caused by an attacking entity. */ ENTITY_ATTACK, + /** + * Knockback caused by the sprint bonus applied during an entity attack. + */ + ENTITY_SPRINT_ATTACK, /** * Knockback caused by an explosion. */ diff --git a/paper-server/patches/sources/net/minecraft/world/entity/LivingEntity.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/LivingEntity.java.patch index dd7bcd5582d9..48f275dd5b80 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/LivingEntity.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/LivingEntity.java.patch @@ -597,7 +597,7 @@ if (success) { this.lastDamageSource = source; this.lastDamageStamp = this.level().getGameTime(); -@@ -1300,13 +_,28 @@ +@@ -1300,13 +_,37 @@ zd = source.getSourcePosition().z() - this.getZ(); } @@ -609,9 +609,18 @@ + if (Math.abs(zd) > 200) { + zd = Math.random() - Math.random(); + } -+ // Paper end - Check distance in entity interactions + -+ this.knockback(0.4F, xd, zd, source, damage, source.getDirectEntity(), source.getDirectEntity() == null ? io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.DAMAGE : io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK); // CraftBukkit // Paper - knockback events ++ // Paper start - knockback events ++ io.papermc.paper.event.entity.EntityKnockbackEvent.Cause cause; ++ if (source.getDirectEntity() instanceof LivingEntity living && living.isSprinting()) { ++ cause = io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_SPRINT_ATTACK; ++ } else if (source.getDirectEntity() == null) { ++ cause = io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.DAMAGE; ++ } else { ++ cause = io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK; ++ } ++ this.knockback(0.4F, xd, zd, source, damage, source.getDirectEntity(), cause); ++ // Paper end - knockback events if (!blocked) { this.indicateDamage(xd, zd); } @@ -902,7 +911,7 @@ Vec3 deltaMovement = this.getDeltaMovement(); while (xd * xd + zd * zd < 1.0E-5F) { -@@ -1651,16 +_,32 @@ +@@ -1651,16 +_,33 @@ } Vec3 deltaVector = new Vec3(xd, 0.0, zd).normalize().scale(power); @@ -914,13 +923,14 @@ ); + // Paper start - knockback events + Vec3 knockback = targetMovement.subtract(deltaMovement); -+ io.papermc.paper.event.entity.EntityKnockbackEvent event = CraftEventFactory.callEntityKnockbackEvent((org.bukkit.craftbukkit.entity.CraftLivingEntity) this.getBukkitEntity(), attacker, attacker, eventCause, power, knockback); -+ if (event.isCancelled()) { -+ return; ++ if (!comesFromEffect) { ++ io.papermc.paper.event.entity.EntityKnockbackEvent event = CraftEventFactory.callEntityKnockbackEvent((org.bukkit.craftbukkit.entity.CraftLivingEntity) this.getBukkitEntity(), attacker, attacker, eventCause, power, knockback); ++ if (event.isCancelled()) { ++ return; ++ } + } -+ + this.needsSync = true; -+ this.setDeltaMovement(deltaMovement.add(event.getKnockback().getX(), event.getKnockback().getY(), event.getKnockback().getZ())); ++ this.setDeltaMovement(deltaMovement.add(knockback.x, knockback.y, knockback.z)); + // Paper end - knockback events } } @@ -1271,15 +1281,22 @@ } private Vec3 updateFallFlyingMovement(Vec3 movement) { -@@ -2749,7 +_,7 @@ +@@ -2748,9 +_,14 @@ + final Entity target, final float knockback, final Vec3 oldMovement, final DamageSource damageSource, final float damage, final boolean comesFromEffect ) { if (knockback > 0.0F && target instanceof LivingEntity livingTarget) { ++ // Paper start - knockback events ++ io.papermc.paper.event.entity.EntityKnockbackEvent.Cause cause = this.isSprinting() ++ ? io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_SPRINT_ATTACK ++ : io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK; livingTarget.knockback( - knockback, Mth.sin(this.getYRot() * Mth.DEG_TO_RAD), -Mth.cos(this.getYRot() * Mth.DEG_TO_RAD), damageSource, damage, comesFromEffect -+ knockback, Mth.sin(this.getYRot() * Mth.DEG_TO_RAD), -Mth.cos(this.getYRot() * Mth.DEG_TO_RAD), damageSource, damage, comesFromEffect, this, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK // Paper - knockback events ++ knockback, Mth.sin(this.getYRot() * Mth.DEG_TO_RAD), -Mth.cos(this.getYRot() * Mth.DEG_TO_RAD), damageSource, damage, comesFromEffect, this, cause ); ++ // Paper end - knockback events this.setDeltaMovement(this.getDeltaMovement().multiply(0.6, 1.0, 0.6)); } + } @@ -2826,37 +_,15 @@ profiler.pop(); profiler.push("rangeChecks"); diff --git a/paper-server/patches/sources/net/minecraft/world/entity/player/Player.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/player/Player.java.patch index fb7007df9e5c..e16b9442c4fe 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/player/Player.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/player/Player.java.patch @@ -290,12 +290,13 @@ return true; } else { return false; -@@ -1127,20 +_,41 @@ +@@ -1127,20 +_,42 @@ if (knockbackAmount > 0.0F) { if (entity instanceof LivingEntity livingTarget) { livingTarget.knockback( - knockbackAmount, Mth.sin(this.getYRot() * Mth.DEG_TO_RAD), -Mth.cos(this.getYRot() * Mth.DEG_TO_RAD), damageSource, damage, comesFromEffect -+ knockbackAmount, Mth.sin(this.getYRot() * Mth.DEG_TO_RAD), -Mth.cos(this.getYRot() * Mth.DEG_TO_RAD), damageSource, damage, comesFromEffect, this, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK // Paper - knockback events ++ knockbackAmount, Mth.sin(this.getYRot() * Mth.DEG_TO_RAD), -Mth.cos(this.getYRot() * Mth.DEG_TO_RAD), damageSource, damage, comesFromEffect, this, ++ livingTarget.isSprinting() ? io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_SPRINT_ATTACK : io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK // Paper - knockback events ); } else { - entity.push(-Mth.sin(this.getYRot() * Mth.DEG_TO_RAD) * knockbackAmount, 0.1, Mth.cos(this.getYRot() * Mth.DEG_TO_RAD) * knockbackAmount);