Paper/Spigot-Server-Patches/0279-InventoryCloseEvent-Reason-API.patch
Aikar 9dc4d6448b
Numerous fixes to entity related changes
While it wasn't really "broken" before, if plugins use NMS
(which they really should't be) and mess with entity management
themselves, and get it wrong, they could ultimately corrupt our
state expectations.

I've been unable to reproduce any issues locally, but these changes
are the result of me analyzing the code pretty deeply and seeing
about how to make it more durable to abnormal usage.

Any servers seeing oddities, please run with -Ddebug.entities=true
and send me any logs triggered.
2019-04-05 23:08:45 -04:00

198 lines
10 KiB
Diff

From 5db8e75d6daadd431d60cfc697b54397eda03abe Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
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 a6cacd7da9..c2f12f92b0 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -944,7 +944,7 @@ public class Chunk implements IChunkAccess {
{
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
}
}
}
@@ -969,7 +969,7 @@ public class Chunk implements IChunkAccess {
{
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 d4618d644a..cc1bc01b16 100644
--- a/src/main/java/net/minecraft/server/EntityHuman.java
+++ b/src/main/java/net/minecraft/server/EntityHuman.java
@@ -158,7 +158,7 @@ public abstract class EntityHuman extends EntityLiving {
this.dg();
super.tick();
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;
}
@@ -360,6 +360,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 e4e1d999e9..dc72538de6 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -344,7 +344,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;
}
@@ -555,7 +555,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
if (!event.getKeepInventory()) {
this.inventory.clear();
}
-
+ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DEATH); // Paper
this.setSpectatorTarget(this); // Remove spectated target
// CraftBukkit end
@@ -873,7 +873,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
this.a((new ChatMessage("container.spectatorCantOpen", new Object[0])).a(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) {
@@ -946,7 +946,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();
@@ -1011,7 +1011,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.m();
}
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
index 5ffb2cd346..a00b271b2f 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -2000,7 +2000,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable {
PlayerConnectionUtils.ensureMainThread(packetplayinclosewindow, this, this.player.getWorldServer());
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.m();
}
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
index 96eff10ffa..ddaa73e83d 100644
--- a/src/main/java/net/minecraft/server/PlayerList.java
+++ b/src/main/java/net/minecraft/server/PlayerList.java
@@ -422,7 +422,7 @@ public abstract class PlayerList {
entityplayer.a(StatisticList.LEAVE_GAME);
// 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 9b19dce9bd..cb7697f80b 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
@@ -513,8 +513,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 62235efde9..47426d8fda 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -743,7 +743,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 acc80d0684..2cfe8afe13 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -1110,8 +1110,19 @@ public class CraftEventFactory {
return event;
}
+ // Paper start
+
+ /**
+ * Incase plugins hooked into this or Spigot adds a new inventory close event. Prefer to pass a reason
+ * @param human
+ */
+ @Deprecated
public static void handleInventoryCloseEvent(EntityHuman human) {
- InventoryCloseEvent event = new InventoryCloseEvent(human.activeContainer.getBukkitView());
+ handleInventoryCloseEvent(human, org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN);
+ }
+ 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.21.0