diff --git a/Spigot-Server-Patches/Optimize-Hoppers.patch b/Spigot-Server-Patches/Optimize-Hoppers.patch index 4c91b1abd5..9bed81874a 100644 --- a/Spigot-Server-Patches/Optimize-Hoppers.patch +++ b/Spigot-Server-Patches/Optimize-Hoppers.patch @@ -121,9 +121,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + skipPushModeEventFire = skipHopperEvents; + boolean foundItem = false; + for (int i = 0; i < this.getSize(); ++i) { -+ if (!this.getItem(i).isEmpty()) { ++ ItemStack item = this.getItem(i); ++ if (!item.isEmpty()) { + foundItem = true; -+ ItemStack origItemStack = this.getItem(i); ++ ItemStack origItemStack = item; + ItemStack itemstack = origItemStack; + + final int origCount = origItemStack.getCount(); @@ -160,8 +161,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return false; + } + -+ private static boolean hopperPull(IHopper ihopper, IInventory iinventory, int i) { -+ ItemStack origItemStack = iinventory.getItem(i); ++ private static boolean hopperPull(IHopper ihopper, IInventory iinventory, ItemStack origItemStack, int i) { + ItemStack itemstack = origItemStack; + final int origCount = origItemStack.getCount(); + final World world = ihopper.getWorld(); @@ -287,18 +287,95 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } @@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + return iinventory instanceof IWorldInventory ? IntStream.of(((IWorldInventory) iinventory).getSlotsForFace(enumdirection)) : IntStream.range(0, iinventory.getSize()); + } + +- private boolean b(IInventory iinventory, EnumDirection enumdirection) { +- return a(iinventory, enumdirection).allMatch((i) -> { +- ItemStack itemstack = iinventory.getItem(i); ++ private static boolean allMatch(IInventory iinventory, EnumDirection enumdirection, java.util.function.BiPredicate<ItemStack, Integer> test) { ++ if (iinventory instanceof IWorldInventory) { ++ for (int i : ((IWorldInventory) iinventory).getSlotsForFace(enumdirection)) { ++ if (!test.test(iinventory.getItem(i), i)) { ++ return false; ++ } ++ } ++ } else { ++ int size = iinventory.getSize(); ++ for (int i = 0; i < size; i++) { ++ if (!test.test(iinventory.getItem(i), i)) { ++ return false; ++ } ++ } ++ } ++ return true; ++ } + +- return itemstack.getCount() >= itemstack.getMaxStackSize(); +- }); ++ private static boolean anyMatch(IInventory iinventory, EnumDirection enumdirection, java.util.function.BiPredicate<ItemStack, Integer> test) { ++ if (iinventory instanceof IWorldInventory) { ++ for (int i : ((IWorldInventory) iinventory).getSlotsForFace(enumdirection)) { ++ if (test.test(iinventory.getItem(i), i)) { ++ return true; ++ } ++ } ++ } else { ++ int size = iinventory.getSize(); ++ for (int i = 0; i < size; i++) { ++ if (test.test(iinventory.getItem(i), i)) { ++ return true; ++ } ++ } ++ } ++ return true; ++ } ++ private static final java.util.function.BiPredicate<ItemStack, Integer> STACK_SIZE_TEST = (itemstack, i) -> itemstack.getCount() >= itemstack.getMaxStackSize(); ++ private static final java.util.function.BiPredicate<ItemStack, Integer> IS_EMPTY_TEST = (itemstack, i) -> itemstack.isEmpty(); ++ ++ // Paper end ++ ++ private boolean b(IInventory iinventory, EnumDirection enumdirection) { ++ // Paper start - no streams ++ return allMatch(iinventory, enumdirection, STACK_SIZE_TEST); ++ // Paper end + } + + private static boolean c(IInventory iinventory, EnumDirection enumdirection) { +- return a(iinventory, enumdirection).allMatch((i) -> { +- return iinventory.getItem(i).isEmpty(); +- }); ++ return allMatch(iinventory, enumdirection, IS_EMPTY_TEST); + } + + public static boolean a(IHopper ihopper) { +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + if (iinventory != null) { EnumDirection enumdirection = EnumDirection.DOWN; - return c(iinventory, enumdirection) ? false : a(iinventory, enumdirection).anyMatch((i) -> { -+ skipPullModeEventFire = skipHopperEvents; // Paper - return a(ihopper, iinventory, i, enumdirection); +- return c(iinventory, enumdirection) ? false : a(iinventory, enumdirection).anyMatch((i) -> { +- return a(ihopper, iinventory, i, enumdirection); ++ // Paper start - optimize hoppers and remove streams ++ skipPullModeEventFire = skipHopperEvents; ++ return !c(iinventory, enumdirection) && anyMatch(iinventory, enumdirection, (item, i) -> { ++ // Logic copied from below to avoid extra getItem calls ++ if (!item.isEmpty() && canTakeItem(iinventory, item, i, enumdirection)) { ++ return hopperPull(ihopper, iinventory, item, i); ++ } else { ++ return false; ++ } }); ++ // Paper end } else { + Iterator iterator = c(ihopper).iterator(); + @@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + private static boolean a(IHopper ihopper, IInventory iinventory, int i, EnumDirection enumdirection) { ItemStack itemstack = iinventory.getItem(i); - if (!itemstack.isEmpty() && b(iinventory, itemstack, i, enumdirection)) { -+ return hopperPull(ihopper, iinventory, i); /* // Paper - disable rest +- if (!itemstack.isEmpty() && b(iinventory, itemstack, i, enumdirection)) { ++ if (!itemstack.isEmpty() && b(iinventory, itemstack, i, enumdirection)) { // If this logic changes, update above. this is left inused incase reflective plugins ++ return hopperPull(ihopper, iinventory, itemstack, 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 @@ -320,6 +397,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 entityitem.world.getServer().getPluginManager().callEvent(event); if (event.isCancelled()) { return false; +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + return !iinventory.b(i, itemstack) ? false : !(iinventory instanceof IWorldInventory) || ((IWorldInventory) iinventory).canPlaceItemThroughFace(i, itemstack, enumdirection); + } + ++ private static boolean canTakeItem(IInventory iinventory, ItemStack itemstack, int i, EnumDirection enumdirection) { return b(iinventory, itemstack, i, enumdirection); } // Paper - OBFHELPER + private static boolean b(IInventory iinventory, ItemStack itemstack, int i, EnumDirection enumdirection) { + return !(iinventory instanceof IWorldInventory) || ((IWorldInventory) iinventory).canTakeItemThroughFace(i, itemstack, enumdirection); + } @@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi boolean flag1 = iinventory1.isEmpty(); @@ -369,6 +454,32 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 List<Entity> list = world.getEntities((Entity) null, new AxisAlignedBB(d0 - 0.5D, d1 - 0.5D, d2 - 0.5D, d0 + 0.5D, d1 + 0.5D, d2 + 0.5D), IEntitySelector.d); if (!list.isEmpty()) { +diff --git a/src/main/java/net/minecraft/server/TileEntityLootable.java b/src/main/java/net/minecraft/server/TileEntityLootable.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/TileEntityLootable.java ++++ b/src/main/java/net/minecraft/server/TileEntityLootable.java +@@ -0,0 +0,0 @@ public abstract class TileEntityLootable extends TileEntityContainer { + @Override + public boolean isEmpty() { + this.d((EntityHuman) null); +- return this.f().stream().allMatch(ItemStack::isEmpty); ++ // Paper start ++ for (ItemStack itemStack : this.f()) { ++ if (!itemStack.isEmpty()) { ++ return false; ++ } ++ } ++ // Paper end ++ return true; + } + + @Override + public ItemStack getItem(int i) { +- this.d((EntityHuman) null); ++ if (i == 0) this.d((EntityHuman) null); // Paper + return (ItemStack) this.f().get(i); + } + diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/World.java