From b9023b5dc3dbc2f9d19898f73e503bddde364bcf Mon Sep 17 00:00:00 2001
From: Chaosdave34 <48226277+Chaosdave34@users.noreply.github.com>
Date: Sun, 16 Feb 2025 20:19:28 +0100
Subject: [PATCH] Add EntityAttemptSmashAttackEvent (#12113)

---
 .../entity/EntityAttemptSmashAttackEvent.java | 103 ++++++++++++++++++
 .../minecraft/world/item/MaceItem.java.patch  |  17 +++
 2 files changed, 120 insertions(+)
 create mode 100644 paper-api/src/main/java/io/papermc/paper/event/entity/EntityAttemptSmashAttackEvent.java
 create mode 100644 paper-server/patches/sources/net/minecraft/world/item/MaceItem.java.patch

diff --git a/paper-api/src/main/java/io/papermc/paper/event/entity/EntityAttemptSmashAttackEvent.java b/paper-api/src/main/java/io/papermc/paper/event/entity/EntityAttemptSmashAttackEvent.java
new file mode 100644
index 0000000000..007b61d018
--- /dev/null
+++ b/paper-api/src/main/java/io/papermc/paper/event/entity/EntityAttemptSmashAttackEvent.java
@@ -0,0 +1,103 @@
+package io.papermc.paper.event.entity;
+
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jspecify.annotations.NullMarked;
+
+/**
+ * Called when an entity attempts to perform a smash attack.
+ */
+@NullMarked
+public class EntityAttemptSmashAttackEvent extends EntityEvent {
+
+    private static final HandlerList HANDLER_LIST = new HandlerList();
+
+    private final LivingEntity target;
+    private final ItemStack weapon;
+    private final boolean originalResult;
+    private Result result = Result.DEFAULT;
+
+    @ApiStatus.Internal
+    public EntityAttemptSmashAttackEvent(
+        final LivingEntity attacker,
+        final LivingEntity target,
+        final ItemStack weapon,
+        final boolean originalResult
+    ) {
+        super(attacker);
+        this.target = target;
+        this.weapon = weapon;
+        this.originalResult = originalResult;
+    }
+
+    /**
+     * Yields the target of the attempted smash attack.
+     *
+     * @return the target entity
+     */
+    public LivingEntity getTarget() {
+        return target;
+    }
+
+    /**
+     * Yields a copy of the itemstack used in the smash attack attempt.
+     *
+     * @return the itemstack
+     */
+    public ItemStack getWeapon() {
+        return weapon.clone();
+    }
+
+    /**
+     * Yields the original result the server computed.
+     *
+     * @return {@code true} if this attempt would have been successful by vanilla's logic, {@code false} otherwise.
+     */
+    public boolean getOriginalResult() {
+        return originalResult;
+    }
+
+    /**
+     * Yields the effective result of this event.
+     * The result may take one of three values:
+     *
+     * <ul>
+     *     <li>{@link Result#ALLOW}: The attempt will succeed.</li>
+     *     <li>{@link Result#DENY}: The attempt will fail.</li>
+     *     <li>{@link Result#DEFAULT}: The attempt will succeed if {@link #getOriginalResult()} is {@code true} and fail otherwise.</li>
+     * </ul>
+     *
+     * @return the result.
+     */
+    public Result getResult() {
+        return this.result;
+    }
+
+    /**
+     * Configures a new result for this event.
+     * The passes result may take one of three values:
+     *
+     * <ul>
+     *     <li>{@link Result#ALLOW}: The attempt will succeed.</li>
+     *     <li>{@link Result#DENY}: The attempt will fail.</li>
+     *     <li>{@link Result#DEFAULT}: The attempt will succeed if {@link #getOriginalResult()} is {@code true} and fail otherwise.</li>
+     * </ul>
+     *
+     * @param result the new result of the event.
+     */
+    public void setResult(final Result result) {
+        this.result = result;
+    }
+
+    @Override
+    public HandlerList getHandlers() {
+        return HANDLER_LIST;
+    }
+
+    public static HandlerList getHandlerList() {
+        return HANDLER_LIST;
+    }
+}
diff --git a/paper-server/patches/sources/net/minecraft/world/item/MaceItem.java.patch b/paper-server/patches/sources/net/minecraft/world/item/MaceItem.java.patch
new file mode 100644
index 0000000000..cfeffcdd8e
--- /dev/null
+++ b/paper-server/patches/sources/net/minecraft/world/item/MaceItem.java.patch
@@ -0,0 +1,17 @@
+--- a/net/minecraft/world/item/MaceItem.java
++++ b/net/minecraft/world/item/MaceItem.java
+@@ -61,7 +_,13 @@
+ 
+     @Override
+     public boolean hurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) {
+-        if (canSmashAttack(attacker)) {
++        // Paper start - Add EntityAttemptSmashAttackEvent
++        final boolean canSmashAttack = canSmashAttack(attacker);
++        io.papermc.paper.event.entity.EntityAttemptSmashAttackEvent event = new io.papermc.paper.event.entity.EntityAttemptSmashAttackEvent(attacker.getBukkitLivingEntity(), target.getBukkitLivingEntity(), stack.asBukkitCopy(), canSmashAttack);
++        event.callEvent();
++        final org.bukkit.event.Event.Result result = event.getResult();
++        if (result == org.bukkit.event.Event.Result.ALLOW || (canSmashAttack && result == org.bukkit.event.Event.Result.DEFAULT)) {
++        // Paper end - Add EntityAttemptSmashAttackEvent
+             ServerLevel serverLevel = (ServerLevel)attacker.level();
+             attacker.setDeltaMovement(attacker.getDeltaMovement().with(Direction.Axis.Y, 0.01F));
+             if (attacker instanceof ServerPlayer serverPlayer) {