--- a/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java
+++ b/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java
@@ -1,5 +1,6 @@
 package net.minecraft.world.entity.decoration;
 
+import java.util.Iterator;
 import java.util.List;
 import javax.annotation.Nullable;
 import net.minecraft.core.BlockPos;
@@ -7,8 +8,10 @@
 import net.minecraft.network.protocol.Packet;
 import net.minecraft.network.protocol.game.ClientGamePacketListener;
 import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
+import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket;
 import net.minecraft.network.syncher.SynchedEntityData;
 import net.minecraft.server.level.ServerEntity;
+import net.minecraft.server.level.ServerPlayer;
 import net.minecraft.sounds.SoundEvents;
 import net.minecraft.tags.BlockTags;
 import net.minecraft.world.InteractionHand;
@@ -24,9 +27,13 @@
 import net.minecraft.world.level.gameevent.GameEvent;
 import net.minecraft.world.phys.AABB;
 import net.minecraft.world.phys.Vec3;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityRemoveEvent;
+// CraftBukkit end
 
 public class LeashFenceKnotEntity extends BlockAttachedEntity {
-    public static final double OFFSET_Y = 0.375;
+
+    public static final double OFFSET_Y = 0.375D;
 
     public LeashFenceKnotEntity(EntityType<? extends LeashFenceKnotEntity> type, Level world) {
         super(type, world);
@@ -34,24 +41,24 @@
 
     public LeashFenceKnotEntity(Level world, BlockPos pos) {
         super(EntityType.LEASH_KNOT, world, pos);
-        this.setPos((double)pos.getX(), (double)pos.getY(), (double)pos.getZ());
+        this.setPos((double) pos.getX(), (double) pos.getY(), (double) pos.getZ());
     }
 
     @Override
-    protected void defineSynchedData(SynchedEntityData.Builder builder) {
-    }
+    protected void defineSynchedData(SynchedEntityData.Builder builder) {}
 
     @Override
     protected void recalculateBoundingBox() {
-        this.setPosRaw((double)this.pos.getX() + 0.5, (double)this.pos.getY() + 0.375, (double)this.pos.getZ() + 0.5);
-        double d = (double)this.getType().getWidth() / 2.0;
-        double e = (double)this.getType().getHeight();
-        this.setBoundingBox(new AABB(this.getX() - d, this.getY(), this.getZ() - d, this.getX() + d, this.getY() + e, this.getZ() + d));
+        this.setPosRaw((double) this.pos.getX() + 0.5D, (double) this.pos.getY() + 0.375D, (double) this.pos.getZ() + 0.5D);
+        double d0 = (double) this.getType().getWidth() / 2.0D;
+        double d1 = (double) this.getType().getHeight();
+
+        this.setBoundingBox(new AABB(this.getX() - d0, this.getY(), this.getZ() - d0, this.getX() + d0, this.getY() + d1, this.getZ() + d0));
     }
 
     @Override
     public boolean shouldRenderAtSqrDistance(double distance) {
-        return distance < 1024.0;
+        return distance < 1024.0D;
     }
 
     @Override
@@ -60,45 +67,82 @@
     }
 
     @Override
-    public void addAdditionalSaveData(CompoundTag nbt) {
-    }
+    public void addAdditionalSaveData(CompoundTag nbt) {}
 
     @Override
-    public void readAdditionalSaveData(CompoundTag nbt) {
-    }
+    public void readAdditionalSaveData(CompoundTag nbt) {}
 
     @Override
     public InteractionResult interact(Player player, InteractionHand hand) {
         if (this.level().isClientSide) {
             return InteractionResult.SUCCESS;
         } else {
-            boolean bl = false;
-            List<Leashable> list = LeadItem.leashableInArea(this.level(), this.getPos(), entity -> {
-                Entity entity2 = entity.getLeashHolder();
-                return entity2 == player || entity2 == this;
+            boolean flag = false;
+            List<Leashable> list = LeadItem.leashableInArea(this.level(), this.getPos(), (leashable) -> {
+                Entity entity = leashable.getLeashHolder();
+
+                return entity == player || entity == this;
             });
+            Iterator iterator = list.iterator();
+
+            while (iterator.hasNext()) {
+                Leashable leashable = (Leashable) iterator.next();
 
-            for (Leashable leashable : list) {
                 if (leashable.getLeashHolder() == player) {
+                    // CraftBukkit start
+                    if (leashable instanceof Entity leashed) {
+                        if (CraftEventFactory.callPlayerLeashEntityEvent(leashed, this, player, hand).isCancelled()) {
+                            ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(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);
-                    bl = true;
+                    flag = true;
                 }
             }
 
-            boolean bl2 = false;
-            if (!bl) {
-                this.discard();
-                if (player.getAbilities().instabuild) {
-                    for (Leashable leashable2 : list) {
-                        if (leashable2.isLeashed() && leashable2.getLeashHolder() == this) {
-                            leashable2.dropLeash(true, false);
-                            bl2 = true;
+            boolean flag1 = false;
+
+            if (!flag) {
+                // CraftBukkit start - Move below
+                // this.discard();
+                boolean die = true;
+                // CraftBukkit end
+                if (true || player.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) {
+                            // CraftBukkit start
+                            boolean dropLeash = !player.hasInfiniteMaterials();
+                            if (leashable1 instanceof Entity leashed) {
+                                // Paper start - Expand EntityUnleashEvent
+                                org.bukkit.event.player.PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(leashed, player, hand, dropLeash);
+                                dropLeash = event.isDropLeash();
+                                if (event.isCancelled()) {
+                                    // Paper end - Expand EntityUnleashEvent
+                                    die = false;
+                                    continue;
+                                }
+                            }
+                            leashable1.dropLeash(true, dropLeash); // false -> survival mode boolean // Paper - Expand EntityUnleashEvent
+                            // CraftBukkit end
+                            flag1 = true;
                         }
                     }
+                    // CraftBukkit start
+                    if (die) {
+                        this.discard(EntityRemoveEvent.Cause.DROP); // CraftBukkit - add Bukkit remove cause
+                    }
+                    // CraftBukkit end
                 }
             }
 
-            if (bl || bl2) {
+            if (flag || flag1) {
                 this.gameEvent(GameEvent.BLOCK_ATTACH, player);
             }
 
@@ -115,18 +159,23 @@
         int i = pos.getX();
         int j = pos.getY();
         int k = pos.getZ();
+        List<LeashFenceKnotEntity> list = world.getEntitiesOfClass(LeashFenceKnotEntity.class, new AABB((double) i - 1.0D, (double) j - 1.0D, (double) k - 1.0D, (double) i + 1.0D, (double) j + 1.0D, (double) k + 1.0D));
+        Iterator iterator = list.iterator();
 
-        for (LeashFenceKnotEntity leashFenceKnotEntity : world.getEntitiesOfClass(
-            LeashFenceKnotEntity.class, new AABB((double)i - 1.0, (double)j - 1.0, (double)k - 1.0, (double)i + 1.0, (double)j + 1.0, (double)k + 1.0)
-        )) {
-            if (leashFenceKnotEntity.getPos().equals(pos)) {
-                return leashFenceKnotEntity;
+        LeashFenceKnotEntity entityleash;
+
+        do {
+            if (!iterator.hasNext()) {
+                LeashFenceKnotEntity entityleash1 = new LeashFenceKnotEntity(world, pos);
+
+                world.addFreshEntity(entityleash1);
+                return entityleash1;
             }
-        }
 
-        LeashFenceKnotEntity leashFenceKnotEntity2 = new LeashFenceKnotEntity(world, pos);
-        world.addFreshEntity(leashFenceKnotEntity2);
-        return leashFenceKnotEntity2;
+            entityleash = (LeashFenceKnotEntity) iterator.next();
+        } while (!entityleash.getPos().equals(pos));
+
+        return entityleash;
     }
 
     public void playPlacementSound() {
@@ -140,7 +189,7 @@
 
     @Override
     public Vec3 getRopeHoldPosition(float delta) {
-        return this.getPosition(delta).add(0.0, 0.2, 0.0);
+        return this.getPosition(delta).add(0.0D, 0.2D, 0.0D);
     }
 
     @Override
