Breakpoint before projectile mess

This commit is contained in:
Bjarne Koll 2024-10-23 11:04:00 +02:00
parent 9d63c814c2
commit dc5af4848a
No known key found for this signature in database
GPG key ID: 27F6CCCF55D2EE62
12 changed files with 178 additions and 207 deletions

View file

@ -0,0 +1,44 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Mon, 18 Jun 2018 01:12:53 -0400
Subject: [PATCH] PlayerReadyArrowEvent
Called when a player is firing a bow and the server is choosing an arrow to use.
Plugins can skip selection of certain arrows and control which is used.
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 605f043bb132b21ff263ba7ab31a0f468a912d13..df0cfd316d24e285f927c713ab1f9a912857928c 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -2185,18 +2185,29 @@ public abstract class Player extends LivingEntity {
return ImmutableList.of(Pose.STANDING, Pose.CROUCHING, Pose.SWIMMING);
}
+ // Paper start - PlayerReadyArrowEvent
+ protected boolean tryReadyArrow(ItemStack bow, ItemStack itemstack) {
+ return !(this instanceof ServerPlayer) ||
+ new com.destroystokyo.paper.event.player.PlayerReadyArrowEvent(
+ ((ServerPlayer) this).getBukkitEntity(),
+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(bow),
+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)
+ ).callEvent();
+ }
+ // Paper end - PlayerReadyArrowEvent
+
@Override
public ItemStack getProjectile(ItemStack stack) {
if (!(stack.getItem() instanceof ProjectileWeaponItem)) {
return ItemStack.EMPTY;
} else {
- Predicate<ItemStack> predicate = ((ProjectileWeaponItem) stack.getItem()).getSupportedHeldProjectiles();
+ Predicate<ItemStack> predicate = ((ProjectileWeaponItem) stack.getItem()).getSupportedHeldProjectiles().and(item -> tryReadyArrow(stack, item)); // Paper - PlayerReadyArrowEvent
ItemStack itemstack1 = ProjectileWeaponItem.getHeldProjectile(this, predicate);
if (!itemstack1.isEmpty()) {
return itemstack1;
} else {
- predicate = ((ProjectileWeaponItem) stack.getItem()).getAllSupportedProjectiles();
+ predicate = ((ProjectileWeaponItem) stack.getItem()).getAllSupportedProjectiles().and(item -> tryReadyArrow(stack, item)); // Paper - PlayerReadyArrowEvent
for (int i = 0; i < this.inventory.getContainerSize(); ++i) {
ItemStack itemstack2 = this.inventory.getItem(i);

View file

@ -0,0 +1,319 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Brokkonaut <hannos17@gmx.de>
Date: Mon, 18 Jun 2018 15:46:23 +0200
Subject: [PATCH] Add entity knockback events
- EntityKnockbackEvent
- EntityPushedByEntityAttackEvent
- EntityKnockbackByEntityEvent
Co-authored-by: aerulion <aerulion@gmail.com>
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 087f030985180b91a809fb45244e23106da62e34..011006bc2e88a9fec98796f939c07d884b92126b 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -2050,7 +2050,21 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
public void push(double deltaX, double deltaY, double deltaZ) {
- this.setDeltaMovement(this.getDeltaMovement().add(deltaX, deltaY, deltaZ));
+ // 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(this.getBukkitEntity(), io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.PUSH, pushingEntity.getBukkitEntity(), delta);
+ if (!event.callEvent()) {
+ return;
+ }
+ delta = event.getKnockback();
+ }
+ this.setDeltaMovement(this.getDeltaMovement().add(delta.getX(), delta.getY(), delta.getZ()));
+ // Paper end - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent
this.hasImpulse = true;
}
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 0a4d2abc5b70c5e4e93dc06fe112e2398d9916e7..c9d7589a18e9cee204f4e52368a60aa421c1e150 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -1565,7 +1565,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
d1 = source.getSourcePosition().z() - this.getZ();
}
- this.knockback(0.4000000059604645D, d0, d1, entity1, entity1 == null ? EntityKnockbackEvent.KnockbackCause.DAMAGE : EntityKnockbackEvent.KnockbackCause.ENTITY_ATTACK); // CraftBukkit
+ this.knockback(0.4000000059604645D, d0, d1, entity1, entity1 == null ? io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.DAMAGE : io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK); // CraftBukkit // Paper - knockback events
if (!flag) {
this.indicateDamage(d0, d1);
}
@@ -1622,7 +1622,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, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.SHIELD_BLOCK); // CraftBukkit // Paper - fix attacker & knockback events
}
private boolean checkTotemDeathProtection(DamageSource source) {
@@ -1908,10 +1908,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
public void knockback(double strength, double x, double z) {
// CraftBukkit start - EntityKnockbackEvent
- this.knockback(strength, x, z, null, EntityKnockbackEvent.KnockbackCause.UNKNOWN);
+ this.knockback(strength, x, z, null, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.UNKNOWN); // Paper - knockback events
}
- 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, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause cause) { // Paper - knockback events
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
@@ -1924,13 +1924,17 @@ public abstract class LivingEntity extends Entity implements Attackable {
Vec3 vec3d1 = (new Vec3(d1, 0.0D, d2)).normalize().scale(d0);
- EntityKnockbackEvent event = CraftEventFactory.callEntityKnockbackEvent((org.bukkit.craftbukkit.entity.CraftLivingEntity) this.getBukkitEntity(), attacker, cause, d0, vec3d1, vec3d.x / 2.0D - vec3d1.x, this.onGround() ? Math.min(0.4D, vec3d.y / 2.0D + d0) : vec3d.y, vec3d.z / 2.0D - vec3d1.z);
+ // Paper start - knockback events
+ Vec3 finalVelocity = new Vec3(vec3d.x / 2.0D - vec3d1.x, this.onGround() ? Math.min(0.4D, vec3d.y / 2.0D + d0) : vec3d.y, vec3d.z / 2.0D - vec3d1.z);
+ Vec3 diff = finalVelocity.subtract(vec3d);
+ io.papermc.paper.event.entity.EntityKnockbackEvent event = CraftEventFactory.callEntityKnockbackEvent((org.bukkit.craftbukkit.entity.CraftLivingEntity) this.getBukkitEntity(), attacker, attacker, cause, d0, diff);
+ // Paper end - knockback events
if (event.isCancelled()) {
return;
}
this.hasImpulse = true;
- this.setDeltaMovement(event.getFinalKnockback().getX(), event.getFinalKnockback().getY(), event.getFinalKnockback().getZ());
+ this.setDeltaMovement(vec3d.add(event.getKnockback().getX(), event.getKnockback().getY(), event.getKnockback().getZ())); // Paper - knockback events
// CraftBukkit end
}
}
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
index 51381c32c8650400331a122a4b6c8d95c9d0632b..2b8bfccbf520f9a356f816522ac3a5caa51e44e1 100644
--- a/src/main/java/net/minecraft/world/entity/Mob.java
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
@@ -1685,7 +1685,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
if (f1 > 0.0F && target instanceof LivingEntity) {
entityliving = (LivingEntity) target;
- entityliving.knockback((double) (f1 * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this, org.bukkit.event.entity.EntityKnockbackEvent.KnockbackCause.ENTITY_ATTACK); // CraftBukkit
+ entityliving.knockback((double) (f1 * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK); // CraftBukkit // Paper - knockback events
this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D));
}
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 8bf5f18b5835ac97114dfea7dde3876c13433ab4..de81e34cf65318fa5e3034405719ff2a2b05458c 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
@@ -89,7 +89,7 @@ public class RamTarget extends Behavior<Goat> {
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, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.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 dbae113f3447f66e154b302ce0634b0fe446381c..d0fb32feb10f75444e3ed0a50c70ef6f12fb8e18 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
@@ -83,7 +83,7 @@ public class SonicBoom extends Behavior<Warden> {
if (target.hurtServer(world, 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 0012ab1f56180081d210c8836e2a59d543b950b8..ba1bb0f82634054e02c5f4bc062c1822a356e2a6 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
@@ -441,7 +441,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() && entityliving.getLastHurtByMobTimestamp() < entity.tickCount - 2) {
DamageSource damagesource = this.damageSources().mobAttack(this);
diff --git a/src/main/java/net/minecraft/world/entity/decoration/BlockAttachedEntity.java b/src/main/java/net/minecraft/world/entity/decoration/BlockAttachedEntity.java
index 19f9f4bceca158d9b35be2cdc4d7aa502f44a4b9..cd0a2270b58b6c0dba67270e7e1d1ba253eb7953 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/BlockAttachedEntity.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/BlockAttachedEntity.java
@@ -161,7 +161,7 @@ public abstract class BlockAttachedEntity extends Entity {
}
@Override
- public void push(double deltaX, double deltaY, double deltaZ) {
+ public void push(double deltaX, double deltaY, double deltaZ, @Nullable Entity pushingEntity) { // Paper - override correct overload
Level world = this.level();
if (world instanceof ServerLevel worldserver) {
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 6a90feef8eb2d65c925c44bc97305a51e3fb7cf0..7dfbcb2ed831cff5d002d79fb81514e6abf587a4 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
@@ -129,9 +129,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 c4397afa53a36ecf867525c4dcf2231a52d058dd..32973d9c7bf4c4105d7bd82d3723e0b70cd79644 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Ravager.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Ravager.java
@@ -292,7 +292,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 8b80f5c2749106f634d962fd0f381aa20e7ef335..a1e3375519fe676b14788d6729a7e71d089cca37 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
@@ -45,7 +45,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 df0cfd316d24e285f927c713ab1f9a912857928c..ba0ea4d6b67c9c52f170e0235e4b972aad3ce211 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -1271,9 +1271,9 @@ public abstract class Player extends LivingEntity {
if (target instanceof LivingEntity) {
LivingEntity entityliving1 = (LivingEntity) target;
- entityliving1.knockback((double) (f5 * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)));
+ entityliving1.knockback((double) (f5 * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.ENTITY_ATTACK); // Paper - knockback events
} else {
- target.push((double) (-Mth.sin(this.getYRot() * 0.017453292F) * f5 * 0.5F), 0.1D, (double) (Mth.cos(this.getYRot() * 0.017453292F) * f5 * 0.5F));
+ target.push((double) (-Mth.sin(this.getYRot() * 0.017453292F) * f5 * 0.5F), 0.1D, (double) (Mth.cos(this.getYRot() * 0.017453292F) * f5 * 0.5F), this); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent
}
this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D));
@@ -1301,7 +1301,7 @@ public abstract class Player extends LivingEntity {
continue;
}
// CraftBukkit end
- entityliving2.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)));
+ entityliving2.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.SWEEP_ATTACK); // CraftBukkit // Paper - knockback events
// entityliving2.hurt(damagesource, f7); // CraftBukkit - moved up
Level world = this.level();
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 a1b1c6385d3a1fbe38f5ae4471b8e4f6ef2c80b3..78053060dbff7f8a859f9fecb356491f497eed7e 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
@@ -553,7 +553,7 @@ public abstract class AbstractArrow extends Projectile {
Vec3 vec3d = this.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D).normalize().scale(d0 * 0.6D * d1);
if (vec3d.lengthSqr() > 0.0D) {
- target.push(vec3d.x, 0.1D, vec3d.z);
+ target.push(vec3d.x, 0.1D, vec3d.z, this); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent
}
}
diff --git a/src/main/java/net/minecraft/world/entity/projectile/windcharge/AbstractWindCharge.java b/src/main/java/net/minecraft/world/entity/projectile/windcharge/AbstractWindCharge.java
index 6541ab0d8da28785b19fa50d18d6a484ea38cef8..a325a223d06e155c01f664562db0edd0b180e356 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/windcharge/AbstractWindCharge.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/windcharge/AbstractWindCharge.java
@@ -101,7 +101,7 @@ public abstract class AbstractWindCharge extends AbstractHurtingProjectile imple
}
@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 EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent
public abstract void explode(Vec3 pos);
diff --git a/src/main/java/net/minecraft/world/level/ServerExplosion.java b/src/main/java/net/minecraft/world/level/ServerExplosion.java
index 3afacd201683f46fd75cd6f9a7f3d43a7050cf4a..9f37d7284c81d529551107e2836627977efabd65 100644
--- a/src/main/java/net/minecraft/world/level/ServerExplosion.java
+++ b/src/main/java/net/minecraft/world/level/ServerExplosion.java
@@ -258,13 +258,10 @@ public class ServerExplosion implements Explosion {
// CraftBukkit start - Call EntityKnockbackEvent
if (entity instanceof LivingEntity) {
- Vec3 result = entity.getDeltaMovement().add(vec3d);
- org.bukkit.event.entity.EntityKnockbackEvent event = CraftEventFactory.callEntityKnockbackEvent((org.bukkit.craftbukkit.entity.CraftLivingEntity) entity.getBukkitEntity(), this.source, org.bukkit.event.entity.EntityKnockbackEvent.KnockbackCause.EXPLOSION, d6, vec3d, result.x, result.y, result.z);
-
- // SPIGOT-7640: Need to subtract entity movement from the event result,
- // since the code below (the setDeltaMovement call as well as the hitPlayers map)
- // want the vector to be the relative velocity will the event provides the absolute velocity
- vec3d = (event.isCancelled()) ? Vec3.ZERO : new Vec3(event.getFinalKnockback().getX(), event.getFinalKnockback().getY(), event.getFinalKnockback().getZ()).subtract(entity.getDeltaMovement());
+ // Paper start - knockback events
+ io.papermc.paper.event.entity.EntityKnockbackEvent event = CraftEventFactory.callEntityKnockbackEvent((org.bukkit.craftbukkit.entity.CraftLivingEntity) entity.getBukkitEntity(), this.source, this.damageSource.getEntity() != null ? this.damageSource.getEntity() : this.source, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.EXPLOSION, d6, vec3d);
+ vec3d = event.isCancelled() ? Vec3.ZERO : org.bukkit.craftbukkit.util.CraftVector.toNMS(event.getKnockback());
+ // Paper end - knockback events
}
// CraftBukkit end
entity.setDeltaMovement(entity.getDeltaMovement().add(vec3d));
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index f05a19f868be0d685c4fbf64e1dfbefda71131ac..60a16ac62a27a92b763bf90e72fab4ed01aeb592 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -1936,19 +1936,33 @@ public class CraftEventFactory {
return event;
}
- public static EntityKnockbackEvent callEntityKnockbackEvent(CraftLivingEntity entity, Entity attacker, EntityKnockbackEvent.KnockbackCause cause, double force, Vec3 raw, double x, double y, double z) {
- Vector bukkitRaw = new Vector(-raw.x, raw.y, -raw.z); // Due to how the knockback calculation works, we need to invert x and z.
+ // Paper start - replace knockback events
+ public static io.papermc.paper.event.entity.EntityKnockbackEvent callEntityKnockbackEvent(CraftLivingEntity entity, Entity pusher, Entity attacker, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause cause, double force, Vec3 knockback) {
+ Vector apiKnockback = CraftVector.toBukkit(knockback);
+
+ final Vector currentVelocity = entity.getVelocity();
+ final Vector legacyFinalKnockback = currentVelocity.clone().add(apiKnockback);
+ final org.bukkit.event.entity.EntityKnockbackEvent.KnockbackCause legacyCause = org.bukkit.event.entity.EntityKnockbackEvent.KnockbackCause.valueOf(cause.name());
+ EntityKnockbackEvent legacyEvent;
+ if (pusher != null) {
+ legacyEvent = new EntityKnockbackByEntityEvent(entity, pusher.getBukkitEntity(), legacyCause, force, apiKnockback, legacyFinalKnockback);
+ } else {
+ legacyEvent = new EntityKnockbackEvent(entity, legacyCause, force, apiKnockback, legacyFinalKnockback);
+ }
+ legacyEvent.callEvent();
- EntityKnockbackEvent event;
+ final io.papermc.paper.event.entity.EntityKnockbackEvent event;
+ apiKnockback = legacyEvent.getFinalKnockback().subtract(currentVelocity);
if (attacker != null) {
- event = new EntityKnockbackByEntityEvent(entity, attacker.getBukkitEntity(), cause, force, new Vector(-raw.x, raw.y, -raw.z), new Vector(x, y, z));
+ event = new com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent(entity, attacker.getBukkitEntity(), cause, (float) force, apiKnockback);
} else {
- event = new EntityKnockbackEvent(entity, cause, force, new Vector(-raw.x, raw.y, -raw.z), new Vector(x, y, z));
+ event = new io.papermc.paper.event.entity.EntityKnockbackEvent(entity, cause, apiKnockback);
}
-
- Bukkit.getPluginManager().callEvent(event);
+ event.setCancelled(legacyEvent.isCancelled());
+ event.callEvent();
return event;
}
+ // Paper end - replace knockback events
public static void callEntityRemoveEvent(Entity entity, EntityRemoveEvent.Cause cause) {
if (entity instanceof ServerPlayer) {

View file

@ -0,0 +1,87 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Wed, 20 Jun 2018 23:17:24 -0400
Subject: [PATCH] Expand Explosions API
Add Entity as a Source capability, and add more API choices, and on Location.
Co-authored-by: Esoteric Enderman <90862990+EsotericEnderman@users.noreply.github.com>
Co-authored-by: Bjarne Koll <lynxplay101@gmail.com>
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 252f1deea98a6eb83ac99adea3ea7a3c229c0f07..a4709b08ea90e15533a3e1b1d22d16e004556243 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1449,6 +1449,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
}
public ServerExplosion explode0(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.ExplosionInteraction world_a, ParticleOptions particleparam, ParticleOptions particleparam1, Holder<SoundEvent> holder) {
+ // Paper start - Allow explosions to damage source
+ return this.explode0(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, world_a, particleparam, particleparam1, holder, null);
+ }
+ public ServerExplosion explode0(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.ExplosionInteraction world_a, ParticleOptions particleparam, ParticleOptions particleparam1, Holder<SoundEvent> holder, java.util.function.Consumer<ServerExplosion> configurator) {
+ // Paper end - Allow explosions to damage source
// CraftBukkit end
Explosion.BlockInteraction explosion_effect;
@@ -1480,6 +1485,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
Explosion.BlockInteraction explosion_effect1 = explosion_effect;
Vec3 vec3d = new Vec3(d0, d1, d2);
ServerExplosion serverexplosion = new ServerExplosion(this, entity, damagesource, explosiondamagecalculator, vec3d, f, flag, explosion_effect1);
+ if (configurator != null) configurator.accept(serverexplosion);// Paper - Allow explosions to damage source
serverexplosion.explode();
// CraftBukkit start
diff --git a/src/main/java/net/minecraft/world/level/ServerExplosion.java b/src/main/java/net/minecraft/world/level/ServerExplosion.java
index 9f37d7284c81d529551107e2836627977efabd65..d1878f597c3d8119e9b248f4fe8af435ce8c9710 100644
--- a/src/main/java/net/minecraft/world/level/ServerExplosion.java
+++ b/src/main/java/net/minecraft/world/level/ServerExplosion.java
@@ -63,6 +63,7 @@ public class ServerExplosion implements Explosion {
public boolean wasCanceled = false;
public float yield;
// CraftBukkit end
+ public boolean excludeSourceFromDamage = true; // Paper - Allow explosions to damage source
public ServerExplosion(ServerLevel world, @Nullable Entity entity, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator behavior, Vec3 pos, float power, boolean createFire, Explosion.BlockInteraction destructionType) {
this.level = world;
@@ -185,7 +186,7 @@ public class ServerExplosion implements Explosion {
int l = Mth.floor(this.center.y + (double) f + 1.0D);
int i1 = Mth.floor(this.center.z - (double) f - 1.0D);
int j1 = Mth.floor(this.center.z + (double) f + 1.0D);
- List<Entity> list = this.level.getEntities(this.source, new AABB((double) i, (double) k, (double) i1, (double) j, (double) l, (double) j1), (com.google.common.base.Predicate<Entity>) entity -> entity.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities
+ List<Entity> list = this.level.getEntities(excludeSourceFromDamage ? this.source : null, new AABB((double) i, (double) k, (double) i1, (double) j, (double) l, (double) j1), (com.google.common.base.Predicate<Entity>) entity -> entity.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities, Allow explosions to damage source
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 4b2742c0841bd686ee637e1d6dc011e13b0df192..22543e032f9202d590ac3924b537bb43efba9c93 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -784,6 +784,11 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source) {
+ // Paper start - expand explosion API
+ return this.createExplosion(x, y, z, power, setFire, breakBlocks, source, null);
+ }
+ public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source, Consumer<net.minecraft.world.level.ServerExplosion> configurator) {
+ // Paper end - expand explosion API
net.minecraft.world.level.Level.ExplosionInteraction explosionType;
if (!breakBlocks) {
explosionType = net.minecraft.world.level.Level.ExplosionInteraction.NONE; // Don't break blocks
@@ -794,8 +799,14 @@ public class CraftWorld extends CraftRegionAccessor implements World {
}
net.minecraft.world.entity.Entity entity = (source == null) ? null : ((CraftEntity) source).getHandle();
- return !this.world.explode0(entity, Explosion.getDefaultDamageSource(this.world, entity), null, x, y, z, power, setFire, explosionType, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE).wasCanceled;
+ return !this.world.explode0(entity, Explosion.getDefaultDamageSource(this.world, entity), null, x, y, z, power, setFire, explosionType, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE, configurator).wasCanceled; // Paper - expand explosion API
}
+ // Paper start
+ @Override
+ public boolean createExplosion(Entity source, Location loc, float power, boolean setFire, boolean breakBlocks, boolean excludeSourceFromDamage) {
+ return this.createExplosion(loc.x(), loc.getY(), loc.getZ(), power, setFire, breakBlocks, source, e -> e.excludeSourceFromDamage = excludeSourceFromDamage);
+ }
+ // Paper end
@Override
public boolean createExplosion(Location loc, float power) {

View file

@ -0,0 +1,72 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Fri, 29 Jun 2018 00:21:28 -0400
Subject: [PATCH] LivingEntity Active Item API
API relating to items being actively used by a LivingEntity
such as a bow or eating food.
== AT ==
public net/minecraft/world/entity/LivingEntity completeUsingItem()V
public net/minecraft/server/level/ServerPlayer completeUsingItem()V
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index e5186fbd4030d7b39443090b711e855dcbc39426..2033354daafc739a8bd9ddf4a6128d3204d32094 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -884,4 +884,53 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
getHandle().setShieldBlockingDelay(delay);
}
// Paper end
+
+ // Paper start - active item API
+ @Override
+ public void startUsingItem(org.bukkit.inventory.EquipmentSlot hand) {
+ Preconditions.checkArgument(hand != null, "hand must not be null");
+ switch (hand) {
+ case HAND -> getHandle().startUsingItem(InteractionHand.MAIN_HAND);
+ case OFF_HAND -> getHandle().startUsingItem(InteractionHand.OFF_HAND);
+ default -> throw new IllegalArgumentException("hand may only be HAND or OFF_HAND");
+ }
+ }
+
+ @Override
+ public void completeUsingActiveItem() {
+ getHandle().completeUsingItem();
+ }
+
+ @Override
+ public ItemStack getActiveItem() {
+ return this.getHandle().getUseItem().asBukkitMirror();
+ }
+
+ @Override
+ public int getActiveItemRemainingTime() {
+ return this.getHandle().getUseItemRemainingTicks();
+ }
+
+ @Override
+ public void setActiveItemRemainingTime(final int ticks) {
+ Preconditions.checkArgument(ticks >= 0, "ticks must be >= 0");
+ Preconditions.checkArgument(ticks <= this.getHandle().getUseItem().getUseDuration(this.getHandle()), "ticks must be <= item use duration");
+ this.getHandle().useItemRemaining = ticks;
+ }
+
+ @Override
+ public int getActiveItemUsedTime() {
+ return this.getHandle().getTicksUsingItem();
+ }
+
+ @Override
+ public boolean hasActiveItem() {
+ return this.getHandle().isUsingItem();
+ }
+
+ @Override
+ public org.bukkit.inventory.EquipmentSlot getActiveItemHand() {
+ return org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(this.getHandle().getUsedItemHand());
+ }
+ // Paper end - active item API
}

View file

@ -0,0 +1,162 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Tue, 26 Jun 2018 22:00:49 -0400
Subject: [PATCH] RangedEntity API
Allows you to determine if an entity is capable of ranged attacks,
and to perform an attack.
diff --git a/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java b/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java
new file mode 100644
index 0000000000000000000000000000000000000000..d7a8eb1b8f24ed2741ae9dae62d3f6146f273e1d
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java
@@ -0,0 +1,20 @@
+package com.destroystokyo.paper.entity;
+
+import net.minecraft.world.entity.Mob;
+import net.minecraft.world.entity.monster.RangedAttackMob;
+import org.bukkit.craftbukkit.entity.CraftLivingEntity;
+import org.bukkit.entity.LivingEntity;
+
+public interface CraftRangedEntity<T extends Mob & RangedAttackMob> extends RangedEntity {
+ T getHandle();
+
+ @Override
+ default void rangedAttack(LivingEntity target, float charge) {
+ getHandle().performRangedAttack(((CraftLivingEntity) target).getHandle(), charge);
+ }
+
+ @Override
+ default void setChargingAttack(boolean raiseHands) {
+ getHandle().setAggressive(raiseHands);
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractSkeleton.java
index db6ad6eea8fa6f2755bbb0e1325df8bda98e708a..5ff566186431440c25a26900aba14e4adb642031 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractSkeleton.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractSkeleton.java
@@ -4,7 +4,7 @@ import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.AbstractSkeleton;
import org.bukkit.entity.Skeleton;
-public abstract class CraftAbstractSkeleton extends CraftMonster implements AbstractSkeleton {
+public abstract class CraftAbstractSkeleton extends CraftMonster implements AbstractSkeleton, com.destroystokyo.paper.entity.CraftRangedEntity<net.minecraft.world.entity.monster.AbstractSkeleton> { // Paper
public CraftAbstractSkeleton(CraftServer server, net.minecraft.world.entity.monster.AbstractSkeleton entity) {
super(server, entity);
@@ -14,4 +14,10 @@ public abstract class CraftAbstractSkeleton extends CraftMonster implements Abst
public void setSkeletonType(Skeleton.SkeletonType type) {
throw new UnsupportedOperationException("Not supported.");
}
+ // Paper start
+ @Override
+ public net.minecraft.world.entity.monster.AbstractSkeleton getHandle() {
+ return (net.minecraft.world.entity.monster.AbstractSkeleton) super.getHandle();
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java
index c0e59845a7350b0fdb43eaff8a9ec81793e464d5..51fc4acae9f20e8891069704e4a27f212b870766 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java
@@ -3,7 +3,7 @@ package org.bukkit.craftbukkit.entity;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.Drowned;
-public class CraftDrowned extends CraftZombie implements Drowned {
+public class CraftDrowned extends CraftZombie implements Drowned, com.destroystokyo.paper.entity.CraftRangedEntity<net.minecraft.world.entity.monster.Drowned> { // Paper
public CraftDrowned(CraftServer server, net.minecraft.world.entity.monster.Drowned entity) {
super(server, entity);
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java
index 995c77ee53347328bfd0ad66fcc1b39589967476..5b2af80e584977683cd39e6f440e65a76e929be9 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java
@@ -3,7 +3,7 @@ package org.bukkit.craftbukkit.entity;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.Illusioner;
-public class CraftIllusioner extends CraftSpellcaster implements Illusioner {
+public class CraftIllusioner extends CraftSpellcaster implements Illusioner, com.destroystokyo.paper.entity.CraftRangedEntity<net.minecraft.world.entity.monster.Illusioner> { // Paper
public CraftIllusioner(CraftServer server, net.minecraft.world.entity.monster.Illusioner entity) {
super(server, entity);
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java
index 189b5ac97f3354b8dea082c2acef242f8ff2f002..bf297388c75521266c93580a9caafe6bad70ab45 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java
@@ -8,7 +8,7 @@ import org.bukkit.entity.Llama;
import org.bukkit.entity.Llama.Color;
import org.bukkit.inventory.LlamaInventory;
-public class CraftLlama extends CraftChestedHorse implements Llama {
+public class CraftLlama extends CraftChestedHorse implements Llama, com.destroystokyo.paper.entity.CraftRangedEntity<net.minecraft.world.entity.animal.horse.Llama> { // Paper
public CraftLlama(CraftServer server, net.minecraft.world.entity.animal.horse.Llama entity) {
super(server, entity);
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java
index 9426395c17b6d2270f2227a8eaaee93d8f07cb2d..f5ecb8c1dc92e5a4b123effd2859123b17a586d3 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java
@@ -12,7 +12,7 @@ import org.bukkit.craftbukkit.inventory.CraftItemType;
import org.bukkit.entity.Piglin;
import org.bukkit.inventory.Inventory;
-public class CraftPiglin extends CraftPiglinAbstract implements Piglin {
+public class CraftPiglin extends CraftPiglinAbstract implements Piglin, com.destroystokyo.paper.entity.CraftRangedEntity<net.minecraft.world.entity.monster.piglin.Piglin> { // Paper
public CraftPiglin(CraftServer server, net.minecraft.world.entity.monster.piglin.Piglin entity) {
super(server, entity);
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java
index d82cea48d9baeaba4dfa32540dcc9ca73651608b..2638c341bc02f201f7ab17fdebcdbdf3a7ec05bf 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java
@@ -5,7 +5,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventory;
import org.bukkit.entity.Pillager;
import org.bukkit.inventory.Inventory;
-public class CraftPillager extends CraftIllager implements Pillager {
+public class CraftPillager extends CraftIllager implements Pillager, com.destroystokyo.paper.entity.CraftRangedEntity<net.minecraft.world.entity.monster.Pillager> { // Paper
public CraftPillager(CraftServer server, net.minecraft.world.entity.monster.Pillager entity) {
super(server, entity);
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java
index 1f373896cc08cf78bc5f5b188b323c1fff9fd9f1..1e9807b8f468742d208f817e22d7625106fc1b58 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java
@@ -4,7 +4,7 @@ import net.minecraft.world.entity.animal.SnowGolem;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.Snowman;
-public class CraftSnowman extends CraftGolem implements Snowman {
+public class CraftSnowman extends CraftGolem implements Snowman, com.destroystokyo.paper.entity.CraftRangedEntity<SnowGolem> { // Paper
public CraftSnowman(CraftServer server, SnowGolem entity) {
super(server, entity);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java
index bf6acf783d6f2b02f528a4247ad11f3cd181c004..524b5ba5995affc09eedf9a85d22e8b0b4efc156 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java
@@ -3,7 +3,7 @@ package org.bukkit.craftbukkit.entity;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.Witch;
-public class CraftWitch extends CraftRaider implements Witch {
+public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity<net.minecraft.world.entity.monster.Witch> { // Paper
public CraftWitch(CraftServer server, net.minecraft.world.entity.monster.Witch entity) {
super(server, entity);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java
index 59bdb36ca10fa56a83a44b53e482480714cc7bd9..1113533d281ed159bb735040fb1f913482debf3a 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java
@@ -9,7 +9,7 @@ import org.bukkit.craftbukkit.boss.CraftBossBar;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Wither;
-public class CraftWither extends CraftMonster implements Wither {
+public class CraftWither extends CraftMonster implements Wither, com.destroystokyo.paper.entity.CraftRangedEntity<WitherBoss> { // Paper
private BossBar bossBar;

View file

@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@GMail.com>
Date: Fri, 22 Jun 2018 10:38:31 -0500
Subject: [PATCH] Add config to disable ender dragon legacy check
diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
index 3fa3dae36bcf66dfdc8a279d37fb60a624c1ae96..a16229f5eaa9e8320751e4fd1faf016f796d3414 100644
--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
@@ -117,6 +117,12 @@ public class EndDragonFight {
if (data.isRespawning) {
this.respawnStage = DragonRespawnAnimation.START;
}
+ // Paper start - Add config to disable ender dragon legacy check
+ if (data == EndDragonFight.Data.DEFAULT && !world.paperConfig().entities.spawning.scanForLegacyEnderDragon) {
+ this.needsStateScanning = false;
+ this.dragonKilled = true;
+ }
+ // Paper end - Add config to disable ender dragon legacy check
this.portalLocation = (BlockPos) data.exitPortalLocation.orElse(null); // CraftBukkit - decompile error
this.gateways.addAll((Collection) data.gateways.orElseGet(() -> {

View file

@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Brokkonaut <hannos17@gmx.de>
Date: Tue, 3 Jul 2018 16:08:14 +0200
Subject: [PATCH] Implement World.getEntity(UUID) API
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 22543e032f9202d590ac3924b537bb43efba9c93..1982385aa0e4984544d2aef88f5cafd5c0d5a49a 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1137,6 +1137,15 @@ public class CraftWorld extends CraftRegionAccessor implements World {
return list;
}
+ // Paper start - getEntity by UUID API
+ @Override
+ public Entity getEntity(UUID uuid) {
+ Preconditions.checkArgument(uuid != null, "UUID cannot be null");
+ net.minecraft.world.entity.Entity entity = world.getEntity(uuid);
+ return entity == null ? null : entity.getBukkitEntity();
+ }
+ // Paper end
+
@Override
public void save() {
org.spigotmc.AsyncCatcher.catchOp("world save"); // Spigot

View file

@ -0,0 +1,212 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Tue, 3 Jul 2018 21:56:23 -0400
Subject: [PATCH] InventoryCloseEvent Reason API
Allows you to determine why an inventory was closed, enabling plugin developers
to "confirm" things based on if it was player triggered close or not.
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index a4709b08ea90e15533a3e1b1d22d16e004556243..438c936fceede5b21435e1f37f2372072a9d4571 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1234,7 +1234,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
for (net.minecraft.world.level.block.entity.BlockEntity tileentity : chunk.getBlockEntities().values()) {
if (tileentity instanceof net.minecraft.world.Container) {
for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((net.minecraft.world.Container) tileentity).getViewers())) {
- h.closeInventory();
+ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - Inventory close reason
}
}
}
@@ -2279,7 +2279,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// Spigot Start
if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message
for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((org.bukkit.inventory.InventoryHolder) entity.getBukkitEntity()).getInventory().getViewers())) {
- h.closeInventory();
+ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - Inventory close reason
}
}
// Spigot End
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 98aeafcc51e23a7534c8d57e4db0eb58abb3f30b..29b836a75b835f0d5233db419fc5ca8dde885fdb 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -933,7 +933,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
}
// Paper end - Configurable container update tick rate
if (!this.level().isClientSide && !this.containerMenu.stillValid(this)) {
- this.closeContainer();
+ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - Inventory close reason
this.containerMenu = this.inventoryMenu;
}
@@ -1185,7 +1185,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
// SPIGOT-943 - only call if they have an inventory open
if (this.containerMenu != this.inventoryMenu) {
- this.closeContainer();
+ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DEATH); // Paper - Inventory close reason
}
net.kyori.adventure.text.Component deathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure
@@ -1859,7 +1859,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
}
// CraftBukkit end
if (this.containerMenu != this.inventoryMenu) {
- this.closeContainer();
+ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper - Inventory close reason
}
// this.nextContainerCounter(); // CraftBukkit - moved up
@@ -1889,7 +1889,13 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
@Override
public void closeContainer() {
- CraftEventFactory.handleInventoryCloseEvent(this); // CraftBukkit
+ // Paper start - Inventory close reason
+ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN);
+ }
+ @Override
+ public void closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) {
+ CraftEventFactory.handleInventoryCloseEvent(this, reason); // CraftBukkit
+ // Paper end - Inventory close reason
this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId));
this.doCloseContainer();
}
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 0cce81cb61665b2dbd445fa9a0fcfeb42ce3be2c..bcceb9d18524ddcf7cdf2ab6dcb95a67f1155414 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2633,10 +2633,15 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
@Override
public void handleContainerClose(ServerboundContainerClosePacket packet) {
+ // Paper start - Inventory close reason
+ this.handleContainerClose(packet, org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLAYER);
+ }
+ public void handleContainerClose(ServerboundContainerClosePacket packet, org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) {
+ // Paper end - Inventory close reason
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
if (this.player.isImmobile()) return; // CraftBukkit
- CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit
+ CraftEventFactory.handleInventoryCloseEvent(this.player, reason); // CraftBukkit // Paper
this.player.doCloseContainer();
}
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 95b9341859ba6da6945faebf8430a044cc1ee828..038c5f16e60f0e182774e6df5b6c5359153a4b07 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -469,7 +469,7 @@ public abstract class PlayerList {
// CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it
// See SPIGOT-5799, SPIGOT-6145
if (entityplayer.containerMenu != entityplayer.inventoryMenu) {
- entityplayer.closeContainer();
+ entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper - Inventory close reason
}
PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? entityplayer.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(entityplayer.getDisplayName()))); // Paper - Adventure
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 ba0ea4d6b67c9c52f170e0235e4b972aad3ce211..7eb4563299e7c54ec4df53c966f6d1a86fb2ec4e 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -279,7 +279,7 @@ public abstract class Player extends LivingEntity {
this.updateIsUnderwater();
super.tick();
if (!this.level().isClientSide && this.containerMenu != null && !this.containerMenu.stillValid(this)) {
- this.closeContainer();
+ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - Inventory close reason
this.containerMenu = this.inventoryMenu;
}
@@ -531,6 +531,13 @@ public abstract class Player extends LivingEntity {
}
+ // Paper start - Inventory close reason; unused code, but to keep signatures aligned
+ public void closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) {
+ closeContainer();
+ this.containerMenu = this.inventoryMenu;
+ }
+ // Paper end - Inventory close reason
+
public void closeContainer() {
this.containerMenu = this.inventoryMenu;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
index 6d4e0a90c70f7a66450cbb18ebec1d7bf9200af2..5ff159be1a6dfb4b1a5b9aa1e435d294f205215e 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
@@ -387,7 +387,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
if (((ServerPlayer) this.getHandle()).connection == null) return;
if (this.getHandle().containerMenu != this.getHandle().inventoryMenu) {
// fire INVENTORY_CLOSE if one already open
- ((ServerPlayer) this.getHandle()).connection.handleContainerClose(new ServerboundContainerClosePacket(this.getHandle().containerMenu.containerId));
+ ((ServerPlayer) this.getHandle()).connection.handleContainerClose(new ServerboundContainerClosePacket(this.getHandle().containerMenu.containerId), org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper - Inventory close reason
}
ServerPlayer player = (ServerPlayer) this.getHandle();
AbstractContainerMenu container;
@@ -457,8 +457,14 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
@Override
public void closeInventory() {
- this.getHandle().closeContainer();
+ // Paper start - Inventory close reason
+ this.getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLUGIN);
}
+ @Override
+ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) {
+ getHandle().closeContainer(reason);
+ }
+ // Paper end - Inventory close reason
@Override
public boolean isBlocking() {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index e7477aaad01c26e56e3d5e90bd403311deae8d59..ad75996926b7e054f1053d07fb978ac745f22ce6 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1286,7 +1286,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
// Close any foreign inventory
if (this.getHandle().containerMenu != this.getHandle().inventoryMenu) {
- this.getHandle().closeContainer();
+ this.getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.TELEPORT); // Paper - Inventory close reason
}
// Check if the fromWorld and toWorld are the same.
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 60a16ac62a27a92b763bf90e72fab4ed01aeb592..41c6a7260317ed575a3320ac36b0f2be22c120aa 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -1281,7 +1281,7 @@ public class CraftEventFactory {
public static AbstractContainerMenu callInventoryOpenEvent(ServerPlayer player, AbstractContainerMenu container, boolean cancelled) {
if (player.containerMenu != player.inventoryMenu) { // fire INVENTORY_CLOSE if one already open
- player.connection.handleContainerClose(new ServerboundContainerClosePacket(player.containerMenu.containerId));
+ player.connection.handleContainerClose(new ServerboundContainerClosePacket(player.containerMenu.containerId), InventoryCloseEvent.Reason.OPEN_NEW); // Paper - Inventory close reason
}
CraftServer server = player.level().getCraftServer();
@@ -1477,8 +1477,18 @@ public class CraftEventFactory {
return event;
}
+ // Paper start
+ /**
+ * Incase plugins hooked into this or Spigot adds a new inventory close event. Prefer to pass a reason
+ * @param human
+ */
+ @Deprecated
public static void handleInventoryCloseEvent(net.minecraft.world.entity.player.Player human) {
- InventoryCloseEvent event = new InventoryCloseEvent(human.containerMenu.getBukkitView());
+ handleInventoryCloseEvent(human, org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN);
+ }
+ public static void handleInventoryCloseEvent(net.minecraft.world.entity.player.Player human, org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) {
+ // Paper end
+ InventoryCloseEvent event = new InventoryCloseEvent(human.containerMenu.getBukkitView(), reason); // Paper
human.level().getCraftServer().getPluginManager().callEvent(event);
human.containerMenu.transferTo(human.inventoryMenu, human.getBukkitEntity());
}

View file

@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Wed, 4 Jul 2018 15:30:22 -0400
Subject: [PATCH] Vex#get/setSummoner API
Get's the NPC that summoned this Vex and
Allow setting the vex's summoner
Co-authored-by: BillyGalbreath <Blake.Galbreath@GMail.com>
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java
index f816e30e36042438fa5ead72ce25e7b5bce232bb..1cfbe9c476f4a254edf3edf4b70696bbaba78558 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java
@@ -18,6 +18,19 @@ public class CraftVex extends CraftMonster implements Vex {
return (net.minecraft.world.entity.monster.Vex) super.getHandle();
}
+ // Paper start
+ @Override
+ public org.bukkit.entity.Mob getSummoner() {
+ net.minecraft.world.entity.Mob owner = getHandle().getOwner();
+ return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null;
+ }
+
+ @Override
+ public void setSummoner(org.bukkit.entity.Mob summoner) {
+ getHandle().setOwner(summoner == null ? null : ((CraftMob) summoner).getHandle());
+ }
+ // Paper end
+
@Override
public String toString() {
return "CraftVex";

View file

@ -0,0 +1,20 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Thu, 19 Jul 2018 01:13:28 -0400
Subject: [PATCH] add more information to Entity.toString()
UUID, ticks lived, valid, dead
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 011006bc2e88a9fec98796f939c07d884b92126b..79a3d586ddf404c449b7c0aa1996e9b9897b2383 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -3406,7 +3406,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
public String toString() {
String s = this.level() == null ? "~NULL~" : this.level().toString();
- return this.removalReason != null ? String.format(Locale.ROOT, "%s['%s'/%d, l='%s', x=%.2f, y=%.2f, z=%.2f, removed=%s]", this.getClass().getSimpleName(), this.getName().getString(), this.id, s, this.getX(), this.getY(), this.getZ(), this.removalReason) : String.format(Locale.ROOT, "%s['%s'/%d, l='%s', x=%.2f, y=%.2f, z=%.2f]", this.getClass().getSimpleName(), this.getName().getString(), this.id, s, this.getX(), this.getY(), this.getZ());
+ return this.removalReason != null ? String.format(Locale.ROOT, "%s['%s'/%d, uuid='%s', l='%s', x=%.2f, y=%.2f, z=%.2f, cpos=%s, tl=%d, v=%b, removed=%s]", this.getClass().getSimpleName(), this.getName().getString(), this.id, this.uuid, s, this.getX(), this.getY(), this.getZ(), this.chunkPosition(), this.tickCount, this.valid, this.removalReason) : String.format(Locale.ROOT, "%s['%s'/%d, uuid='%s', l='%s', x=%.2f, y=%.2f, z=%.2f, cpos=%s, tl=%d, v=%b]", this.getClass().getSimpleName(), this.getName().getString(), this.id, this.uuid, s, this.getX(), this.getY(), this.getZ(), this.chunkPosition(), this.tickCount, this.valid); // Paper - add more info
}
public final boolean isInvulnerableToBase(DamageSource damageSource) {

View file

@ -0,0 +1,53 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@GMail.com>
Date: Sat, 21 Jul 2018 01:51:27 -0500
Subject: [PATCH] EnderDragon Events
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java
index fe625faf0120b72e892542e4bb5ecea4b73becc7..55b66d3e0d7394a017fb1cdd87e45d7f4eb84976 100644
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java
@@ -89,7 +89,13 @@ public class DragonSittingFlamingPhase extends AbstractDragonSittingPhase {
this.flame.setDuration(200);
this.flame.setParticle(ParticleTypes.DRAGON_BREATH);
this.flame.addEffect(new MobEffectInstance(MobEffects.HARM));
+ if (new com.destroystokyo.paper.event.entity.EnderDragonFlameEvent((org.bukkit.entity.EnderDragon) this.dragon.getBukkitEntity(), (org.bukkit.entity.AreaEffectCloud) this.flame.getBukkitEntity()).callEvent()) { // Paper - EnderDragon Events
world.addFreshEntity(this.flame);
+ // Paper start - EnderDragon Events
+ } else {
+ this.end();
+ }
+ // Paper end - EnderDragon Events
}
}
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java
index 68b7bfc139e928192005df8339be371ed8b2a9be..2db75673e525708d04bda9f6c9af80e7f8d361e6 100644
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java
@@ -80,7 +80,9 @@ public class DragonStrafePlayerPhase extends AbstractDragonPhaseInstance {
DragonFireball dragonFireball = new DragonFireball(world, this.dragon, vec34.normalize());
dragonFireball.moveTo(o, p, q, 0.0F, 0.0F);
+ if (new com.destroystokyo.paper.event.entity.EnderDragonShootFireballEvent((org.bukkit.entity.EnderDragon) dragon.getBukkitEntity(), (org.bukkit.entity.DragonFireball) dragonFireball.getBukkitEntity()).callEvent()) // Paper - EnderDragon Events
world.addFreshEntity(dragonFireball);
+ else dragonFireball.discard(null); // Paper - EnderDragon Events
this.fireballCharge = 0;
if (this.currentPath != null) {
while (!this.currentPath.isDone()) {
diff --git a/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java b/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java
index 5b8f3cf80b4fb425bdd0e3b9a431128536c7f1b1..2eecdcbea3d51b1fb6e0c3db0667464a699ca0df 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java
@@ -62,8 +62,10 @@ public class DragonFireball extends AbstractHurtingProjectile {
}
}
+ if (new com.destroystokyo.paper.event.entity.EnderDragonFireballHitEvent((org.bukkit.entity.DragonFireball) this.getBukkitEntity(), list.stream().map(LivingEntity::getBukkitLivingEntity).collect(java.util.stream.Collectors.toList()), (org.bukkit.entity.AreaEffectCloud) entityareaeffectcloud.getBukkitEntity()).callEvent()) { // Paper - EnderDragon Events
this.level().levelEvent(2006, this.blockPosition(), this.isSilent() ? -1 : 1);
this.level().addFreshEntity(entityareaeffectcloud);
+ } else entityareaeffectcloud.discard(null); // Paper - EnderDragon Events
this.discard(EntityRemoveEvent.Cause.HIT); // CraftBukkit - add Bukkit remove cause
}