2020-05-06 09:48:49 +00:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2019-12-13 22:48:40 +00:00
From: Aikar <aikar@aikar.co>
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
2020-04-24 07:01:17 +00:00
* Don't check for Entities with Inventories if the block above us is also occluding (not just Inventoried)
* Remove Streams from Item Suck In and restore restore 1.12 AABB checks which is simpler and no voxel allocations (was doing TWO Item Suck ins)
2019-12-13 22:48:40 +00:00
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
2021-01-11 01:44:06 +00:00
index edda2121f8c1046478beaa77030ebb36d403b334..7fbd501d70dccf869a4454e2789a5d68f2e15754 100644
2019-12-13 22:48:40 +00:00
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
2021-01-11 01:44:06 +00:00
@@ -585,4 +585,13 @@ public class PaperWorldConfig {
2019-12-22 02:28:35 +00:00
private void entitiesTargetWithFollowRange() {
entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange);
2019-12-13 22:48:40 +00:00
}
+
+ 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"));
+ }
}
2021-03-16 07:19:45 +00:00
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index ede36b4c4d806bee62fd46d2e1ba595c9cd515ce..ef6559190c336822149560d2f2748b2c90dfad86 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1350,6 +1350,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
while (iterator.hasNext()) {
WorldServer worldserver = (WorldServer) iterator.next();
worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper
+ TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper
2020-04-24 07:01:17 +00:00
2021-03-16 07:19:45 +00:00
this.methodProfiler.a(() -> {
return worldserver + " " + worldserver.getDimensionKey().a();
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index 5da20483ed352ac6d9695287f840ed643a2bf302..8a2ff2ef17aba806a63be3aaebfa779dac96831d 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -540,11 +540,12 @@ public final class ItemStack {
2019-12-13 22:48:40 +00:00
return this.getItem().a(this, entityhuman, entityliving, enumhand);
}
- public ItemStack cloneItemStack() {
2019-12-22 02:28:35 +00:00
- if (this.isEmpty()) {
2019-12-13 22:48:40 +00:00
+ public ItemStack cloneItemStack() { return cloneItemStack(false); } // Paper
+ public ItemStack cloneItemStack(boolean origItem) { // Paper
2019-12-22 02:28:35 +00:00
+ if (!origItem && this.isEmpty()) { // Paper
2020-06-25 23:38:24 +00:00
return ItemStack.b;
2019-12-13 22:48:40 +00:00
} else {
- ItemStack itemstack = new ItemStack(this.getItem(), this.count);
+ ItemStack itemstack = new ItemStack(origItem ? this.item : this.getItem(), this.count); // Paper
2020-06-25 23:38:24 +00:00
itemstack.d(this.D());
2019-12-13 22:48:40 +00:00
if (this.tag != null) {
2021-03-16 07:19:45 +00:00
diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java
2021-03-16 13:04:28 +00:00
index 6781b25cc8e15be2556bb1bb8dc8c18c106b40ec..d1738b57efd3f5e6c51603553a773173e4b09bb5 100644
2021-03-16 07:19:45 +00:00
--- a/src/main/java/net/minecraft/world/level/World.java
+++ b/src/main/java/net/minecraft/world/level/World.java
2021-03-16 13:04:28 +00:00
@@ -1162,8 +1162,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
2021-03-16 07:19:45 +00:00
return list;
}
2020-06-25 23:38:24 +00:00
2021-03-16 07:19:45 +00:00
- @Override
- public <T extends Entity> List<T> a(Class<? extends T> oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate<? super T> predicate) {
+ public <T extends Entity> List<T> getEntities(Class<? extends T> oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate<? super T> predicate) { return a(oclass, axisalignedbb, predicate); } // Paper - OBFHELPER
+ @Override public <T extends Entity> List<T> a(Class<? extends T> oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate<? super T> predicate) {
this.getMethodProfiler().c("getEntities");
int i = MathHelper.floor((axisalignedbb.minX - 2.0D) / 16.0D);
int j = MathHelper.f((axisalignedbb.maxX + 2.0D) / 16.0D);
diff --git a/src/main/java/net/minecraft/world/level/block/entity/IHopper.java b/src/main/java/net/minecraft/world/level/block/entity/IHopper.java
2021-03-16 13:04:28 +00:00
index d0943ae1f372784716195666212ff83e6ee4873e..1db7b7bfe98658d0b20800a4178556f8daaf881a 100644
2021-03-16 07:19:45 +00:00
--- a/src/main/java/net/minecraft/world/level/block/entity/IHopper.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/IHopper.java
2021-03-16 13:04:28 +00:00
@@ -1,6 +1,7 @@
package net.minecraft.world.level.block.entity;
import javax.annotation.Nullable;
+import net.minecraft.core.BlockPosition;
import net.minecraft.world.IInventory;
import net.minecraft.world.level.World;
import net.minecraft.world.level.block.Block;
@@ -17,12 +18,13 @@ public interface IHopper extends IInventory {
2021-03-16 07:19:45 +00:00
return IHopper.c;
}
- @Nullable
+ //@Nullable // Paper - it's annoying
World getWorld();
+ default BlockPosition getBlockPosition() { return new BlockPosition(getX(), getY(), getZ()); } // Paper
- double x();
+ double x(); default double getX() { return this.x(); } // Paper - OBFHELPER
- double z();
+ double z(); default double getY() { return this.z(); } // Paper - OBFHELPER
- double A();
+ double A(); default double getZ() { return this.A(); } // Paper - OBFHELPER
}
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java
2021-03-16 13:04:28 +00:00
index 3ff9e389fcf15044c2740fb884c9438428d7a681..9088fd324207f2abc9ba04cf510b519f4fbb8cc9 100644
2021-03-16 07:19:45 +00:00
--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java
2021-03-16 13:04:28 +00:00
@@ -77,6 +77,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { /
2019-12-13 22:48:40 +00:00
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
2021-03-16 13:04:28 +00:00
@@ -155,6 +156,7 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { /
2019-12-13 22:48:40 +00:00
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()) {
2021-03-16 07:19:45 +00:00
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java
index 5fe715e8dbe9d925170acce6e0f18312d9f998f2..66cbb46088c6938ebe1d3771b3312112dd1a7160 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java
@@ -196,6 +196,160 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
2019-12-13 22:48:40 +00:00
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) {
2020-05-11 07:42:32 +00:00
+ ItemStack item = this.getItem(i);
+ if (!item.isEmpty()) {
2019-12-13 22:48:40 +00:00
+ foundItem = true;
2020-05-11 07:42:32 +00:00
+ ItemStack origItemStack = item;
2019-12-13 22:48:40 +00:00
+ 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);
2019-12-22 02:28:35 +00:00
+ origItemStack.setCount(origCount);
2019-12-13 22:48:40 +00:00
+ 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;
+ }
+
2020-05-11 07:42:32 +00:00
+ private static boolean hopperPull(IHopper ihopper, IInventory iinventory, ItemStack origItemStack, int i) {
2019-12-13 22:48:40 +00:00
+ 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);
2019-12-22 02:28:35 +00:00
+ origItemStack.setCount(origCount);
2019-12-13 22:48:40 +00:00
+ 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
+
2020-06-25 23:38:24 +00:00
private boolean k() {
IInventory iinventory = this.l();
2019-12-13 22:48:40 +00:00
2021-03-16 07:19:45 +00:00
@@ -207,6 +361,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
2019-12-13 22:48:40 +00:00
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();
2021-03-16 07:19:45 +00:00
@@ -244,7 +399,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
2019-12-13 22:48:40 +00:00
}
}
- return false;
+ return false;*/ // Paper - end commenting out replaced block for Hopper Optimizations
}
}
}
2021-03-16 07:19:45 +00:00
@@ -253,18 +408,54 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
2020-05-11 07:42:32 +00:00
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) {
2021-03-16 07:19:45 +00:00
@@ -273,9 +464,17 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
2020-05-11 07:42:32 +00:00
if (iinventory != null) {
2019-12-13 22:48:40 +00:00
EnumDirection enumdirection = EnumDirection.DOWN;
2020-05-11 07:42:32 +00:00
- 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;
+ }
2019-12-13 22:48:40 +00:00
});
2020-05-11 07:42:32 +00:00
+ // Paper end
2019-12-13 22:48:40 +00:00
} else {
2020-05-11 07:42:32 +00:00
Iterator iterator = c(ihopper).iterator();
2021-03-16 07:19:45 +00:00
@@ -293,10 +492,11 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
2020-06-28 04:58:25 +00:00
}
}
- private static boolean a(IHopper ihopper, IInventory iinventory, int i, EnumDirection enumdirection) {
+ private static boolean a(IHopper ihopper, IInventory iinventory, int i, EnumDirection enumdirection) {// Paper - method unused as logic is inlined above
2019-12-13 22:48:40 +00:00
ItemStack itemstack = iinventory.getItem(i);
2020-05-11 07:42:32 +00:00
- 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
2019-12-13 22:48:40 +00:00
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
2021-03-16 07:19:45 +00:00
@@ -333,7 +533,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
2019-12-13 22:48:40 +00:00
}
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;
2021-03-16 07:19:45 +00:00
@@ -342,7 +542,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
2019-12-13 22:48:40 +00:00
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;
2021-03-16 07:19:45 +00:00
@@ -384,6 +584,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
2020-05-11 07:42:32 +00:00
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);
}
2021-03-16 07:19:45 +00:00
@@ -396,7 +597,9 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
2020-01-22 02:02:07 +00:00
boolean flag1 = iinventory1.isEmpty();
2019-12-13 22:48:40 +00:00
if (itemstack1.isEmpty()) {
+ IGNORE_TILE_UPDATES = true; // Paper
iinventory1.setItem(i, itemstack);
+ IGNORE_TILE_UPDATES = false; // Paper
2020-06-25 23:38:24 +00:00
itemstack = ItemStack.b;
2019-12-13 22:48:40 +00:00
flag = true;
} else if (a(itemstack1, itemstack)) {
2021-03-16 07:19:45 +00:00
@@ -447,18 +650,24 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
2020-04-24 07:01:17 +00:00
}
public static List<EntityItem> c(IHopper ihopper) {
2020-08-25 02:22:08 +00:00
- return (List) ihopper.aa_().d().stream().flatMap((axisalignedbb) -> {
2020-06-25 23:38:24 +00:00
- return ihopper.getWorld().a(EntityItem.class, axisalignedbb.d(ihopper.x() - 0.5D, ihopper.z() - 0.5D, ihopper.A() - 0.5D), IEntitySelector.a).stream();
2020-04-24 07:01:17 +00:00
- }).collect(Collectors.toList());
+ // Paper start - Optimize item suck in. remove streams, restore 1.12 checks. Seriously checking the bowl?!
+ World world = ihopper.getWorld();
+ double d0 = ihopper.getX();
+ double d1 = ihopper.getY();
+ double d2 = ihopper.getZ();
+ AxisAlignedBB bb = new AxisAlignedBB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D);
+ return world.getEntities(EntityItem.class, bb, Entity::isAlive);
+ // Paper end
}
@Nullable
public static IInventory b(World world, BlockPosition blockposition) {
- return a(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D);
+ return a(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, true); // Paper
}
@Nullable
- public static IInventory a(World world, double d0, double d1, double d2) {
+ public static IInventory a(World world, double d0, double d1, double d2) { return a(world, d0, d1, d2, false); } // Paper - overload to default false
+ public static IInventory a(World world, double d0, double d1, double d2, boolean optimizeEntities) { // Paper
Object object = null;
BlockPosition blockposition = new BlockPosition(d0, d1, d2);
if ( !world.isLoaded( blockposition ) ) return null; // Spigot
2021-03-16 07:19:45 +00:00
@@ -478,7 +687,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
2020-04-24 07:01:17 +00:00
}
}
- if (object == null) {
+ if (object == null && (!optimizeEntities || !org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(block).isOccluding())) { // Paper
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()) {
2021-03-16 07:19:45 +00:00
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java
index 1508e267a38555820e2d31f3075adca185fbd4b6..f0da819627035bed83561128a11059424d2b7e30 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java
@@ -97,12 +97,19 @@ public abstract class TileEntityLootable extends TileEntityContainer {
2020-05-11 07:42:32 +00:00
@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);
}