From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Fri, 29 Jan 2021 15:13:11 +0100
Subject: [PATCH] Expand EntityUnleashEvent


diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 7d131f3b3f5739468aa3115e97ed28b6bfeca33d..da184893d617311a43f9ce176a965f8417a2876d 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -2574,12 +2574,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
             if (leashable.getLeashHolder() == player) {
                 if (!this.level().isClientSide()) {
                     // CraftBukkit start - fire PlayerUnleashEntityEvent
-                    if (CraftEventFactory.callPlayerUnleashEntityEvent(this, player, hand).isCancelled()) {
+                    // Paper start - Expand EntityUnleashEvent
+                    org.bukkit.event.player.PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(this, player, hand, !player.hasInfiniteMaterials());
+                    if (event.isCancelled()) {
+                        // Paper end - Expand EntityUnleashEvent
                         ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, leashable.getLeashHolder()));
                         return InteractionResult.PASS;
                     }
                     // CraftBukkit end
-                    leashable.dropLeash(true, !player.hasInfiniteMaterials());
+                    leashable.dropLeash(true, event.isDropLeash()); // Paper - Expand EntityUnleashEvent
                     this.gameEvent(GameEvent.ENTITY_INTERACT, player);
                 }
 
@@ -3449,9 +3452,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
 
     protected void removeAfterChangingDimensions() {
         this.setRemoved(Entity.RemovalReason.CHANGED_DIMENSION, null); // CraftBukkit - add Bukkit remove cause
-        if (this instanceof Leashable leashable) {
-            this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit
-            leashable.dropLeash(true, false);
+        if (this instanceof Leashable leashable && leashable.isLeashed()) { // Paper - only call if it is leashed
+            // Paper start - Expand EntityUnleashEvent
+            final EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN, false); // CraftBukkit
+            event.callEvent();
+            leashable.dropLeash(true, event.isDropLeash());
+            // Paper end - Expand EntityUnleashEvent
         }
 
     }
diff --git a/src/main/java/net/minecraft/world/entity/Leashable.java b/src/main/java/net/minecraft/world/entity/Leashable.java
index 5c51dd5229689cba459655d488aee59bd159a414..e7535f15be3cc1537aafee53779ccfb4f21d1f38 100644
--- a/src/main/java/net/minecraft/world/entity/Leashable.java
+++ b/src/main/java/net/minecraft/world/entity/Leashable.java
@@ -166,8 +166,11 @@ public interface Leashable {
 
         if (leashable_a != null && leashable_a.leashHolder != null) {
             if (!entity.isAlive() || !leashable_a.leashHolder.isAlive()) {
-                entity.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(entity.getBukkitEntity(), (!entity.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE)); // CraftBukkit
-                Leashable.dropLeash(entity, true, !entity.pluginRemoved); // CraftBukkit - SPIGOT-7487: Don't drop leash, when the holder was removed by a plugin
+                // Paper start - Expand EntityUnleashEvent
+                final EntityUnleashEvent event = new EntityUnleashEvent(entity.getBukkitEntity(), (!entity.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE, !entity.pluginRemoved);
+                event.callEvent();
+                Leashable.dropLeash(entity, true, event.isDropLeash()); // CraftBukkit - SPIGOT-7487: Don't drop leash, when the holder was removed by a plugin
+                // Paper end - Expand EntityUnleashEvent
             }
 
             Entity entity1 = ((Leashable) entity).getLeashHolder();
@@ -198,11 +201,16 @@ public interface Leashable {
 
     default void leashTooFarBehaviour() {
         // CraftBukkit start
+        boolean dropLeash = true; // Paper
         if (this instanceof Entity entity) {
-            entity.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(entity.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE));
+            // Paper start - Expand EntityUnleashEvent
+            final EntityUnleashEvent event = new EntityUnleashEvent(entity.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true);
+            if (!event.callEvent()) return;
+            dropLeash = event.isDropLeash();
+            // Paper end - Expand EntityUnleashEvent
         }
         // CraftBukkit end
-        this.dropLeash(true, true);
+        this.dropLeash(true, dropLeash); // Paper
     }
 
     default void closeRangeLeashBehaviour(Entity entity) {}
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
index b46572f6e3b52f498b395d3b8c5def2aa799ff03..e87360e21e6eb7b0161c34a3ac6cb83d18bcd1e8 100644
--- a/src/main/java/net/minecraft/world/entity/Mob.java
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
@@ -1621,8 +1621,11 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
         boolean flag1 = super.startRiding(entity, force);
 
         if (flag1 && this.isLeashed()) {
-            this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit
-            this.dropLeash(true, true);
+            // Paper start - Expand EntityUnleashEvent
+            EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.UNKNOWN, true);
+            if (!event.callEvent()) { return flag1; }
+            this.dropLeash(true, event.isDropLeash());
+            // Paper end - Expand EntityUnleashEvent
         }
 
         return flag1;
diff --git a/src/main/java/net/minecraft/world/entity/TamableAnimal.java b/src/main/java/net/minecraft/world/entity/TamableAnimal.java
index bf2c9134c7d9d5926add36b55e3cfea79e8c8243..7b7bc1a205dfacbe5709011b6b6799e75af9e4cc 100644
--- a/src/main/java/net/minecraft/world/entity/TamableAnimal.java
+++ b/src/main/java/net/minecraft/world/entity/TamableAnimal.java
@@ -98,7 +98,11 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity {
     public boolean handleLeashAtDistance(Entity leashHolder, float distance) {
         if (this.isInSittingPose()) {
             if (distance > (float) this.level().paperConfig().misc.maxLeashDistance.or(Leashable.LEASH_TOO_FAR_DIST)) { // Paper - Configurable max leash distance
-                this.dropLeash(true, true);
+                // Paper start - Expand EntityUnleashEvent
+                org.bukkit.event.entity.EntityUnleashEvent event = new org.bukkit.event.entity.EntityUnleashEvent(this.getBukkitEntity(), org.bukkit.event.entity.EntityUnleashEvent.UnleashReason.DISTANCE, true);
+                if (!event.callEvent()) return false;
+                this.dropLeash(true, event.isDropLeash());
+                // Paper end - Expand EntityUnleashEvent
             }
 
             return false;
diff --git a/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java b/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java
index 3c0af74ed65610b1d5e3b72fdcf28c5a3423f0da..01173fc7177d78588978e087e63efda0b0527c2f 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java
@@ -118,13 +118,18 @@ public class LeashFenceKnotEntity extends BlockAttachedEntity {
 
                         if (leashable1.isLeashed() && leashable1.getLeashHolder() == this) {
                             // CraftBukkit start
+                            boolean dropLeash = !player.hasInfiniteMaterials();
                             if (leashable1 instanceof Entity leashed) {
-                                if (CraftEventFactory.callPlayerUnleashEntityEvent(leashed, player, hand).isCancelled()) {
+                                // 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, !player.getAbilities().instabuild); // false -> survival mode boolean
+                            leashable1.dropLeash(true, dropLeash); // false -> survival mode boolean // Paper - Expand EntityUnleashEvent
                             // CraftBukkit end
                             flag1 = true;
                         }
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 251b605396b77b0c449972c1da75978f57587e1a..c48a9026c4db2005b67c5f70e9e1fa95b7820bc0 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -1598,8 +1598,10 @@ public class CraftEventFactory {
         Bukkit.getPluginManager().callEvent(new PlayerRecipeBookSettingsChangeEvent(player.getBukkitEntity(), bukkitType, open, filter));
     }
 
-    public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(Entity entity, net.minecraft.world.entity.player.Player player, InteractionHand enumhand) {
-        PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity(), CraftEquipmentSlot.getHand(enumhand));
+    // Paper start - Expand EntityUnleashEvent
+    public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(Entity entity, net.minecraft.world.entity.player.Player player, InteractionHand enumhand, boolean dropLeash) {
+        PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity(), CraftEquipmentSlot.getHand(enumhand), dropLeash);
+        // Paper end - Expand EntityUnleashEvent
         entity.level().getCraftServer().getPluginManager().callEvent(event);
         return event;
     }