diff --git a/Spigot-API-Patches/0123-InventoryCloseEvent-Reason-API.patch b/Spigot-API-Patches/0123-InventoryCloseEvent-Reason-API.patch new file mode 100644 index 0000000000..d3e8be94ad --- /dev/null +++ b/Spigot-API-Patches/0123-InventoryCloseEvent-Reason-API.patch @@ -0,0 +1,92 @@ +From eeec38e29cc2041734e18b87f80400f63fa7734c Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 3 Jul 2018 21:52:52 -0400 +Subject: [PATCH] InventoryCloseEvent Reason API + +Allows you to determine why an inventory was closed, enabling plugin developers +to "confirm" things based on if it was player triggered close or not. + +diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java +index dd95773e..3924d00c 100644 +--- a/src/main/java/org/bukkit/entity/HumanEntity.java ++++ b/src/main/java/org/bukkit/entity/HumanEntity.java +@@ -137,6 +137,13 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, Permissible, Inv + */ + public void closeInventory(); + ++ // Paper start ++ /** ++ * Force-closes the currently open inventory view for this player, if any. ++ */ ++ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason); ++ // Paper end ++ + /** + * Returns the ItemStack currently in your hand, can be empty. + * +diff --git a/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java +index 19889b27..e6e45b93 100644 +--- a/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java ++++ b/src/main/java/org/bukkit/event/inventory/InventoryCloseEvent.java +@@ -11,8 +11,58 @@ import org.bukkit.inventory.InventoryView; + public class InventoryCloseEvent extends InventoryEvent { + private static final HandlerList handlers = new HandlerList(); + ++ // Paper start ++ private final Reason reason; ++ public Reason getReason() { ++ return reason; ++ } ++ ++ public enum Reason { ++ /** ++ * Unknown reason ++ */ ++ UNKNOWN, ++ /** ++ * Player is teleporting ++ */ ++ TELEPORT, ++ /** ++ * Player is no longer permitted to use this inventory ++ */ ++ CANT_USE, ++ /** ++ * The chunk the inventory was in was unloaded ++ */ ++ UNLOADED, ++ /** ++ * Opening new inventory instead ++ */ ++ OPEN_NEW, ++ /** ++ * Closed ++ */ ++ PLAYER, ++ /** ++ * Closed due to disconnect ++ */ ++ DISCONNECT, ++ /** ++ * The player died ++ */ ++ DEATH, ++ /** ++ * Closed by Bukkit API ++ */ ++ PLUGIN, ++ } + public InventoryCloseEvent(InventoryView transaction) { ++ this(transaction, Reason.UNKNOWN); ++ } ++ ++ public InventoryCloseEvent(InventoryView transaction, Reason reason) { + super(transaction); ++ this.reason = reason; ++ // Paper end + } + + /** +-- +2.18.0 + diff --git a/Spigot-Server-Patches/0322-InventoryCloseEvent-Reason-API.patch b/Spigot-Server-Patches/0322-InventoryCloseEvent-Reason-API.patch new file mode 100644 index 0000000000..ef36008559 --- /dev/null +++ b/Spigot-Server-Patches/0322-InventoryCloseEvent-Reason-API.patch @@ -0,0 +1,189 @@ +From 579bde3a655017237446cb5e5589764243e25609 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Tue, 3 Jul 2018 21:56:23 -0400 +Subject: [PATCH] InventoryCloseEvent Reason API + +Allows you to determine why an inventory was closed, enabling plugin developers +to "confirm" things based on if it was player triggered close or not. + +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index 7cd537a59..ddd5ed57d 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -836,7 +836,7 @@ public class Chunk { + { + if ( h instanceof org.bukkit.craftbukkit.entity.CraftHumanEntity ) + { +- ( (org.bukkit.craftbukkit.entity.CraftHumanEntity) h).getHandle().closeInventory(); ++ ( (org.bukkit.craftbukkit.entity.CraftHumanEntity) h).getHandle().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper + } + } + } +@@ -861,7 +861,7 @@ public class Chunk { + { + if ( h instanceof org.bukkit.craftbukkit.entity.CraftHumanEntity ) + { +- ( (org.bukkit.craftbukkit.entity.CraftHumanEntity) h).getHandle().closeInventory(); ++ ( (org.bukkit.craftbukkit.entity.CraftHumanEntity) h).getHandle().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper + } + } + } +diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java +index 0b51903e2..aa0b27f0e 100644 +--- a/src/main/java/net/minecraft/server/EntityHuman.java ++++ b/src/main/java/net/minecraft/server/EntityHuman.java +@@ -145,7 +145,7 @@ public abstract class EntityHuman extends EntityLiving { + + super.B_(); + if (!this.world.isClientSide && this.activeContainer != null && !this.activeContainer.canUse(this)) { +- this.closeInventory(); ++ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper + this.activeContainer = this.defaultContainer; + } + +@@ -294,6 +294,13 @@ public abstract class EntityHuman extends EntityLiving { + return this.getHealth() <= 0.0F || this.isSleeping(); + } + ++ // Paper start - unused code, but to keep signatures aligned ++ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ closeInventory(); ++ this.activeContainer = this.defaultContainer; ++ } ++ // Paper end ++ + public void closeInventory() { + this.activeContainer = this.defaultContainer; + } +diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java +index cce3f98da..4ff505cfa 100644 +--- a/src/main/java/net/minecraft/server/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/EntityPlayer.java +@@ -287,7 +287,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + } + // Paper end + if (!this.world.isClientSide && !this.activeContainer.canUse(this)) { +- this.closeInventory(); ++ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper + this.activeContainer = this.defaultContainer; + } + +@@ -483,7 +483,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + this.inventory.clear(); + } + +- this.closeInventory(); ++ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DEATH); // Paper + this.setSpectatorTarget(this); // Remove spectated target + // CraftBukkit end + +@@ -837,7 +837,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + this.a((new ChatMessage("container.spectatorCantOpen", new Object[0])).setChatModifier((new ChatModifier()).setColor(EnumChatFormat.RED)), true); + } else { + if (this.activeContainer != this.defaultContainer) { +- this.closeInventory(); ++ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + + if (iinventory instanceof ITileInventory) { +@@ -903,7 +903,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + } + // CraftBukkit end + if (this.activeContainer != this.defaultContainer) { +- this.closeInventory(); ++ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + + this.nextContainerCounter(); +@@ -968,7 +968,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + } + + public void closeInventory() { +- CraftEventFactory.handleInventoryCloseEvent(this); // CraftBukkit ++ // Paper start ++ closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); ++ } ++ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ CraftEventFactory.handleInventoryCloseEvent(this, reason); // CraftBukkit ++ // Paper end + this.playerConnection.sendPacket(new PacketPlayOutCloseWindow(this.activeContainer.windowId)); + this.r(); + } +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index a5faa6a0a..96d2dee65 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -1758,7 +1758,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { + PlayerConnectionUtils.ensureMainThread(packetplayinclosewindow, this, this.player.x()); + + if (this.player.isFrozen()) return; // CraftBukkit +- CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit ++ CraftEventFactory.handleInventoryCloseEvent(this.player, org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLAYER); // CraftBukkit // Paper + + this.player.r(); + } +diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java +index b478f385a..eaaa54acd 100644 +--- a/src/main/java/net/minecraft/server/PlayerList.java ++++ b/src/main/java/net/minecraft/server/PlayerList.java +@@ -423,7 +423,7 @@ public abstract class PlayerList { + entityplayer.b(StatisticList.f); + + // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it +- org.bukkit.craftbukkit.event.CraftEventFactory.handleInventoryCloseEvent(entityplayer); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleInventoryCloseEvent(entityplayer, org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper + + PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), "\u00A7e" + entityplayer.getName() + " left the game"); + cserver.getPluginManager().callEvent(playerQuitEvent); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +index d85b5defc..05ca403e8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +@@ -401,8 +401,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + } + + public void closeInventory() { +- getHandle().closeInventory(); ++ // Paper start ++ getHandle().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLUGIN); + } ++ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ getHandle().closeInventory(reason); ++ } ++ // Paper end + + public boolean isBlocking() { + return getHandle().isBlocking(); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index fd47065c6..53f973615 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -640,7 +640,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + // Close any foreign inventory + if (getHandle().activeContainer != getHandle().defaultContainer) { +- getHandle().closeInventory(); ++ getHandle().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.TELEPORT); // Paper + } + + // Check if the fromWorld and toWorld are the same. +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 248873fb4..c6f447205 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -927,8 +927,10 @@ public class CraftEventFactory { + return event; + } + +- public static void handleInventoryCloseEvent(EntityHuman human) { +- InventoryCloseEvent event = new InventoryCloseEvent(human.activeContainer.getBukkitView()); ++ // Paper start ++ public static void handleInventoryCloseEvent(EntityHuman human, org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ InventoryCloseEvent event = new InventoryCloseEvent(human.activeContainer.getBukkitView(), reason); ++ // Paper end + human.world.getServer().getPluginManager().callEvent(event); + human.activeContainer.transferTo(human.defaultContainer, human.getBukkitEntity()); + } +-- +2.18.0 +