From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Phoenix616 <mail@moep.tv>
Date: Tue, 24 Mar 2020 17:40:50 +0100
Subject: [PATCH] Hopper Optimizations

- Don't tick empty hoppers: This avoids ticking hoppers that are only used to transport items in a
chain.
- Add config option to increase the full hopper cooldown
- Only set check cooldown if it's bigger than already set cooldown

diff --git a/src/main/java/de/minebench/origami/OrigamiConfig.java b/src/main/java/de/minebench/origami/OrigamiConfig.java
index a1a585f5b4b2c10c41b184636149c8dde2a3ae51..f02eb8478cef4ffccee83a1ec4ae5ffbfb0591c1 100644
--- a/src/main/java/de/minebench/origami/OrigamiConfig.java
+++ b/src/main/java/de/minebench/origami/OrigamiConfig.java
@@ -120,6 +120,12 @@ public final class OrigamiConfig {
                 Bukkit.getLogger().info("Returning matching chunk rom fast search directly instead of loading it.");
             }
         }
+        public boolean tickEmptyHoppers = false;
+        public int fullHopperCooldown = 128;
+        private void hopperOptimizations() {
+            tickEmptyHoppers = getBoolean("tick-empty-hoppers", tickEmptyHoppers);
+            fullHopperCooldown = getInt("ticks-per.full-hopper-cooldown", fullHopperCooldown);
+        }
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java
index 3b84039a76843a0784e2d71bb66dc322450c2cab..15aaff4797f0343b5aba0302a3dc1e5fae459b5d 100644
--- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java
+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java
@@ -167,6 +167,13 @@ public class EntityItem extends Entity {
                 }
             }
 
+            // Origami start - don't tick empty hoppers
+            if (!world.origamiConfig.tickEmptyHoppers && locY() >= 1 && (this.age < 10 || this.age > this.getDespawnRate() - 10
+                    || (int) locX() != (int) lastX || (int) locZ() != (int) lastZ || (int) locY() != (int) lastY)) {
+                net.minecraft.world.level.block.entity.TileEntityHopper.enableTicking(world.getTileEntity(new BlockPosition(locX(), locY() - 1, locZ())), 0);
+            }
+            // Origami end
+
             if (!this.world.isClientSide && this.age >= this.getDespawnRate()) { // Spigot // Paper
                 // CraftBukkit start - fire ItemDespawnEvent
                 if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) {
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java
index 0166d11cb540a536390f486e1069d6119d8d23d6..b688ff6534e069bc631e2cb84bb1deb3e4f1914a 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java
@@ -164,7 +164,6 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp
         if (!itemstack.isEmpty() && itemstack.getCount() > this.getMaxStackSize()) {
             itemstack.setCount(this.getMaxStackSize());
         }
-
     }
 
     @Override
@@ -178,7 +177,25 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp
     }
 
     @Override
-    public void update() {}
+    public void update() {
+        // Origami start - don't tick empty hoppers
+        checkHopperBelow();
+    }
+
+    @Override
+    public void tick() {
+        super.tick();
+        if (locY() >= 1 && ((int) locX() != (int) lastX || (int) locZ() != (int) lastZ || (int) locY() != (int) lastY)) {
+            checkHopperBelow();
+        }
+    }
+
+    private void checkHopperBelow() {
+        if (!world.origamiConfig.tickEmptyHoppers && !this.isEmpty()) {
+            net.minecraft.world.level.block.entity.TileEntityHopper.enableTicking(world.getTileEntity(new net.minecraft.core.BlockPosition(locX(), locY() - 1, locZ())), 0);
+        }
+    }
+    // Origami end
 
     @Override
     public boolean a(EntityHuman entityhuman) {
diff --git a/src/main/java/net/minecraft/world/level/block/BlockComposter.java b/src/main/java/net/minecraft/world/level/block/BlockComposter.java
index c0b235d5edf3cd14021696d1b4f76ce3de41f5d5..2d6abc0b8b3c9860110f0b5f1df1b3b3bbf30673 100644
--- a/src/main/java/net/minecraft/world/level/block/BlockComposter.java
+++ b/src/main/java/net/minecraft/world/level/block/BlockComposter.java
@@ -302,6 +302,7 @@ public class BlockComposter extends Block implements IInventoryHolder {
         if ((Integer) iblockdata.get(BlockComposter.a) == 7) {
             worldserver.setTypeAndData(blockposition, (IBlockData) iblockdata.a((IBlockState) BlockComposter.a), 3);
             worldserver.playSound((EntityHuman) null, blockposition, SoundEffects.BLOCK_COMPOSTER_READY, SoundCategory.BLOCKS, 1.0F, 1.0F);
+            net.minecraft.world.level.block.entity.TileEntityHopper.enableTicking(worldserver.getTileEntity(new BlockPosition(blockposition.getX(), blockposition.getY() - 1, blockposition.getZ())), 0); // Origami - don't tick empty hoppers
         }
 
     }
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java
index fb7a1a854efcf42f0351ef521aff67d5fcc4ab27..96dfe05ed57f7e2c3dac3a784ae3445ad9975c40 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java
@@ -98,4 +98,14 @@ public abstract class TileEntityContainer extends TileEntity implements IInvento
         return new org.bukkit.Location(world.getWorld(), position.getX(), position.getY(), position.getZ());
     }
     // CraftBukkit end
+
+    // Origami start - don't tick empty hoppers
+    @Override
+    public void update() {
+        super.update();
+        if (world != null && !world.origamiConfig.tickEmptyHoppers) {
+            TileEntityHopper.enableTicking(world.getTileEntity(position.shift(net.minecraft.core.EnumDirection.DOWN)), world.spigotConfig.hopperCheck);
+        }
+    }
+    // Origami end
 }
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 537dc52e5ff3325555ee6049bc7f277952983b76..a859e12571ceff2199842e03df77b21ee9d689f2 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
@@ -47,8 +47,9 @@ import org.bukkit.inventory.Inventory;
 public class TileEntityHopper extends TileEntityLootable implements IHopper, ITickable {
 
     private NonNullList<ItemStack> items;
-    private int j;
+    private int j; public int getCooldown() { return this.j; } // Origami - OBFHELPER
     private long k;
+    public boolean shouldTick = true; // Origami - don't tick empty hoppers
 
     // CraftBukkit start - add fields and methods
     public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
@@ -126,7 +127,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
         if (itemstack.getCount() > this.getMaxStackSize()) {
             itemstack.setCount(this.getMaxStackSize());
         }
-
+        shouldTick = true; // Origami - don't tick empty hoppers
     }
 
     @Override
@@ -136,7 +137,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
 
     @Override
     public void tick() {
-        if (this.world != null && !this.world.isClientSide) {
+        if (this.world != null && !this.world.isClientSide && (shouldTick || world.origamiConfig.tickEmptyHoppers)) { // Origami - don't tick empty hoppers
             --this.j;
             this.k = this.world.getTime();
             if (!this.m()) {
@@ -145,7 +146,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
                 boolean result = this.a(() -> {
                     return a((IHopper) this);
                 });
-                if (!result && this.world.spigotConfig.hopperCheck > 1) {
+                if (!result && this.world.spigotConfig.hopperCheck > 1 && this.world.spigotConfig.hopperCheck > this.getCooldown()) { // Origami - only set check cooldown if it's bigger than already set one
                     this.setCooldown(this.world.spigotConfig.hopperCheck);
                 }
                 // Spigot end
@@ -154,6 +155,26 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
         }
     }
 
+    // Origami start - don't tick empty hoppers
+    @Override
+    public void update() {
+        shouldTick = true;
+        super.update();
+    }
+
+    public static void enableTicking(TileEntity tileEntity, int cooldown) {
+        if (tileEntity instanceof TileEntityHopper) {
+            if (!((TileEntityHopper) tileEntity).shouldTick) {
+                if (((TileEntityHopper) tileEntity).getCooldown() > cooldown && tileEntity.getBlock().get(BlockHopper.ENABLED)) {
+                    // Force the hopper to update if it is enabled and didn't tick/decrease cooldown before
+                    ((TileEntityHopper) tileEntity).setCooldown(cooldown);
+                }
+                ((TileEntityHopper) tileEntity).shouldTick = true;
+            }
+        }
+    }
+    // Origami end
+
     private boolean a(Supplier<Boolean> supplier) {
         if (this.world != null && !this.world.isClientSide) {
             if (!this.m() && (Boolean) this.getBlock().get(BlockHopper.ENABLED)) {
@@ -161,6 +182,10 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
 
                 if (!this.isEmpty()) {
                     flag = this.k();
+                    // Origami - don't tick empty hoppers
+                } else {
+                    shouldTick = world.origamiConfig.tickEmptyHoppers;
+                    // Origami end
                 }
 
                 if (!this.j()) {
@@ -240,7 +265,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
             }
         }
         if (foundItem && world.paperConfig.cooldownHopperWhenFull) { // Inventory was full - cooldown
-            this.setCooldown(world.spigotConfig.hopperTransfer);
+            this.setCooldown(world.origamiConfig.fullHopperCooldown > -1 ? world.origamiConfig.fullHopperCooldown : world.spigotConfig.hopperTransfer); // Origami - full hopper cooldown config
         }
         return false;
     }
@@ -280,7 +305,13 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
         origItemStack.setCount(origCount);
 
         if (world.paperConfig.cooldownHopperWhenFull) {
-            cooldownHopper(ihopper);
+            // Origami start - full hopper cooldown config
+            if (ihopper instanceof TileEntityHopper) {
+                ((TileEntityHopper) ihopper).setCooldown(world.origamiConfig.fullHopperCooldown > -1 ? world.origamiConfig.fullHopperCooldown : world.spigotConfig.hopperTransfer);
+            } else if (ihopper instanceof EntityMinecartHopper) {
+                ((EntityMinecartHopper) ihopper).setCooldown(world.spigotConfig.hopperTransfer / 2);
+            }
+            // Origami end - full hopper cooldown config
         }
 
         return false;
@@ -488,6 +519,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
                 entityitem = (EntityItem) iterator.next();
             } while (!a((IInventory) ihopper, entityitem));
 
+            if (ihopper instanceof TileEntityHopper) ((TileEntityHopper) ihopper).shouldTick = true; // Origami - don't tick empty hoppers
             return true;
         }
     }
@@ -576,7 +608,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
                 itemstack = a(iinventory, iinventory1, itemstack, k, enumdirection);
             }
         }
-
+        if (iinventory1 instanceof TileEntityHopper) ((TileEntityHopper) iinventory1).shouldTick = true; // Origami - don't tick empty hoppers
         return itemstack;
     }
 
@@ -717,7 +749,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
         return (double) this.position.getZ() + 0.5D;
     }
 
-    private void setCooldown(int i) {
+    public void setCooldown(int i) { // Origami - make public
         this.j = i;
     }
 
@@ -744,6 +776,7 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
             BlockPosition blockposition = this.getPosition();
 
             if (VoxelShapes.c(VoxelShapes.a(entity.getBoundingBox().d((double) (-blockposition.getX()), (double) (-blockposition.getY()), (double) (-blockposition.getZ()))), this.aa_(), OperatorBoolean.AND)) {
+                enableTicking(this, 0); // Origami - don't tick empty hoppers
                 this.a(() -> {
                     return a((IInventory) this, (EntityItem) entity);
                 });
