PaperMC/CraftBukkit-Patches/0157-Schedule-Hopper-Ticks.patch

328 lines
14 KiB
Diff

From b4ba16f862dc2d42971780eb3e1cc45d6b2eb821 Mon Sep 17 00:00:00 2001
From: "Evan A. Haskell" <eah2119@gmail.com>
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 9f9b45d..6f9ac3a 100644
--- a/src/main/java/net/minecraft/server/BlockHopper.java
+++ b/src/main/java/net/minecraft/server/BlockHopper.java
@@ -21,6 +21,7 @@ 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) {
@@ -97,6 +98,14 @@ 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
}
}
@@ -158,4 +167,15 @@ 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 d5922fe..367361a 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -783,6 +783,14 @@ 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 d6d83fe..30c8d63 100644
--- a/src/main/java/net/minecraft/server/EntityItem.java
+++ b/src/main/java/net/minecraft/server/EntityItem.java
@@ -100,6 +100,25 @@ 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 17b5714..5f22f9e 100644
--- a/src/main/java/net/minecraft/server/EntityMinecartContainer.java
+++ b/src/main/java/net/minecraft/server/EntityMinecartContainer.java
@@ -52,6 +52,31 @@ 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 edcb307..4b3ea37 100644
--- a/src/main/java/net/minecraft/server/EntityOcelot.java
+++ b/src/main/java/net/minecraft/server/EntityOcelot.java
@@ -30,6 +30,27 @@ 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 c268a40..c4cc269 100644
--- a/src/main/java/net/minecraft/server/TileEntity.java
+++ b/src/main/java/net/minecraft/server/TileEntity.java
@@ -21,6 +21,67 @@ 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;
@@ -105,6 +166,10 @@ 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 1553656..9818166 100644
--- a/src/main/java/net/minecraft/server/TileEntityHopper.java
+++ b/src/main/java/net/minecraft/server/TileEntityHopper.java
@@ -18,6 +18,18 @@ 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<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
private int maxStack = MAX_STACK;
@@ -91,6 +103,7 @@ 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() {
@@ -182,6 +195,16 @@ 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;
@@ -592,6 +615,7 @@ 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 6de5ba5..1fa8448 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -429,6 +429,14 @@ 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;
--
2.1.4