From e343c4eb445d66791d6c23446d466a1a2a4941eb Mon Sep 17 00:00:00 2001 From: SamB440 Date: Sat, 11 Feb 2023 15:41:06 +0000 Subject: [PATCH] Add projectile hit simulation API (#8816) This adds API to force a projectile to hit a provided entity. Example usage could be if you have a player disguised as another entity, you could simulate an arrow colliding with the (fake) entity hitbox. --- patches/api/More-Projectile-API.patch | 35 +++++++++++++++++++ ...rojectileHitEvent-for-piercing-arrow.patch | 2 +- patches/server/More-Projectile-API.patch | 17 +++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/patches/api/More-Projectile-API.patch b/patches/api/More-Projectile-API.patch index b45037da6a..d944bdf8c5 100644 --- a/patches/api/More-Projectile-API.patch +++ b/patches/api/More-Projectile-API.patch @@ -225,6 +225,41 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @param beenShot has been in shot into the world + */ + void setHasBeenShot(boolean beenShot); ++ ++ /** ++ * Gets whether this projectile can hit an entity. ++ *

++ * This method returns true under the following conditions: ++ *

++ * - The shooter can see the entity ({@link Player#canSee(Entity)})

++ * - The entity is alive and not a spectator

++ * - The projectile has left the hitbox of the shooter ({@link #hasLeftShooter()})

++ * - If this is an arrow with piercing, it has not pierced the entity already ++ * ++ * @param entity the entity to check if this projectile can hit ++ * @return true if this projectile can damage the entity, false otherwise ++ */ ++ boolean canHitEntity(@org.jetbrains.annotations.NotNull Entity entity); ++ ++ /** ++ * Makes this projectile hit a specific entity. ++ * This uses the current position of the projectile for the hit point. ++ * Using this method will result in {@link org.bukkit.event.entity.ProjectileHitEvent} being called. ++ * @param entity the entity to hit ++ * @see #hitEntity(Entity, org.bukkit.util.Vector) ++ * @see #canHitEntity(Entity) ++ */ ++ void hitEntity(@org.jetbrains.annotations.NotNull Entity entity); ++ ++ /** ++ * Makes this projectile hit a specific entity from a specific point. ++ * Using this method will result in {@link org.bukkit.event.entity.ProjectileHitEvent} being called. ++ * @param entity the entity to hit ++ * @param vector the direction to hit from ++ * @see #hitEntity(Entity) ++ * @see #canHitEntity(Entity) ++ */ ++ void hitEntity(@org.jetbrains.annotations.NotNull Entity entity, @org.jetbrains.annotations.NotNull org.bukkit.util.Vector vector); + // Paper end } diff --git a/src/main/java/org/bukkit/entity/ShulkerBullet.java b/src/main/java/org/bukkit/entity/ShulkerBullet.java diff --git a/patches/server/Fix-cancelling-ProjectileHitEvent-for-piercing-arrow.patch b/patches/server/Fix-cancelling-ProjectileHitEvent-for-piercing-arrow.patch index 8805b11086..9da51bd837 100644 --- a/patches/server/Fix-cancelling-ProjectileHitEvent-for-piercing-arrow.patch +++ b/patches/server/Fix-cancelling-ProjectileHitEvent-for-piercing-arrow.patch @@ -24,7 +24,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start + @Override -+ protected void preOnHit(HitResult hitResult) { ++ public void preOnHit(HitResult hitResult) { + super.preOnHit(hitResult); + if (hitResult instanceof EntityHitResult entityHitResult && this.hitCancelled && this.getPierceLevel() > 0) { + if (this.piercingIgnoreEntityIds == null) { diff --git a/patches/server/More-Projectile-API.patch b/patches/server/More-Projectile-API.patch index 207fcb2f15..a30f72f3a7 100644 --- a/patches/server/More-Projectile-API.patch +++ b/patches/server/More-Projectile-API.patch @@ -14,6 +14,8 @@ public net.minecraft.world.entity.projectile.AbstractArrow soundEvent public net.minecraft.world.entity.projectile.ThrownTrident dealtDamage public net.minecraft.world.entity.projectile.Projectile hasBeenShot public net.minecraft.world.entity.projectile.Projectile leftOwner +public net.minecraft.world.entity.projectile.Projectile preOnHit(Lnet/minecraft/world/phys/HitResult;)V +public net.minecraft.world.entity.projectile.Projectile canHitEntity(Lnet/minecraft/world/entity/Entity;)Z Co-authored-by: Nassim Jahnke @@ -72,6 +74,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override ++ public boolean canHitEntity(org.bukkit.entity.Entity entity) { ++ return this.getHandle().canHitEntity(((CraftEntity) entity).getHandle()); ++ } ++ ++ @Override ++ public void hitEntity(org.bukkit.entity.Entity entity) { ++ this.getHandle().preOnHit(new net.minecraft.world.phys.EntityHitResult(((CraftEntity) entity).getHandle())); ++ } ++ ++ @Override ++ public void hitEntity(org.bukkit.entity.Entity entity, org.bukkit.util.Vector vector) { ++ this.getHandle().preOnHit(new net.minecraft.world.phys.EntityHitResult(((CraftEntity) entity).getHandle(), new net.minecraft.world.phys.Vec3(vector.getX(), vector.getY(), vector.getZ()))); ++ } ++ ++ @Override + public net.minecraft.world.entity.projectile.Projectile getHandle() { + return (net.minecraft.world.entity.projectile.Projectile) entity; + }