From dd7f5642126a1e7d54d369aa062b9bbdbb932b1d Mon Sep 17 00:00:00 2001 From: MrPowerGamerBR Date: Sun, 2 Nov 2025 15:23:17 -0300 Subject: [PATCH] Add InventoryPreMoveItemEvent --- .../inventory/InventoryPreMoveItemEvent.java | 85 +++++++++++++++++++ .../block/entity/HopperBlockEntity.java.patch | 64 ++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 sparklypaper-api/src/main/java/net/sparklypower/sparklypaper/event/inventory/InventoryPreMoveItemEvent.java diff --git a/sparklypaper-api/src/main/java/net/sparklypower/sparklypaper/event/inventory/InventoryPreMoveItemEvent.java b/sparklypaper-api/src/main/java/net/sparklypower/sparklypaper/event/inventory/InventoryPreMoveItemEvent.java new file mode 100644 index 0000000..22726df --- /dev/null +++ b/sparklypaper-api/src/main/java/net/sparklypower/sparklypaper/event/inventory/InventoryPreMoveItemEvent.java @@ -0,0 +1,85 @@ +package net.sparklypower.sparklypaper.event.inventory; + +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.inventory.Inventory; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +/** + * Called when some entity or block (e.g. hopper) tries to move items directly + * from one inventory to another. + *

+ * This event is called before InventoryMoveItemEvent, and is called before the + * item within the container is modified to match the pull/push stack count. + */ +public class InventoryPreMoveItemEvent extends Event implements Cancellable { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final Inventory sourceInventory; + private final Inventory destinationInventory; + private final boolean didSourceInitiate; + + private boolean cancelled; + + @ApiStatus.Internal + public InventoryPreMoveItemEvent(@NotNull final Inventory sourceInventory, @NotNull final Inventory destinationInventory, final boolean didSourceInitiate) { + this.sourceInventory = sourceInventory; + this.destinationInventory = destinationInventory; + this.didSourceInitiate = didSourceInitiate; + } + + /** + * Gets the Inventory that the ItemStack is being taken from + * + * @return Inventory that the ItemStack is being taken from + */ + @NotNull + public Inventory getSource() { + return this.sourceInventory; + } + + /** + * Gets the Inventory that the ItemStack is being put into + * + * @return Inventory that the ItemStack is being put into + */ + @NotNull + public Inventory getDestination() { + return this.destinationInventory; + } + + /** + * Gets the Inventory that initiated the transfer. This will always be + * either the destination or source Inventory. + * + * @return Inventory that initiated the transfer + */ + @NotNull + public Inventory getInitiator() { + return this.didSourceInitiate ? this.sourceInventory : this.destinationInventory; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } + + @NotNull + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + + @NotNull + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } +} diff --git a/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch b/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch index 1199222..22f4ef4 100644 --- a/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch +++ b/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch @@ -1,5 +1,69 @@ --- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java +@@ -228,7 +_,15 @@ + for (int i = 0; i < hopper.getContainerSize(); ++i) { + final ItemStack item = hopper.getItem(i); + if (!item.isEmpty()) { ++ // SparklyPaper start - InventoryPreMoveItemEvent ++ if (!foundItem) { ++ // Only call it once per push, instead of per item ++ if (!callPushPreMoveEvent(destination, hopper)) ++ return false; ++ } ++ // SparklyPaper end + foundItem = true; ++ + ItemStack origItemStack = item; + ItemStack movedItem = origItemStack; + +@@ -268,6 +_,10 @@ + } + + private static boolean hopperPull(final Level level, final Hopper hopper, final Container container, ItemStack origItemStack, final int i) { ++ // SparklyPaper start - InventoryPreMoveItemEvent ++ if (!callPullPreMoveEvent(hopper, container)) ++ return true; ++ // SparklyPaper end + ItemStack movedItem = origItemStack; + final int originalItemCount = origItemStack.getCount(); + final int movedItemCount = Math.min(level.spigotConfig.hopperAmount, originalItemCount); +@@ -357,6 +_,36 @@ + } + } + ++ // SparklyPaper start - InventoryPreMoveItemEvent ++ private static boolean callPushPreMoveEvent(Container destination, HopperBlockEntity hopper) { ++ final org.bukkit.inventory.Inventory destinationInventory = getInventory(destination); ++ final net.sparklypower.sparklypaper.event.inventory.InventoryPreMoveItemEvent event = new net.sparklypower.sparklypaper.event.inventory.InventoryPreMoveItemEvent( ++ hopper.getOwner(false).getInventory(), ++ destinationInventory, ++ true ++ ); ++ final boolean result = event.callEvent(); ++ if (!result) { ++ applyCooldown(hopper); ++ } ++ ++ return result; ++ } ++ ++ private static boolean callPullPreMoveEvent(final Hopper hopper, final Container container) { ++ final org.bukkit.inventory.Inventory sourceInventory = getInventory(container); ++ final org.bukkit.inventory.Inventory destination = getInventory(hopper); ++ ++ // Mirror is safe as no plugins ever use this item ++ final net.sparklypower.sparklypaper.event.inventory.InventoryPreMoveItemEvent event = new net.sparklypower.sparklypaper.event.inventory.InventoryPreMoveItemEvent(sourceInventory, destination, false); ++ final boolean result = event.callEvent(); ++ if (!result) ++ applyCooldown(hopper); ++ ++ return result; ++ } ++ // SparklyPaper end ++ + private static org.bukkit.inventory.Inventory getInventory(final Container container) { + final org.bukkit.inventory.Inventory sourceInventory; + if (container instanceof net.minecraft.world.CompoundContainer compoundContainer) { @@ -424,6 +_,7 @@ } else { Direction opposite = blockEntity.facing.getOpposite();