aboutsummaryrefslogtreecommitdiffhomepage
path: root/Spigot-Server-Patches/0145-Make-entities-look-for-hoppers.patch
diff options
context:
space:
mode:
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.patch382
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
+