From 25d538dd89eb048d59ac626afe4121377632226d Mon Sep 17 00:00:00 2001 From: Clexus <528373858@qq.com> Date: Sun, 6 Jul 2025 15:28:28 +0800 Subject: [PATCH] Add EntitySpinAttackEvent --- .../event/entity/EntitySpinAttackEvent.java | 63 +++++++++++++++++++ .../world/entity/LivingEntity.java.patch | 16 +++++ 2 files changed, 79 insertions(+) create mode 100644 paper-api/src/main/java/io/papermc/paper/event/entity/EntitySpinAttackEvent.java diff --git a/paper-api/src/main/java/io/papermc/paper/event/entity/EntitySpinAttackEvent.java b/paper-api/src/main/java/io/papermc/paper/event/entity/EntitySpinAttackEvent.java new file mode 100644 index 000000000000..e4f095dc993a --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/event/entity/EntitySpinAttackEvent.java @@ -0,0 +1,63 @@ +package io.papermc.paper.event.entity; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.EntityEvent; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + + +/** + * Called when an entity is performing a spin attack and touches other entities. + * Currently, only player has default damage action which + * calls {@link org.bukkit.event.entity.EntityDamageByEntityEvent}. + */ +@NullMarked +public class EntitySpinAttackEvent extends EntityEvent implements Cancellable { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private boolean cancelled; + private final LivingEntity touched; + + + @ApiStatus.Internal + public EntitySpinAttackEvent(final LivingEntity attacker, final LivingEntity touched) { + super(attacker); + this.touched = touched; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(final boolean cancel) { + this.cancelled = cancel; + } + + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } + + /** + * Gets the entity that gets touched. + * + * @return the touched entity + */ + public LivingEntity getTouched() { + return touched; + } + + @Override + public LivingEntity getEntity() { + return (LivingEntity) super.getEntity(); + } +} 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 3553abdf602c..b1e19370e838 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 @@ -1540,6 +1540,22 @@ this.doPush(entity1); } } +@@ -2956,8 +_,13 @@ + List entities = this.level().getEntities(this, aabb); + if (!entities.isEmpty()) { + for (Entity entity : entities) { +- if (entity instanceof LivingEntity) { +- this.doAutoAttackOnTouch((LivingEntity)entity); ++ if (entity instanceof LivingEntity livingEntity) { // Paper - move LivingEntity conversion ahead ++ // Paper start - fire EntitySpinAttackEvent ++ if(!(new io.papermc.paper.event.entity.EntitySpinAttackEvent(this.getBukkitLivingEntity(), livingEntity.getBukkitLivingEntity()).callEvent())){ ++ continue; ++ } ++ // Paper end - fire EntitySpinAttackEvent ++ this.doAutoAttackOnTouch(livingEntity); + this.autoSpinAttackTicks = 0; + this.setDeltaMovement(this.getDeltaMovement().scale(-0.2)); + break; @@ -2987,9 +_,16 @@ @Override