From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Brokkonaut Date: Mon, 18 Jun 2018 15:46:23 +0200 Subject: [PATCH] Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent Co-authored-by: aerulion This event is called when an entity receives knockback by another entity. diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java index 0cc82ffdcebbdd92fa953e7c52a20911f46a503c..165cc45e2ae99e606533e5e5294e431ed5e3a2dd 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -1868,9 +1868,23 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S } } - public void push(double deltaX, double deltaY, double deltaZ) { - this.setDeltaMovement(this.getDeltaMovement().add(deltaX, deltaY, deltaZ)); + public final void push(double deltaX, double deltaY, double deltaZ) { // Paper - override the added overload below + // Paper start - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent + this.push(deltaX, deltaY, deltaZ, null); + } + + public void push(double deltaX, double deltaY, double deltaZ, @org.jetbrains.annotations.Nullable Entity pushingEntity) { + org.bukkit.util.Vector delta = new org.bukkit.util.Vector(deltaX, deltaY, deltaZ); + if (pushingEntity != null) { + io.papermc.paper.event.entity.EntityPushedByEntityAttackEvent event = new io.papermc.paper.event.entity.EntityPushedByEntityAttackEvent(getBukkitEntity(), pushingEntity.getBukkitEntity(), delta); + if (!event.callEvent()) { + return; + } + delta = event.getAcceleration(); + } + this.setDeltaMovement(this.getDeltaMovement().add(delta.getX(), delta.getY(), delta.getZ())); this.hasImpulse = true; + // Paper end - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent } protected void markHurt() { diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java index e3dfef027fb7f6aedd3e3411af6457671b5507a7..88af8a11dfc3b645c5a2b5fb629a73fc1e2b2f80 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -1569,7 +1569,7 @@ public abstract class LivingEntity extends Entity implements Attackable { } protected void blockedByShield(LivingEntity target) { - target.knockback(0.5D, target.getX() - this.getX(), target.getZ() - this.getZ(), null, EntityKnockbackEvent.KnockbackCause.SHIELD_BLOCK); // CraftBukkit + target.knockback(0.5D, target.getX() - this.getX(), target.getZ() - this.getZ(), this, EntityKnockbackEvent.KnockbackCause.SHIELD_BLOCK); // CraftBukkit // Paper - fix attacker } private boolean checkTotemDeathProtection(DamageSource source) { @@ -1832,7 +1832,7 @@ public abstract class LivingEntity extends Entity implements Attackable { this.knockback(strength, x, z, null, EntityKnockbackEvent.KnockbackCause.UNKNOWN); } - public void knockback(double d0, double d1, double d2, Entity attacker, EntityKnockbackEvent.KnockbackCause cause) { + public void knockback(double d0, double d1, double d2, @Nullable Entity attacker, EntityKnockbackEvent.KnockbackCause cause) { // Paper - add nullable to attacker param d0 *= 1.0D - this.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE); if (true || d0 > 0.0D) { // CraftBukkit - Call event even when force is 0 //this.hasImpulse = true; // CraftBukkit - Move down @@ -1844,8 +1844,22 @@ public abstract class LivingEntity extends Entity implements Attackable { return; } + // Paper start - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent + final org.bukkit.util.Vector currentMovement = this.getBukkitEntity().getVelocity(); + org.bukkit.util.Vector resultingMovement = event.getFinalKnockback(); + final org.bukkit.util.Vector deltaMovement = resultingMovement.clone().subtract(currentMovement); + if (attacker != null) { + final com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent knockbackEvent = new com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent(this.getBukkitLivingEntity(), attacker.getBukkitEntity(), (float) event.getForce(), deltaMovement); + if (!knockbackEvent.callEvent()) { + return; + } + + // Back from delta to the absolute vector + resultingMovement = currentMovement.add(knockbackEvent.getAcceleration()); + } this.hasImpulse = true; - this.setDeltaMovement(event.getFinalKnockback().getX(), event.getFinalKnockback().getY(), event.getFinalKnockback().getZ()); + this.setDeltaMovement(resultingMovement.getX(), resultingMovement.getY(), resultingMovement.getZ()); + // Paper end - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent // CraftBukkit end } } diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/RamTarget.java b/src/main/java/net/minecraft/world/entity/ai/behavior/RamTarget.java index 312398b7f1281144a0529a743d2a09376d575ff5..0c63779af7e1c790160fb2ab86bf455219b3cc36 100644 --- a/src/main/java/net/minecraft/world/entity/ai/behavior/RamTarget.java +++ b/src/main/java/net/minecraft/world/entity/ai/behavior/RamTarget.java @@ -83,7 +83,7 @@ public class RamTarget extends Behavior { float f = 0.25F * (float)(i - j); float g = Mth.clamp(entity.getSpeed() * 1.65F, 0.2F, 3.0F) + f; float h = livingEntity.isDamageSourceBlocked(world.damageSources().mobAttack(entity)) ? 0.5F : 1.0F; - livingEntity.knockback((double)(h * g) * this.getKnockbackForce.applyAsDouble(entity), this.ramDirection.x(), this.ramDirection.z()); + livingEntity.knockback(h * g * this.getKnockbackForce.applyAsDouble(entity), this.ramDirection.x(), this.ramDirection.z(), entity, org.bukkit.event.entity.EntityKnockbackEvent.KnockbackCause.ENTITY_ATTACK); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent this.finishRam(world, entity); world.playSound(null, entity, this.getImpactSound.apply(entity), SoundSource.NEUTRAL, 1.0F, 1.0F); } else if (this.hasRammedHornBreakingBlock(world, entity)) { diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/warden/SonicBoom.java b/src/main/java/net/minecraft/world/entity/ai/behavior/warden/SonicBoom.java index c7ce058dda0dcb58197faea4f1799ebc580829c0..4f4c09cd7b75de38c0a3580386494e7e05f0acee 100644 --- a/src/main/java/net/minecraft/world/entity/ai/behavior/warden/SonicBoom.java +++ b/src/main/java/net/minecraft/world/entity/ai/behavior/warden/SonicBoom.java @@ -81,7 +81,7 @@ public class SonicBoom extends Behavior { target.hurt(world.damageSources().sonicBoom(entity), 10.0F); double d = 0.5 * (1.0 - target.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE)); double e = 2.5 * (1.0 - target.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE)); - target.push(vec33.x() * e, vec33.y() * d, vec33.z() * e); + target.push(vec33.x() * e, vec33.y() * d, vec33.z() * e, entity); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent }); } } diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java index 9ab60fb1b7f9c8a342d9116e99f7f0a1e463a626..0d84f1fb53384a827d7418c322a32e3286f4081a 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java @@ -459,7 +459,7 @@ public class EnderDragon extends Mob implements Enemy { double d3 = entity.getZ() - d1; double d4 = Math.max(d2 * d2 + d3 * d3, 0.1D); - entity.push(d2 / d4 * 4.0D, 0.20000000298023224D, d3 / d4 * 4.0D); + entity.push(d2 / d4 * 4.0D, 0.20000000298023224D, d3 / d4 * 4.0D, this); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent if (!this.phaseManager.getCurrentPhase().isSitting() && ((LivingEntity) entity).getLastHurtByMobTimestamp() < entity.tickCount - 2) { entity.hurt(this.damageSources().mobAttack(this), 5.0F); this.doEnchantDamageEffects(this, entity); diff --git a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java index b3d05578f38af41f242f6634864ce1d2ecac14f8..aaa579ba04445aa350a439610d460a2415320cfc 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java +++ b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java @@ -250,7 +250,7 @@ public abstract class HangingEntity extends Entity { } @Override - public void push(double deltaX, double deltaY, double deltaZ) { + public void push(double deltaX, double deltaY, double deltaZ, @org.jetbrains.annotations.Nullable Entity pushingEntity) { // Paper - add push source entity param if (false && !this.level().isClientSide && !this.isRemoved() && deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ > 0.0D) { // CraftBukkit - not needed this.kill(); this.dropItem((Entity) null); diff --git a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java index 78a3c87b74218a0d5792801c07e3a263c15fcd5b..f90878e0449f39f66ae3a7036a65c374b36b7dbc 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java +++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java @@ -159,9 +159,9 @@ public class ItemFrame extends HangingEntity { } @Override - public void push(double deltaX, double deltaY, double deltaZ) { + public void push(double deltaX, double deltaY, double deltaZ, @org.jetbrains.annotations.Nullable Entity pushingEntity) { // Paper - add push source entity param if (!this.fixed) { - super.push(deltaX, deltaY, deltaZ); + super.push(deltaX, deltaY, deltaZ, pushingEntity); // Paper - add push source entity param } } diff --git a/src/main/java/net/minecraft/world/entity/monster/Ravager.java b/src/main/java/net/minecraft/world/entity/monster/Ravager.java index 041f1650b853138e4286fe83a08d79d276054ce7..aba20a4352d8983b01ab5d329187588f68d3e405 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Ravager.java +++ b/src/main/java/net/minecraft/world/entity/monster/Ravager.java @@ -265,7 +265,7 @@ public class Ravager extends Raider { double d1 = entity.getZ() - this.getZ(); double d2 = Math.max(d0 * d0 + d1 * d1, 0.001D); - entity.push(d0 / d2 * 4.0D, 0.2D, d1 / d2 * 4.0D); + entity.push(d0 / d2 * 4.0D, 0.2D, d1 / d2 * 4.0D, this); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent } @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/HoglinBase.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/HoglinBase.java index 38c27b4aa37e8b046e3eccdde3f527eb555da6f8..05dee42941a842bf4bba9480a2c04a142541ac29 100644 --- a/src/main/java/net/minecraft/world/entity/monster/hoglin/HoglinBase.java +++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/HoglinBase.java @@ -40,7 +40,7 @@ public interface HoglinBase { double j = f * (double)(attacker.level().random.nextFloat() * 0.5F + 0.2F); Vec3 vec3 = new Vec3(g, 0.0, h).normalize().scale(j).yRot(i); double k = f * (double)attacker.level().random.nextFloat() * 0.5; - target.push(vec3.x, k, vec3.z); + target.push(vec3.x, k, vec3.z, attacker); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent target.hurtMarked = true; } } diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java index 0bff92eeade590852b9b37105a18df35f587559b..c934c7614281f77376858909c86d9a1a73c8e174 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java @@ -1279,7 +1279,7 @@ public abstract class Player extends LivingEntity { if (target instanceof LivingEntity) { ((LivingEntity) target).knockback((double) ((float) i * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this, EntityKnockbackEvent.KnockbackCause.ENTITY_ATTACK); // CraftBukkit } else { - target.push((double) (-Mth.sin(this.getYRot() * 0.017453292F) * (float) i * 0.5F), 0.1D, (double) (Mth.cos(this.getYRot() * 0.017453292F) * (float) i * 0.5F)); + target.push((double) (-Mth.sin(this.getYRot() * 0.017453292F) * (float) i * 0.5F), 0.1D, (double) (Mth.cos(this.getYRot() * 0.017453292F) * (float) i * 0.5F), this); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent } this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java index c210ae3795b1bbaefbe84a6f62b9d3dd75d642a4..f1d7f202b99b8ae4c16d10956d68d74efae8445b 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java @@ -410,7 +410,7 @@ public abstract class AbstractArrow extends Projectile { Vec3 vec3d = this.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D).normalize().scale((double) this.knockback * 0.6D * d0); if (vec3d.lengthSqr() > 0.0D) { - entityliving.push(vec3d.x, 0.1D, vec3d.z); + entityliving.push(vec3d.x, 0.1D, vec3d.z, this); // Paper } } diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java index 00cfa26783ce0772c75166266ead258a415097bc..ade10a9fd93f4c0f04cd56ce5e1da06af4a05060 100644 --- a/src/main/java/net/minecraft/world/level/Explosion.java +++ b/src/main/java/net/minecraft/world/level/Explosion.java @@ -298,7 +298,17 @@ public class Explosion { Vec3 result = entity.getDeltaMovement().add(vec3d1); org.bukkit.event.entity.EntityKnockbackEvent event = CraftEventFactory.callEntityKnockbackEvent((org.bukkit.craftbukkit.entity.CraftLivingEntity) entity.getBukkitEntity(), this.source, org.bukkit.event.entity.EntityKnockbackEvent.KnockbackCause.EXPLOSION, d13, vec3d1, result.x, result.y, result.z); - vec3d1 = (event.isCancelled()) ? Vec3.ZERO : new Vec3(event.getFinalKnockback().getX(), event.getFinalKnockback().getY(), event.getFinalKnockback().getZ()); + // Paper start - call EntityKnockbackByEntityEvent for explosions + vec3d1 = (event.isCancelled()) ? Vec3.ZERO : new Vec3(event.getFinalKnockback().getX(), event.getFinalKnockback().getY(), event.getFinalKnockback().getZ()).subtract(entity.getDeltaMovement()); // changes on this line fix a bug where vec3d1 wasn't reassigned with the "change", but instead the final deltaMovement + if (this.damageSource.getEntity() != null || this.source != null) { + final org.bukkit.entity.Entity hitBy = this.damageSource.getEntity() != null ? this.damageSource.getEntity().getBukkitEntity() : this.source.getBukkitEntity(); + com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent paperEvent = new com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent(((LivingEntity) entity).getBukkitLivingEntity(), hitBy, (float) event.getForce(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(vec3d1)); + if (!paperEvent.callEvent()) { + continue; + } + vec3d1 = org.bukkit.craftbukkit.util.CraftVector.toNMS(paperEvent.getAcceleration()); + } + // Paper end - call EntityKnockbackByEntityEvent for explosions } // CraftBukkit end entity.setDeltaMovement(entity.getDeltaMovement().add(vec3d1));