diff options
Diffstat (limited to 'Spigot-Server-Patches/0145-Make-entities-look-for-hoppers.patch')
-rw-r--r-- | Spigot-Server-Patches/0145-Make-entities-look-for-hoppers.patch | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/Spigot-Server-Patches/0145-Make-entities-look-for-hoppers.patch b/Spigot-Server-Patches/0145-Make-entities-look-for-hoppers.patch new file mode 100644 index 0000000000..f94f692727 --- /dev/null +++ b/Spigot-Server-Patches/0145-Make-entities-look-for-hoppers.patch @@ -0,0 +1,382 @@ +From fef949da0a39778974de622940c54323e5053c39 Mon Sep 17 00:00:00 2001 +From: Techcable <[email protected]> +Date: Sat, 18 Jun 2016 01:01:37 -0500 +Subject: [PATCH] Make entities look for hoppers + +Every tick hoppers try and find an block-inventory to extract from. +If no tile entity is above the hopper (which there often isn't) it will do a bounding box search for minecart chests and minecart hoppers. +If it can't find an inventory, it will then look for a dropped item, which is another bounding box search. +This patch eliminates that expensive check by having dropped items and minecart hoppers/chests look for hoppers instead. +Hoppers are tile entities meaning you can do a simple tile entity lookup to find the nearest hopper in range. +Pushing out of hoppers causes a bouding box lookup, which this patch replaces with a tile entity lookup. + +This patch may causes a decrease in the performance of dropped items, which is why it can be disabled in the configuration. + +diff --git a/src/main/java/com/destroystokyo/paper/HopperPusher.java b/src/main/java/com/destroystokyo/paper/HopperPusher.java +new file mode 100644 +index 000000000..aef7c2be9 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/HopperPusher.java +@@ -0,0 +1,59 @@ ++package com.destroystokyo.paper; ++ ++import net.minecraft.server.AxisAlignedBB; ++import net.minecraft.server.BlockPosition; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.TileEntityHopper; ++import net.minecraft.server.World; ++ ++public interface HopperPusher { ++ ++ default TileEntityHopper findHopper() { ++ BlockPosition pos = new BlockPosition(getX(), getY(), getZ()); ++ int startX = pos.getX() - 1; ++ int endX = pos.getX() + 1; ++ int startY = Math.max(0, pos.getY() - 1); ++ int endY = Math.min(255, pos.getY() + 1); ++ int startZ = pos.getZ() - 1; ++ int endZ = pos.getZ() + 1; ++ BlockPosition.PooledBlockPosition adjacentPos = BlockPosition.PooledBlockPosition.aquire(); ++ for (int x = startX; x <= endX; x++) { ++ for (int y = startY; y <= endY; y++) { ++ for (int z = startZ; z <= endZ; z++) { ++ adjacentPos.setValues(x, y, z); ++ TileEntityHopper hopper = MCUtil.getHopper(getWorld(), adjacentPos); ++ if (hopper == null) continue; // Avoid playing with the bounding boxes, if at all possible ++ AxisAlignedBB hopperBoundingBox = hopper.getHopperLookupBoundingBox(); ++ /* ++ * Check if the entity's bounding box intersects with the hopper's lookup box. ++ * This operation doesn't work both ways! ++ * Make sure you check if the entity's box intersects the hopper's box, not vice versa! ++ */ ++ if (this.getBoundingBox().intersects(hopperBoundingBox)) { ++ return hopper; ++ } ++ } ++ } ++ } ++ adjacentPos.free(); ++ return null; ++ } ++ ++ boolean acceptItem(TileEntityHopper hopper); ++ ++ default boolean tryPutInHopper() { ++ if (!getWorld().paperConfig.isHopperPushBased) return false; ++ TileEntityHopper hopper = findHopper(); ++ return hopper != null && hopper.canAcceptItems() && acceptItem(hopper); ++ } ++ ++ AxisAlignedBB getBoundingBox(); ++ ++ World getWorld(); ++ ++ double getX(); ++ ++ double getY(); ++ ++ double getZ(); ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 7bd745a27..894d40662 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -340,4 +340,9 @@ public class PaperWorldConfig { + private void altFallingBlockOnGround() { + altFallingBlockOnGround = getBoolean("use-alternate-fallingblock-onGround-detection", false); + } ++ ++ public boolean isHopperPushBased; ++ private void isHopperPushBased() { ++ isHopperPushBased = getBoolean("hopper.push-based", false); ++ } + } +diff --git a/src/main/java/net/minecraft/server/AxisAlignedBB.java b/src/main/java/net/minecraft/server/AxisAlignedBB.java +index 1eb9c2da8..c88b76a79 100644 +--- a/src/main/java/net/minecraft/server/AxisAlignedBB.java ++++ b/src/main/java/net/minecraft/server/AxisAlignedBB.java +@@ -235,6 +235,7 @@ public class AxisAlignedBB { + } + } + ++ public final boolean intersects(AxisAlignedBB intersecting) { return this.c(intersecting); } // Paper - OBFHELPER + public boolean c(AxisAlignedBB axisalignedbb) { + return this.a(axisalignedbb.a, axisalignedbb.b, axisalignedbb.c, axisalignedbb.d, axisalignedbb.e, axisalignedbb.f); + } +diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java +index 008ed206d..b3c1f550c 100644 +--- a/src/main/java/net/minecraft/server/BlockPosition.java ++++ b/src/main/java/net/minecraft/server/BlockPosition.java +@@ -250,6 +250,7 @@ public class BlockPosition extends BaseBlockPosition { + super(i, j, k); + } + ++ public static BlockPosition.PooledBlockPosition aquire() { return s(); } // Paper - OBFHELPER + public static BlockPosition.PooledBlockPosition s() { + return e(0, 0, 0); + } +@@ -276,6 +277,7 @@ public class BlockPosition extends BaseBlockPosition { + return new BlockPosition.PooledBlockPosition(i, j, k); + } + ++ public void free() { t(); } // Paper - OBFHELPER + public void t() { + List list = BlockPosition.PooledBlockPosition.g; + +@@ -393,6 +395,7 @@ public class BlockPosition extends BaseBlockPosition { + return this.d; + } + ++ public void setValues(int x, int y, int z) { c(x, y, z); } // Paper - OBFHELPER + public BlockPosition.MutableBlockPosition c(int i, int j, int k) { + this.b = i; + this.c = j; +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 0d1fdd3ee..0479b7551 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -80,6 +80,19 @@ public abstract class Entity implements ICommandListener { + public double locX; + public double locY; + public double locZ; ++ // Paper start - getters to implement HopperPusher ++ public double getX() { ++ return locX; ++ } ++ ++ public double getY() { ++ return locY; ++ } ++ ++ public double getZ() { ++ return locZ; ++ } ++ // Paper end + public double motX; + public double motY; + public double motZ; +diff --git a/src/main/java/net/minecraft/server/EntityItem.java b/src/main/java/net/minecraft/server/EntityItem.java +index 9742afc65..95ca1b8e4 100644 +--- a/src/main/java/net/minecraft/server/EntityItem.java ++++ b/src/main/java/net/minecraft/server/EntityItem.java +@@ -5,8 +5,15 @@ import javax.annotation.Nullable; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + import org.bukkit.event.player.PlayerPickupItemEvent; // CraftBukkit ++import com.destroystokyo.paper.HopperPusher; // Paper + +-public class EntityItem extends Entity { ++// Paper start - implement HopperPusher ++public class EntityItem extends Entity implements HopperPusher { ++ @Override ++ public boolean acceptItem(TileEntityHopper hopper) { ++ return TileEntityHopper.putDropInInventory(null, hopper, this); ++ } ++// Paper end + + private static final Logger b = LogManager.getLogger(); + private static final DataWatcherObject<ItemStack> c = DataWatcher.a(EntityItem.class, DataWatcherRegistry.f); +@@ -56,6 +63,7 @@ public class EntityItem extends Entity { + this.die(); + } else { + super.A_(); ++ if (tryPutInHopper()) return; // Paper + // CraftBukkit start - Use wall time for pickup and despawn timers + int elapsedTicks = MinecraftServer.currentTick - this.lastTick; + if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; +@@ -143,6 +151,7 @@ public class EntityItem extends Entity { + // Spigot start - copied from above + @Override + public void inactiveTick() { ++ if (tryPutInHopper()) return; // Paper + // CraftBukkit start - Use wall time for pickup and despawn timers + int elapsedTicks = MinecraftServer.currentTick - this.lastTick; + if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; +diff --git a/src/main/java/net/minecraft/server/EntityMinecartContainer.java b/src/main/java/net/minecraft/server/EntityMinecartContainer.java +index 965aa5c23..04256898b 100644 +--- a/src/main/java/net/minecraft/server/EntityMinecartContainer.java ++++ b/src/main/java/net/minecraft/server/EntityMinecartContainer.java +@@ -7,6 +7,7 @@ import javax.annotation.Nullable; + import java.util.List; + import org.bukkit.Location; + ++import com.destroystokyo.paper.HopperPusher; // Paper + import com.destroystokyo.paper.loottable.CraftLootableInventoryData; // Paper + import com.destroystokyo.paper.loottable.CraftLootableInventory; // Paper + import com.destroystokyo.paper.loottable.LootableInventory; // Paper +@@ -15,7 +16,25 @@ import org.bukkit.entity.HumanEntity; + import org.bukkit.inventory.InventoryHolder; + // CraftBukkit end + +-public abstract class EntityMinecartContainer extends EntityMinecartAbstract implements ITileInventory, ILootable, CraftLootableInventory { // Paper ++// Paper start - push into hoppers ++public abstract class EntityMinecartContainer extends EntityMinecartAbstract implements ITileInventory, ILootable, CraftLootableInventory, HopperPusher { // Paper - CraftLootableInventory ++ @Override ++ public boolean acceptItem(TileEntityHopper hopper) { ++ return TileEntityHopper.acceptItem(hopper, this); ++ } ++ ++ @Override ++ public void A_() { ++ super.A_(); ++ tryPutInHopper(); ++ } ++ ++ @Override ++ public void inactiveTick() { ++ super.inactiveTick(); ++ tryPutInHopper(); ++ } ++ // Paper end + + private NonNullList<ItemStack> items; + private boolean b; +diff --git a/src/main/java/net/minecraft/server/IHopper.java b/src/main/java/net/minecraft/server/IHopper.java +index 804215a1c..e830d8390 100644 +--- a/src/main/java/net/minecraft/server/IHopper.java ++++ b/src/main/java/net/minecraft/server/IHopper.java +@@ -4,9 +4,9 @@ public interface IHopper extends IInventory { + + World getWorld(); + +- double E(); ++ double E(); default double getX() { return E(); } // Paper - OBFHELPER + +- double F(); ++ double F(); default double getY() { return F(); } // Paper - OBFHELPER + +- double G(); ++ double G(); default double getZ() { return G(); } // Paper - OBFHELPER + } +diff --git a/src/main/java/net/minecraft/server/TileEntityHopper.java b/src/main/java/net/minecraft/server/TileEntityHopper.java +index 44b6ecc5d..022e64520 100644 +--- a/src/main/java/net/minecraft/server/TileEntityHopper.java ++++ b/src/main/java/net/minecraft/server/TileEntityHopper.java +@@ -126,6 +126,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + + private boolean o() { ++ mayAcceptItems = false; // Paper - at the beginning of a tick, assume we can't accept items + if (this.world != null && !this.world.isClientSide) { + if (!this.J() && BlockHopper.f(this.v())) { + boolean flag = false; +@@ -135,6 +136,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + + if (!this.r()) { ++ mayAcceptItems = true; // Paper - flag this hopper to be able to accept items + flag = a((IHopper) this) || flag; + } + +@@ -150,6 +152,14 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + } + ++ // Paper start ++ private boolean mayAcceptItems = false; ++ ++ public boolean canAcceptItems() { ++ return mayAcceptItems; ++ } ++ // Paper end ++ + private boolean p() { + Iterator iterator = this.items.iterator(); + +@@ -302,8 +312,15 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + return true; + } + ++ // Paper start - split methods, and only do entity lookup if in pull mode + public static boolean a(IHopper ihopper) { +- IInventory iinventory = b(ihopper); ++ IInventory iinventory = getInventory(ihopper, !(ihopper instanceof TileEntityHopper) || !ihopper.getWorld().paperConfig.isHopperPushBased); ++ ++ return acceptItem(ihopper, iinventory); ++ } ++ ++ public static boolean acceptItem(IHopper ihopper, IInventory iinventory) { ++ // Paper end + + if (iinventory != null) { + EnumDirection enumdirection = EnumDirection.DOWN; +@@ -334,8 +351,8 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + } + } +- } else { +- Iterator iterator = a(ihopper.getWorld(), ihopper.E(), ihopper.F(), ihopper.G()).iterator(); ++ } else if (!ihopper.getWorld().paperConfig.isHopperPushBased || !(ihopper instanceof TileEntityHopper)) { // Paper - only search for entities in 'pull mode' ++ Iterator iterator = a(ihopper.getWorld(), ihopper.E(), ihopper.F(), ihopper.G()).iterator(); // Change getHopperLookupBoundingBox() if this ever changes + + while (iterator.hasNext()) { + EntityItem entityitem = (EntityItem) iterator.next(); +@@ -401,6 +418,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + return false; + } + ++ public static boolean putDropInInventory(IInventory iinventory, IInventory iinventory1, EntityItem entityitem) { return a(iinventory, iinventory1, entityitem); } // Paper - OBFHELPER + public static boolean a(IInventory iinventory, IInventory iinventory1, EntityItem entityitem) { + boolean flag = false; + +@@ -506,18 +524,44 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + private IInventory I() { + EnumDirection enumdirection = BlockHopper.e(this.v()); + +- return b(this.getWorld(), this.E() + (double) enumdirection.getAdjacentX(), this.F() + (double) enumdirection.getAdjacentY(), this.G() + (double) enumdirection.getAdjacentZ()); ++ // Paper start - don't search for entities in push mode ++ World world = getWorld(); ++ return getInventory(world, this.E() + (double) enumdirection.getAdjacentX(), this.F() + (double) enumdirection.getAdjacentY(), this.G() + (double) enumdirection.getAdjacentZ(), !world.paperConfig.isHopperPushBased); ++ // Paper end + } + +- public static IInventory b(IHopper ihopper) { +- return b(ihopper.getWorld(), ihopper.E(), ihopper.F() + 1.0D, ihopper.G()); ++ // Paper start - add option to search for entities ++ public static IInventory b(IHopper hopper) { ++ return getInventory(hopper, true); ++ } ++ ++ public static IInventory getInventory(IHopper ihopper, boolean searchForEntities) { ++ return getInventory(ihopper.getWorld(), ihopper.E(), ihopper.F() + 1.0D, ihopper.G(), searchForEntities); ++ // Paper end + } + + public static List<EntityItem> a(World world, double d0, double d1, double d2) { +- return world.a(EntityItem.class, new AxisAlignedBB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D), IEntitySelector.a); ++ return world.a(EntityItem.class, new AxisAlignedBB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D), IEntitySelector.a); // Change getHopperLookupBoundingBox(double, double, double) if the bounding box calculation is ever changed ++ } ++ ++ // Paper start ++ public AxisAlignedBB getHopperLookupBoundingBox() { ++ return getHopperLookupBoundingBox(this.getX(), this.getY(), this.getZ()); + } + ++ private static AxisAlignedBB getHopperLookupBoundingBox(double d0, double d1, double d2) { ++ // Change this if a(World, double, double, double) above ever changes ++ return new AxisAlignedBB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D); ++ } ++ // Paper end ++ ++ // Paper start - add option to searchForEntities + public static IInventory b(World world, double d0, double d1, double d2) { ++ return getInventory(world, d0, d1, d2, true); ++ } ++ ++ public static IInventory getInventory(World world, double d0, double d1, double d2, boolean searchForEntities) { ++ // Paper end + Object object = null; + int i = MathHelper.floor(d0); + int j = MathHelper.floor(d1); +@@ -537,7 +581,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi + } + } + +- if (object == null) { ++ if (object == null && searchForEntities) { // Paper - only if searchForEntities + List 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.c); + + if (!list.isEmpty()) { +-- +2.12.0.windows.1 + |