From 3b93c5b112ea1afe2eebe45c89895753303b72aa Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Fri, 13 Dec 2019 21:31:04 +0000 Subject: [PATCH] Drop fix zero-tick farms (Fixes #2736) Fixed by mojang in 1.15, farm blocks are no longer in the next tick list Also, add hopper optimization patch to the removed folder --- ...-161754.patch => 0403-Fix-MC-161754.patch} | 2 +- ...ro-tick-instant-grow-farms-MC-113809.patch | 99 ------ ...e-improvement-for-Chunk.getEntities.patch} | 2 +- ...anging-entities-that-are-not-ItemFr.patch} | 2 +- ...06-Expose-the-internal-current-tick.patch} | 2 +- ...sneak-when-changing-worlds-MC-10657.patch} | 2 +- ...-option-to-disable-pillager-patrols.patch} | 6 +- ...r-when-player-hand-set-to-empty-typ.patch} | 2 +- removed/1.15/0281-Optimize-Hoppers.patch | 308 ++++++++++++++++++ 9 files changed, 317 insertions(+), 108 deletions(-) rename Spigot-Server-Patches/{0404-Fix-MC-161754.patch => 0403-Fix-MC-161754.patch} (94%) delete mode 100644 Spigot-Server-Patches/0403-Fix-zero-tick-instant-grow-farms-MC-113809.patch rename Spigot-Server-Patches/{0405-Performance-improvement-for-Chunk.getEntities.patch => 0404-Performance-improvement-for-Chunk.getEntities.patch} (96%) rename Spigot-Server-Patches/{0406-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch => 0405-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch} (96%) rename Spigot-Server-Patches/{0407-Expose-the-internal-current-tick.patch => 0406-Expose-the-internal-current-tick.patch} (92%) rename Spigot-Server-Patches/{0408-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch => 0407-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch} (96%) rename Spigot-Server-Patches/{0409-Add-option-to-disable-pillager-patrols.patch => 0408-Add-option-to-disable-pillager-patrols.patch} (90%) rename Spigot-Server-Patches/{0410-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch => 0409-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch} (96%) create mode 100644 removed/1.15/0281-Optimize-Hoppers.patch diff --git a/Spigot-Server-Patches/0404-Fix-MC-161754.patch b/Spigot-Server-Patches/0403-Fix-MC-161754.patch similarity index 94% rename from Spigot-Server-Patches/0404-Fix-MC-161754.patch rename to Spigot-Server-Patches/0403-Fix-MC-161754.patch index a4a9a57626..b5907a403f 100644 --- a/Spigot-Server-Patches/0404-Fix-MC-161754.patch +++ b/Spigot-Server-Patches/0403-Fix-MC-161754.patch @@ -1,4 +1,4 @@ -From 540b6207ac043f0b18905843b06ac9b2f31c6ef7 Mon Sep 17 00:00:00 2001 +From 65125b3e106030630c0b1703e00c1f1c3936d797 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Tue, 24 Sep 2019 16:03:00 -0700 Subject: [PATCH] Fix MC-161754 diff --git a/Spigot-Server-Patches/0403-Fix-zero-tick-instant-grow-farms-MC-113809.patch b/Spigot-Server-Patches/0403-Fix-zero-tick-instant-grow-farms-MC-113809.patch deleted file mode 100644 index 688c62789d..0000000000 --- a/Spigot-Server-Patches/0403-Fix-zero-tick-instant-grow-farms-MC-113809.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 7e22aa26cdf426fb9dd1094509e21ace67d1cd30 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Sun, 15 Sep 2019 11:32:32 -0500 -Subject: [PATCH] Fix zero-tick instant grow farms MC-113809 - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 33e251c87..c0af1aaf3 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -564,6 +564,11 @@ public class PaperWorldConfig { - disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); - } - -+ public boolean fixZeroTickInstantGrowFarms = true; -+ private void fixZeroTickInstantGrowFarms() { -+ fixZeroTickInstantGrowFarms = getBoolean("fix-zero-tick-instant-grow-farms", fixZeroTickInstantGrowFarms); -+ } -+ - public boolean altItemDespawnRateEnabled; - public Map altItemDespawnRateMap; - private void altItemDespawnRate() { -diff --git a/src/main/java/net/minecraft/server/Block.java b/src/main/java/net/minecraft/server/Block.java -index 46490a943..54a61283e 100644 ---- a/src/main/java/net/minecraft/server/Block.java -+++ b/src/main/java/net/minecraft/server/Block.java -@@ -46,6 +46,7 @@ public class Block implements IMaterial { - private final float g; - protected final BlockStateList blockStateList; - private IBlockData blockData; -+ public boolean randomTick = false; // Paper - fix MC-113809 - protected final boolean v; - private final boolean i; - private final boolean j; -diff --git a/src/main/java/net/minecraft/server/BlockBamboo.java b/src/main/java/net/minecraft/server/BlockBamboo.java -index c482aad3e..02c548dd9 100644 ---- a/src/main/java/net/minecraft/server/BlockBamboo.java -+++ b/src/main/java/net/minecraft/server/BlockBamboo.java -@@ -85,6 +85,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - if (!iblockdata.canPlace(worldserver, blockposition)) { - worldserver.b(blockposition, true); - } else if ((Integer) iblockdata.get(BlockBamboo.f) == 0) { -+ if (worldserver.paperConfig.fixZeroTickInstantGrowFarms && !randomTick) return; // Paper - fix MC-113809 - if (random.nextInt(Math.max(1, (int) (100.0F / worldserver.spigotConfig.bambooModifier) * 3)) == 0 && worldserver.isEmpty(blockposition.up()) && worldserver.getLightLevel(blockposition.up(), 0) >= 9) { // Spigot - int i = this.b(worldserver, blockposition) + 1; - -diff --git a/src/main/java/net/minecraft/server/BlockCactus.java b/src/main/java/net/minecraft/server/BlockCactus.java -index e0974e256..3524fcb92 100644 ---- a/src/main/java/net/minecraft/server/BlockCactus.java -+++ b/src/main/java/net/minecraft/server/BlockCactus.java -@@ -21,6 +21,7 @@ public class BlockCactus extends Block { - if (!iblockdata.canPlace(worldserver, blockposition)) { - worldserver.b(blockposition, true); - } else { -+ if (worldserver.paperConfig.fixZeroTickInstantGrowFarms && !randomTick) return; // Paper - fix MC-113809 - BlockPosition blockposition1 = blockposition.up(); - - if (worldserver.isEmpty(blockposition1)) { -diff --git a/src/main/java/net/minecraft/server/BlockChorusFlower.java b/src/main/java/net/minecraft/server/BlockChorusFlower.java -index d70b52cad..b624cf380 100644 ---- a/src/main/java/net/minecraft/server/BlockChorusFlower.java -+++ b/src/main/java/net/minecraft/server/BlockChorusFlower.java -@@ -22,6 +22,7 @@ public class BlockChorusFlower extends Block { - if (!iblockdata.canPlace(worldserver, blockposition)) { - worldserver.b(blockposition, true); - } else { -+ if (worldserver.paperConfig.fixZeroTickInstantGrowFarms && !randomTick) return; // Paper - fix MC-113809 - BlockPosition blockposition1 = blockposition.up(); - - if (worldserver.isEmpty(blockposition1) && blockposition1.getY() < 256) { -diff --git a/src/main/java/net/minecraft/server/BlockReed.java b/src/main/java/net/minecraft/server/BlockReed.java -index 55b07444e..3bc3c5aa2 100644 ---- a/src/main/java/net/minecraft/server/BlockReed.java -+++ b/src/main/java/net/minecraft/server/BlockReed.java -@@ -23,6 +23,7 @@ public class BlockReed extends Block { - if (!iblockdata.canPlace(worldserver, blockposition)) { - worldserver.b(blockposition, true); - } else if (worldserver.isEmpty(blockposition.up())) { -+ if (worldserver.paperConfig.fixZeroTickInstantGrowFarms && !randomTick) return; // Paper - fix MC-113809 - int i; - - for (i = 1; worldserver.getType(blockposition.down(i)).getBlock() == this; ++i) { -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index 4da34b6dd..722384a91 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -678,7 +678,9 @@ public class WorldServer extends World { - IBlockData iblockdata = this.getType(nextticklistentry.a); - - if (iblockdata.getBlock() == nextticklistentry.b()) { -+ iblockdata.getBlock().randomTick = true; // Paper - fix MC-113809 - iblockdata.a(this, nextticklistentry.a, this.random); -+ iblockdata.getBlock().randomTick = false; // Paper - fix MC-113809 - } - - } --- -2.24.1 - diff --git a/Spigot-Server-Patches/0405-Performance-improvement-for-Chunk.getEntities.patch b/Spigot-Server-Patches/0404-Performance-improvement-for-Chunk.getEntities.patch similarity index 96% rename from Spigot-Server-Patches/0405-Performance-improvement-for-Chunk.getEntities.patch rename to Spigot-Server-Patches/0404-Performance-improvement-for-Chunk.getEntities.patch index 671067b614..67ad5f58dd 100644 --- a/Spigot-Server-Patches/0405-Performance-improvement-for-Chunk.getEntities.patch +++ b/Spigot-Server-Patches/0404-Performance-improvement-for-Chunk.getEntities.patch @@ -1,4 +1,4 @@ -From 6c486f323f302b16d1edbbd44981886a0b3f8668 Mon Sep 17 00:00:00 2001 +From 38866c8296404908c68b70f267d8451f786ac6c8 Mon Sep 17 00:00:00 2001 From: wea_ondara Date: Thu, 10 Oct 2019 11:29:42 +0200 Subject: [PATCH] Performance improvement for Chunk.getEntities diff --git a/Spigot-Server-Patches/0406-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch b/Spigot-Server-Patches/0405-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch similarity index 96% rename from Spigot-Server-Patches/0406-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch rename to Spigot-Server-Patches/0405-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch index 81985697c2..38604dbeba 100644 --- a/Spigot-Server-Patches/0406-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch +++ b/Spigot-Server-Patches/0405-Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch @@ -1,4 +1,4 @@ -From 1b6b2b8c524a8742957d2740a6c0415f19ce2dc5 Mon Sep 17 00:00:00 2001 +From b33a5cb73492f271d67424568394978dc3f40c26 Mon Sep 17 00:00:00 2001 From: MisterErwin Date: Wed, 30 Oct 2019 16:57:54 +0100 Subject: [PATCH] Fix spawning of hanging entities that are not ItemFrames and diff --git a/Spigot-Server-Patches/0407-Expose-the-internal-current-tick.patch b/Spigot-Server-Patches/0406-Expose-the-internal-current-tick.patch similarity index 92% rename from Spigot-Server-Patches/0407-Expose-the-internal-current-tick.patch rename to Spigot-Server-Patches/0406-Expose-the-internal-current-tick.patch index 3454ec357c..fa93dc1d31 100644 --- a/Spigot-Server-Patches/0407-Expose-the-internal-current-tick.patch +++ b/Spigot-Server-Patches/0406-Expose-the-internal-current-tick.patch @@ -1,4 +1,4 @@ -From 1bf364be98d7ded883550eeca361a4efc79238ed Mon Sep 17 00:00:00 2001 +From a78d4cc3de32d2fe41b7d1cfa8a213a429d4f000 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sat, 20 Apr 2019 19:47:34 -0500 Subject: [PATCH] Expose the internal current tick diff --git a/Spigot-Server-Patches/0408-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch b/Spigot-Server-Patches/0407-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch similarity index 96% rename from Spigot-Server-Patches/0408-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch rename to Spigot-Server-Patches/0407-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch index 61a7636d79..1436550572 100644 --- a/Spigot-Server-Patches/0408-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch +++ b/Spigot-Server-Patches/0407-Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch @@ -1,4 +1,4 @@ -From ecae0134303ae5583c8b982bcad6b2137f268252 Mon Sep 17 00:00:00 2001 +From 84478c066481a43f8bd96e877047ca0d4b52e9be Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Wed, 9 Oct 2019 21:51:43 -0500 Subject: [PATCH] Fix stuck in sneak when changing worlds (MC-10657) diff --git a/Spigot-Server-Patches/0409-Add-option-to-disable-pillager-patrols.patch b/Spigot-Server-Patches/0408-Add-option-to-disable-pillager-patrols.patch similarity index 90% rename from Spigot-Server-Patches/0409-Add-option-to-disable-pillager-patrols.patch rename to Spigot-Server-Patches/0408-Add-option-to-disable-pillager-patrols.patch index f0cd98d62d..25f9ebc935 100644 --- a/Spigot-Server-Patches/0409-Add-option-to-disable-pillager-patrols.patch +++ b/Spigot-Server-Patches/0408-Add-option-to-disable-pillager-patrols.patch @@ -1,14 +1,14 @@ -From 18bd737e8991b816105348051466a01efdbdbf35 Mon Sep 17 00:00:00 2001 +From fe96ecbaebd3330a84f5840bc0a87093d39a22c0 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Wed, 9 Oct 2019 21:46:15 -0500 Subject: [PATCH] Add option to disable pillager patrols diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index c0af1aaf3..dbc645ebb 100644 +index 33e251c87..79716faca 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -626,4 +626,9 @@ public class PaperWorldConfig { +@@ -621,4 +621,9 @@ public class PaperWorldConfig { private void generatorSettings() { generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); } diff --git a/Spigot-Server-Patches/0410-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch b/Spigot-Server-Patches/0409-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch similarity index 96% rename from Spigot-Server-Patches/0410-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch rename to Spigot-Server-Patches/0409-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch index a883d4e1ee..9e58986a84 100644 --- a/Spigot-Server-Patches/0410-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch +++ b/Spigot-Server-Patches/0409-Fix-AssertionError-when-player-hand-set-to-empty-typ.patch @@ -1,4 +1,4 @@ -From cb0fd78af1de7f392b3f0eb9806baca978e20b89 Mon Sep 17 00:00:00 2001 +From d40b72004ddb31eb29063f990162d63f39617f47 Mon Sep 17 00:00:00 2001 From: Lukasz Derlatka Date: Mon, 11 Nov 2019 16:08:13 +0100 Subject: [PATCH] Fix AssertionError when player hand set to empty type diff --git a/removed/1.15/0281-Optimize-Hoppers.patch b/removed/1.15/0281-Optimize-Hoppers.patch new file mode 100644 index 0000000000..a301f0aad4 --- /dev/null +++ b/removed/1.15/0281-Optimize-Hoppers.patch @@ -0,0 +1,308 @@ +From bd7c380b8e4238b100012405cf46a02a0e05990d Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 27 Apr 2016 22:09:52 -0400 +Subject: [PATCH] Optimize Hoppers + +* Removes unnecessary extra calls to .update() that are very expensive +* Lots of itemstack cloning removed. Only clone if the item is actually moved +* Return true when a plugin cancels inventory move item event instead of false, as false causes pulls to cycle through all items. + However, pushes do not exhibit the same behavior, so this is not something plugins could of been relying on. +* Add option (Default on) to cooldown hoppers when they fail to move an item due to full inventory +* Skip subsequent InventoryMoveItemEvents if a plugin does not use the item after first event fire for an iteration + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 42d14fac2..80d66c647 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -397,4 +397,13 @@ public class PaperWorldConfig { + this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); + log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); + } ++ ++ public boolean cooldownHopperWhenFull = true; ++ public boolean disableHopperMoveEvents = false; ++ private void hopperOptimizations() { ++ cooldownHopperWhenFull = getBoolean("hopper.cooldown-when-full", cooldownHopperWhenFull); ++ log("Cooldown Hoppers when Full: " + (cooldownHopperWhenFull ? "enabled" : "disabled")); ++ disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); ++ log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); ++ } + } +diff --git a/src/main/java/net/minecraft/server/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java +index 33d9cac4d..627fa465c 100644 +--- a/src/main/java/net/minecraft/server/ItemStack.java ++++ b/src/main/java/net/minecraft/server/ItemStack.java +@@ -481,11 +481,12 @@ public final class ItemStack { + return this.getItem().a(this, entityhuman, entityliving, enumhand); + } + +- public ItemStack cloneItemStack() { ++ public ItemStack cloneItemStack() { return cloneItemStack(false); } // Paper ++ public ItemStack cloneItemStack(boolean origItem) { // Paper + if (this.isEmpty()) { + return ItemStack.a; + } else { +- ItemStack itemstack = new ItemStack(this.getItem(), this.count); ++ ItemStack itemstack = new ItemStack(origItem ? this.item : this.getItem(), this.count); // Paper + + itemstack.d(this.C()); + if (this.tag != null) { +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index dd2d8712e..206a4ad64 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1168,6 +1168,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper ++ TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper + if (true || worldserver.worldProvider.getDimensionManager() == DimensionManager.OVERWORLD || this.getAllowNether()) { // CraftBukkit + this.methodProfiler.a(() -> { + return worldserver.getWorldData().getName() + " " + IRegistry.DIMENSION_TYPE.getKey(worldserver.worldProvider.getDimensionManager()); +diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java +index 958279249..a8e64dfda 100644 +--- a/src/main/java/net/minecraft/server/TileEntity.java ++++ b/src/main/java/net/minecraft/server/TileEntity.java +@@ -62,6 +62,7 @@ public abstract class TileEntity implements KeyedObject { // Paper + public void setCurrentChunk(Chunk chunk) { + this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; + } ++ static boolean IGNORE_TILE_UPDATES = false; + // Paper end + + @Nullable +@@ -140,6 +141,7 @@ public abstract class TileEntity implements KeyedObject { // Paper + + public void update() { + if (this.world != null) { ++ if (IGNORE_TILE_UPDATES) return; // Paper + this.c = this.world.getType(this.position); + this.world.b(this.position, this); + if (!this.c.isAir()) { +diff --git a/src/main/java/net/minecraft/server/TileEntityHopper.java b/src/main/java/net/minecraft/server/TileEntityHopper.java +index e08faf538..e7cf14d10 100644 +--- a/src/main/java/net/minecraft/server/TileEntityHopper.java ++++ b/src/main/java/net/minecraft/server/TileEntityHopper.java +@@ -168,6 +168,158 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + return false; + } + ++ // Paper start - Optimize Hoppers ++ private static boolean skipPullModeEventFire = false; ++ private static boolean skipPushModeEventFire = false; ++ static boolean skipHopperEvents = false; ++ ++ private boolean hopperPush(IInventory iinventory, EnumDirection enumdirection) { ++ skipPushModeEventFire = skipHopperEvents; ++ boolean foundItem = false; ++ for (int i = 0; i < this.getSize(); ++i) { ++ if (!this.getItem(i).isEmpty()) { ++ foundItem = true; ++ ItemStack origItemStack = this.getItem(i); ++ ItemStack itemstack = origItemStack; ++ ++ final int origCount = origItemStack.getCount(); ++ final int moved = Math.min(world.spigotConfig.hopperAmount, origCount); ++ origItemStack.setCount(moved); ++ ++ // We only need to fire the event once to give protection plugins a chance to cancel this event ++ // Because nothing uses getItem, every event call should end up the same result. ++ if (!skipPushModeEventFire) { ++ itemstack = callPushMoveEvent(iinventory, itemstack); ++ if (itemstack == null) { // cancelled ++ origItemStack.setCount(origCount); ++ return false; ++ } ++ } ++ final ItemStack itemstack2 = addItem(this, iinventory, itemstack, enumdirection); ++ final int remaining = itemstack2.getCount(); ++ if (remaining != moved) { ++ origItemStack = origItemStack.cloneItemStack(true); ++ if (!origItemStack.isEmpty()) { ++ origItemStack.setCount(origCount - moved + remaining); ++ } ++ this.setItem(i, origItemStack); ++ iinventory.update(); ++ return true; ++ } ++ origItemStack.setCount(origCount); ++ } ++ } ++ if (foundItem && world.paperConfig.cooldownHopperWhenFull) { // Inventory was full - cooldown ++ this.setCooldown(world.spigotConfig.hopperTransfer); ++ } ++ return false; ++ } ++ ++ private static boolean hopperPull(IHopper ihopper, IInventory iinventory, int i) { ++ ItemStack origItemStack = iinventory.getItem(i); ++ ItemStack itemstack = origItemStack; ++ final int origCount = origItemStack.getCount(); ++ final World world = ihopper.getWorld(); ++ final int moved = Math.min(world.spigotConfig.hopperAmount, origCount); ++ itemstack.setCount(moved); ++ ++ if (!skipPullModeEventFire) { ++ itemstack = callPullMoveEvent(ihopper, iinventory, itemstack); ++ if (itemstack == null) { // cancelled ++ origItemStack.setCount(origCount); ++ // Drastically improve performance by returning true. ++ // No plugin could of relied on the behavior of false as the other call ++ // site for IMIE did not exhibit the same behavior ++ return true; ++ } ++ } ++ ++ final ItemStack itemstack2 = addItem(iinventory, ihopper, itemstack, null); ++ final int remaining = itemstack2.getCount(); ++ if (remaining != moved) { ++ origItemStack = origItemStack.cloneItemStack(true); ++ if (!origItemStack.isEmpty()) { ++ origItemStack.setCount(origCount - moved + remaining); ++ } ++ IGNORE_TILE_UPDATES = true; ++ iinventory.setItem(i, origItemStack); ++ IGNORE_TILE_UPDATES = false; ++ iinventory.update(); ++ return true; ++ } ++ origItemStack.setCount(origCount); ++ ++ if (world.paperConfig.cooldownHopperWhenFull) { ++ cooldownHopper(ihopper); ++ } ++ ++ return false; ++ } ++ ++ private ItemStack callPushMoveEvent(IInventory iinventory, ItemStack itemstack) { ++ Inventory destinationInventory = getInventory(iinventory); ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner(false).getInventory(), ++ CraftItemStack.asCraftMirror(itemstack), destinationInventory, true); ++ boolean result = event.callEvent(); ++ if (!event.calledGetItem && !event.calledSetItem) { ++ skipPushModeEventFire = true; ++ } ++ if (!result) { ++ cooldownHopper(this); ++ return null; ++ } ++ ++ if (event.calledSetItem) { ++ return CraftItemStack.asNMSCopy(event.getItem()); ++ } else { ++ return itemstack; ++ } ++ } ++ ++ private static ItemStack callPullMoveEvent(IHopper hopper, IInventory iinventory, ItemStack itemstack) { ++ Inventory sourceInventory = getInventory(iinventory); ++ Inventory destination = getInventory(hopper); ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, ++ // Mirror is safe as we no plugins ever use this item ++ CraftItemStack.asCraftMirror(itemstack), destination, false); ++ boolean result = event.callEvent(); ++ if (!event.calledGetItem && !event.calledSetItem) { ++ skipPullModeEventFire = true; ++ } ++ if (!result) { ++ cooldownHopper(hopper); ++ return null; ++ } ++ ++ if (event.calledSetItem) { ++ return CraftItemStack.asNMSCopy(event.getItem()); ++ } else { ++ return itemstack; ++ } ++ } ++ ++ private static Inventory getInventory(IInventory iinventory) { ++ Inventory sourceInventory;// Have to special case large chests as they work oddly ++ if (iinventory instanceof InventoryLargeChest) { ++ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); ++ } else if (iinventory instanceof TileEntity) { ++ sourceInventory = ((TileEntity) iinventory).getOwner(false).getInventory(); ++ } else { ++ sourceInventory = iinventory.getOwner().getInventory(); ++ } ++ return sourceInventory; ++ } ++ ++ private static void cooldownHopper(IHopper hopper) { ++ if (hopper instanceof TileEntityHopper) { ++ ((TileEntityHopper) hopper).setCooldown(hopper.getWorld().spigotConfig.hopperTransfer); ++ } else if (hopper instanceof EntityMinecartHopper) { ++ ((EntityMinecartHopper) hopper).setCooldown(hopper.getWorld().spigotConfig.hopperTransfer / 2); ++ } ++ } ++ // Paper end ++ + private boolean j() { + IInventory iinventory = this.k(); + +@@ -179,6 +331,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + if (this.b(iinventory, enumdirection)) { + return false; + } else { ++ return hopperPush(iinventory, enumdirection); /* // Paper - disable rest + for (int i = 0; i < this.getSize(); ++i) { + if (!this.getItem(i).isEmpty()) { + ItemStack itemstack = this.getItem(i).cloneItemStack(); +@@ -216,7 +369,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + } + +- return false; ++ return false;*/ // Paper - end commenting out replaced block for Hopper Optimizations + } + } + } +@@ -246,6 +399,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + EnumDirection enumdirection = EnumDirection.DOWN; + + return c(iinventory, enumdirection) ? false : a(iinventory, enumdirection).anyMatch((i) -> { ++ skipPullModeEventFire = skipHopperEvents; // Paper + return a(ihopper, iinventory, i, enumdirection); + }); + } else { +@@ -269,6 +423,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + ItemStack itemstack = iinventory.getItem(i); + + if (!itemstack.isEmpty() && b(iinventory, itemstack, i, enumdirection)) { ++ return hopperPull(ihopper, iinventory, i); /* // Paper - disable rest + ItemStack itemstack1 = itemstack.cloneItemStack(); + // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.splitStack(i, 1), (EnumDirection) null); + // CraftBukkit start - Call event on collection of items from inventories into the hopper +@@ -305,7 +460,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + + itemstack1.subtract(origCount - itemstack2.getCount()); // Spigot +- iinventory.setItem(i, itemstack1); ++ iinventory.setItem(i, itemstack1);*/ // Paper - end commenting out replaced block for Hopper Optimizations + } + + return false; +@@ -314,7 +469,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + public static boolean a(IInventory iinventory, EntityItem entityitem) { + boolean flag = false; + // CraftBukkit start +- InventoryPickupItemEvent event = new InventoryPickupItemEvent(iinventory.getOwner().getInventory(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ InventoryPickupItemEvent event = new InventoryPickupItemEvent(getInventory(iinventory), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); // Paper - use getInventory() to avoid snapshot creation + entityitem.world.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return false; +@@ -368,7 +523,9 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + boolean flag1 = iinventory1.isNotEmpty(); + + if (itemstack1.isEmpty()) { ++ IGNORE_TILE_UPDATES = true; // Paper + iinventory1.setItem(i, itemstack); ++ IGNORE_TILE_UPDATES = false; // Paper + itemstack = ItemStack.a; + flag = true; + } else if (a(itemstack1, itemstack)) { +-- +2.24.1 +