From a18bcfaf43d750456fcc5dca15be215250114eac Mon Sep 17 00:00:00 2001 From: md_5 Date: Tue, 26 May 2015 19:16:27 +1000 Subject: [PATCH] Add back hopper tick scheduling Tick a hopper only if certain conditions have changed i.e. inventory changes, redstone updates, etc. --- .../0008-Merge-tweaks-and-configuration.patch | 2 +- .../0157-Schedule-Hopper-Ticks.patch | 323 ++++++++++++++++++ 2 files changed, 324 insertions(+), 1 deletion(-) create mode 100644 CraftBukkit-Patches/0157-Schedule-Hopper-Ticks.patch diff --git a/CraftBukkit-Patches/0008-Merge-tweaks-and-configuration.patch b/CraftBukkit-Patches/0008-Merge-tweaks-and-configuration.patch index e0a72c3ebf..a95ee34689 100644 --- a/CraftBukkit-Patches/0008-Merge-tweaks-and-configuration.patch +++ b/CraftBukkit-Patches/0008-Merge-tweaks-and-configuration.patch @@ -73,8 +73,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/spigotmc/SpigotWorldConfig.java +++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java @@ -0,0 +0,0 @@ public class SpigotWorldConfig - saplingModifier = getAndValidateGrowth( "Sapling" ); wheatModifier = getAndValidateGrowth( "Wheat" ); + wartModifier = getAndValidateGrowth( "NetherWart" ); } + + public double itemMerge; diff --git a/CraftBukkit-Patches/0157-Schedule-Hopper-Ticks.patch b/CraftBukkit-Patches/0157-Schedule-Hopper-Ticks.patch new file mode 100644 index 0000000000..4877233670 --- /dev/null +++ b/CraftBukkit-Patches/0157-Schedule-Hopper-Ticks.patch @@ -0,0 +1,323 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Evan A. Haskell" +Date: Sat, 19 Apr 2014 16:58:26 -0400 +Subject: [PATCH] Schedule Hopper Ticks + +Tick a hopper only if certain conditions have changed i.e. inventory changes, redstone updates, etc. + +diff --git a/src/main/java/net/minecraft/server/BlockHopper.java b/src/main/java/net/minecraft/server/BlockHopper.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/BlockHopper.java ++++ b/src/main/java/net/minecraft/server/BlockHopper.java +@@ -0,0 +0,0 @@ public class BlockHopper extends BlockContainer { + this.j(this.blockStateList.getBlockData().set(BlockHopper.FACING, EnumDirection.DOWN).set(BlockHopper.ENABLED, Boolean.valueOf(true))); + this.a(CreativeModeTab.d); + this.a(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F); ++ this.a(true); // Spigot - Enable random block updates on hoppers // PAIL: Rename + } + + public void updateShape(IBlockAccess iblockaccess, BlockPosition blockposition) { +@@ -0,0 +0,0 @@ public class BlockHopper extends BlockContainer { + + if (flag != ((Boolean) iblockdata.get(BlockHopper.ENABLED)).booleanValue()) { + world.setTypeAndData(blockposition, iblockdata.set(BlockHopper.ENABLED, Boolean.valueOf(flag)), 4); ++ // Spigot start - When this hopper becomes unpowered, make it active. ++ // Called when this block's power level changes. flag1 is the current ++ // isNotPowered from metadata. flag is the recalculated isNotPowered. ++ TileEntityHopper hopper = (TileEntityHopper) world.getTileEntity(blockposition); ++ if (flag && hopper != null) { ++ hopper.ensureUpdates(); ++ } ++ // Spigot end + } + + } +@@ -0,0 +0,0 @@ public class BlockHopper extends BlockContainer { + protected BlockStateList getStateList() { + return new BlockStateList(this, new IBlockState[] { BlockHopper.FACING, BlockHopper.ENABLED}); + } ++ ++ // Spigot start - Use random block updates to make hoppers active. ++ // PAIL: Rename ++ @Override ++ public void a(World world, BlockPosition blockposition, IBlockData iblockdata, java.util.Random random) { ++ TileEntityHopper hopper = (TileEntityHopper) world.getTileEntity(blockposition); ++ if (hopper != null) { ++ hopper.ensureUpdates(); ++ } ++ } ++ // Spigot end + } +diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -0,0 +0,0 @@ public class Chunk { + + tileentity.D(); + this.tileEntities.put(blockposition, tileentity); ++ // Spigot start ++ // When a tile entity is added, update hoppers around the tile ++ tileentity.scheduleTicks(); ++ ++ // if it is a large chest, hoppers should update around its ++ // other half ++ TileEntity.updateChestAndHoppers(this.world, blockposition); ++ // Spigot end + // CraftBukkit start + } else { + System.out.println("Attempted to place a tile entity (" + tileentity + ") at " + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ() +diff --git a/src/main/java/net/minecraft/server/EntityItem.java b/src/main/java/net/minecraft/server/EntityItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityItem.java ++++ b/src/main/java/net/minecraft/server/EntityItem.java +@@ -0,0 +0,0 @@ public class EntityItem extends Entity { + if (this.onGround) { + this.motY *= -0.5D; + } ++ // Spigot start - Make the hopper(s) below this item active. ++ // Called each tick on each item entity. ++ int xi = MathHelper.floor(this.getBoundingBox().a); ++ int yi = MathHelper.floor(this.getBoundingBox().b) - 1; ++ int zi = MathHelper.floor(this.getBoundingBox().c); ++ int xf = MathHelper.floor(this.getBoundingBox().d); ++ int yf = MathHelper.floor(this.getBoundingBox().e) - 1; ++ int zf = MathHelper.floor(this.getBoundingBox().f); ++ for (int a = xi; a <= xf; a++) { ++ for (int c = zi; c <= zf; c++) { ++ for (int b = yi; b <= yf; b++) { ++ TileEntity tileEntity = this.world.getTileEntity(new BlockPosition(a, b, c)); ++ if (tileEntity instanceof TileEntityHopper) { ++ ((TileEntityHopper) tileEntity).ensureUpdates(); ++ } ++ } ++ } ++ } ++ // Spigot end + + /* Craftbukkit start - moved up + if (this.age != -32768) { +diff --git a/src/main/java/net/minecraft/server/EntityMinecartContainer.java b/src/main/java/net/minecraft/server/EntityMinecartContainer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityMinecartContainer.java ++++ b/src/main/java/net/minecraft/server/EntityMinecartContainer.java +@@ -0,0 +0,0 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp + super(world, d0, d1, d2); + } + ++ // Spigot start - Make hoppers around this container minecart active. ++ // Called each tick on each minecart. ++ // PAIL: Rename ++ @Override ++ public void t_() { ++ int xi = MathHelper.floor(this.getBoundingBox().a) - 1; ++ int yi = MathHelper.floor(this.getBoundingBox().b) - 1; ++ int zi = MathHelper.floor(this.getBoundingBox().c) - 1; ++ int xf = MathHelper.floor(this.getBoundingBox().d) + 1; ++ int yf = MathHelper.floor(this.getBoundingBox().e) + 1; ++ int zf = MathHelper.floor(this.getBoundingBox().f) + 1; ++ for (int a = xi; a <= xf; a++) { ++ for (int b = yi; b <= yf; b++) { ++ for (int c = zi; c <= zf; c++) { ++ TileEntity tileEntity = this.world.getTileEntity(new BlockPosition(a, b, c)); ++ if (tileEntity instanceof TileEntityHopper) { ++ ((TileEntityHopper) tileEntity).ensureUpdates(); ++ } ++ } ++ } ++ } ++ super.t_(); ++ } ++ // Spigot end ++ + public void a(DamageSource damagesource) { + super.a(damagesource); + if (this.world.getGameRules().getBoolean("doEntityDrops")) { +diff --git a/src/main/java/net/minecraft/server/EntityOcelot.java b/src/main/java/net/minecraft/server/EntityOcelot.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/EntityOcelot.java ++++ b/src/main/java/net/minecraft/server/EntityOcelot.java +@@ -0,0 +0,0 @@ public class EntityOcelot extends EntityTameableAnimal { + this.datawatcher.a(18, Byte.valueOf((byte) 0)); + } + ++ // Spigot start - We use K, the method called in World.class on each entity each tick ++ // PAIL: Rename ++ @Override ++ public void K() { ++ int xi = MathHelper.floor(this.getBoundingBox().a); ++ int yi = MathHelper.floor(this.getBoundingBox().b) - 1; ++ int zi = MathHelper.floor(this.getBoundingBox().c); ++ int xf = MathHelper.floor(this.getBoundingBox().d); ++ int yf = MathHelper.floor(this.getBoundingBox().e) - 1; ++ int zf = MathHelper.floor(this.getBoundingBox().f); ++ for (int a = xi; a <= xf; a++) { ++ for (int c = zi; c <= zf; c++) { ++ for (int b = yi; b <= yf; b++) { ++ TileEntity.updateChestAndHoppers(this.world, new BlockPosition(a, b, c)); ++ } ++ } ++ } ++ super.K(); ++ } ++ // Spigot end ++ + public void E() { + if (this.getControllerMove().a()) { + double d0 = this.getControllerMove().b(); +diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/TileEntity.java ++++ b/src/main/java/net/minecraft/server/TileEntity.java +@@ -0,0 +0,0 @@ public abstract class TileEntity { + private int h; + protected Block e; + ++ // Spigot start ++ // Helper method for scheduleTicks. If the hopper at blockposition is pointed ++ // toward this tile, then make the hopper active ++ private void scheduleTick(BlockPosition blockposition) { ++ TileEntity tileEntity = this.world.getTileEntity(blockposition); ++ if (tileEntity instanceof TileEntityHopper) { ++ // i is the metadeta assoiated with the direction the hopper faces. ++ EnumDirection dir = BlockHopper.b(tileEntity.u()); ++ ++ // Facing class provides arrays for direction offset. ++ if (tileEntity.position.shift(dir).equals(position)) { ++ ((TileEntityHopper) tileEntity).ensureUpdates(); ++ } ++ } ++ } ++ ++ // Called from update when the contents have changed, so hoppers need updates. ++ // Check all 6 faces. ++ public void scheduleTicks() { ++ if (this.world != null) { ++ // Check the top ++ this.scheduleTick(position.up()); ++ // Check the sides ++ for (int i = 2; i < 6; i++) { ++ this.scheduleTick(position.shift(EnumDirection.fromType1(i))); ++ } ++ // Check the bottom. ++ TileEntity tileEntity = this.world.getTileEntity(position.down()); ++ if (tileEntity instanceof TileEntityHopper && tileEntity.world != null) { ++ ((TileEntityHopper) tileEntity).ensureUpdates(); ++ } ++ } ++ } ++ ++ // If there is a chest at blockposition, then update hoppers around it ++ // as well as around its other half (if it exists) ++ public static void updateChestAndHoppers(World world, BlockPosition blockposition) { ++ Block block = world.getType(blockposition).getBlock(); ++ if (block instanceof BlockChest) { ++ TileEntity tile = world.getTileEntity(blockposition); ++ if (tile instanceof TileEntityChest) { ++ tile.scheduleTicks(); ++ } ++ for (int i = 2; i < 6; i++) { ++ // Look for a matching chest at each face ++ BlockPosition pos = blockposition.shift(EnumDirection.fromType1(i)); ++ if (world.getType(pos).getBlock() == block) { ++ tile = world.getTileEntity(pos); ++ if (tile instanceof TileEntityChest) { ++ tile.scheduleTicks(); ++ } ++ break; ++ } ++ } ++ } ++ } ++ // Spigot end ++ + public TileEntity() { + this.position = BlockPosition.ZERO; + this.h = -1; +@@ -0,0 +0,0 @@ public abstract class TileEntity { + if (this.w() != Blocks.AIR) { + this.world.updateAdjacentComparators(this.position, this.w()); + } ++ // Spigot start - Called when the contents have changed, so hoppers around this ++ // tile need updating. ++ this.scheduleTicks(); ++ // Spigot end + } + + } +diff --git a/src/main/java/net/minecraft/server/TileEntityHopper.java b/src/main/java/net/minecraft/server/TileEntityHopper.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/TileEntityHopper.java ++++ b/src/main/java/net/minecraft/server/TileEntityHopper.java +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityContainer implements IHopper, IU + private String f; + private int g = -1; + ++ // Spigot start ++ ++ // Whether it has been determined that this hopper should update ++ private boolean active = true; ++ ++ // Called by redstone updates, inventory changes, etc. to ensure this ++ // hopper updates ++ public void ensureUpdates() { ++ active = true; ++ } ++ // Spigot end ++ + // CraftBukkit start - add fields and methods + public List transaction = new java.util.ArrayList(); + private int maxStack = MAX_STACK; +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityContainer implements IHopper, IU + + public void update() { + super.update(); ++ ensureUpdates(); // Spigot - Contents have changed, so make this hopper active + } + + public int getSize() { +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityContainer implements IHopper, IU + + public boolean m() { + if (this.world != null && !this.world.isClientSide) { ++ // Spigot start ++ ++ // if it has not been determined that this hopper should update, ++ // then don't waste time doing it ++ if (!active) ++ return false; ++ ++ // set it up for the next time this method is called ++ active = false; ++ // Spigot end + if (!this.n() && BlockHopper.f(this.u())) { + boolean flag = false; + +@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityContainer implements IHopper, IU + + public void d(int i) { + this.g = i; ++ this.ensureUpdates(); // Spigot + } + + public boolean n() { +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 ++++ b/src/main/java/net/minecraft/server/World.java +@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { + // Modularize client and physic updates + notifyAndUpdatePhysics(blockposition, chunk, block1, block, i); + } ++ // Spigot start - If this block is changing to that which a chest beneath it ++ // becomes able to be opened, then the chest must be updated. ++ // block1 is the old block. block is the new block. r returns true if the block type ++ // prevents access to a chest. ++ if (block1 != null && block1.isOccluding() && !block.isOccluding()) { ++ TileEntity.updateChestAndHoppers(this, blockposition.down()); ++ } ++ // Spigot end + // CraftBukkit end + + return true; +-- \ No newline at end of file