--- a/net/minecraft/world/entity/decoration/EntityLeash.java
+++ b/net/minecraft/world/entity/decoration/EntityLeash.java
@@ -27,6 +27,13 @@
 import net.minecraft.world.phys.AxisAlignedBB;
 import net.minecraft.world.phys.Vec3D;
 
+// CraftBukkit start
+import net.minecraft.network.protocol.game.PacketPlayOutAttachEntity;
+import net.minecraft.server.level.EntityPlayer;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityRemoveEvent;
+// CraftBukkit end
+
 public class EntityLeash extends BlockAttachedEntity {
 
     public static final double OFFSET_Y = 0.375D;
@@ -85,6 +92,15 @@
                 Leashable leashable = (Leashable) iterator.next();
 
                 if (leashable.getLeashHolder() == entityhuman) {
+                    // CraftBukkit start
+                    if (leashable instanceof Entity leashed) {
+                        if (CraftEventFactory.callPlayerLeashEntityEvent(leashed, this, entityhuman, enumhand).isCancelled()) {
+                            ((EntityPlayer) entityhuman).connection.send(new PacketPlayOutAttachEntity(leashed, leashable.getLeashHolder()));
+                            flag = true; // Also set true when the event is cancelled otherwise it tries to unleash the entities
+                            continue;
+                        }
+                    }
+                    // CraftBukkit end
                     leashable.setLeashedTo(this, true);
                     flag = true;
                 }
@@ -93,18 +109,38 @@
             boolean flag1 = false;
 
             if (!flag) {
-                this.discard();
-                if (entityhuman.getAbilities().instabuild) {
+                // CraftBukkit start - Move below
+                // this.discard();
+                boolean die = true;
+                // CraftBukkit end
+                if (true || entityhuman.getAbilities().instabuild) { // CraftBukkit - Process for non-creative as well
                     Iterator iterator1 = list.iterator();
 
                     while (iterator1.hasNext()) {
                         Leashable leashable1 = (Leashable) iterator1.next();
 
                         if (leashable1.isLeashed() && leashable1.getLeashHolder() == this) {
-                            leashable1.removeLeash();
+                            // CraftBukkit start
+                            if (leashable1 instanceof Entity leashed) {
+                                if (CraftEventFactory.callPlayerUnleashEntityEvent(leashed, entityhuman, enumhand).isCancelled()) {
+                                    die = false;
+                                    continue;
+                                }
+                            }
+                            if (entityhuman.getAbilities().instabuild){
+                                leashable1.removeLeash();
+                            } else {
+                                leashable1.dropLeash();
+                            }
+                            // CraftBukkit end
                             flag1 = true;
                         }
                     }
+                    // CraftBukkit start
+                    if (die) {
+                        this.discard(EntityRemoveEvent.Cause.DROP); // CraftBukkit - add Bukkit remove cause
+                    }
+                    // CraftBukkit end
                 }
             }
 
