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) { + if (!world.isLoaded(blockposition)) { + return; + } + 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; --