Improve quarry performance.

Reduce getBlockId calls in canChangeBlock/isSoftBlock to one, add canChangeBlock/isSoftBlock with blockID parameter to allow for only a single getBlockId call per block checked for the visit list.
Use heightmaps when building visit list to increase performance when checking a mostly empty quarry

Signed-off-by: Ross Allan <rallanpcl@gmail.com>
This commit is contained in:
Ross Allan 2013-02-12 17:06:53 +00:00
parent 8b0312b12a
commit 814b450719
2 changed files with 33 additions and 20 deletions

View file

@ -58,14 +58,15 @@ public class BlockUtil {
}
public static boolean canChangeBlock(World world, int x, int y, int z) {
if (world.isAirBlock(x, y, z))
return true;
return canChangeBlock(world.getBlockId(x, y, z), world, x, y, z);
}
int blockID = world.getBlockId(x, y, z);
if (Block.blocksList[blockID] == null)
return true;
public static boolean canChangeBlock(int blockID, World world, int x, int y, int z) {
Block block = Block.blocksList[blockID];
if (blockID == 0 || block == null || block.isAirBlock(world, x, y, z))
return true;
if (block.getBlockHardness(world, x, y, z) < 0)
return false;
@ -79,11 +80,12 @@ public class BlockUtil {
}
public static boolean isSoftBlock(World world, int x, int y, int z) {
if (world.isAirBlock(x, y, z))
return true;
return isSoftBlock(world.getBlockId(x, y, z), world, x, y, z);
}
int blockId = world.getBlockId(x, y, z);
public static boolean isSoftBlock(int blockID, World world, int x, int y, int z) {
Block block = Block.blocksList[blockID];
return BuildCraftAPI.softBlocks[blockId] || Block.blocksList[blockId] == null;
return blockID == 0 || block == null || BuildCraftAPI.softBlocks[blockID] || block.isAirBlock(world, x, y, z);
}
}

33
common/buildcraft/factory/TileQuarry.java Normal file → Executable file
View file

@ -75,7 +75,7 @@ public class TileQuarry extends TileMachine implements IMachine, IPowerReceptor,
boolean isDigging = false;
public static int MAX_ENERGY = 15000;
public static final int MAX_ENERGY = 15000;
public TileQuarry() {
powerProvider = PowerFramework.currentFramework.createPowerProvider();
@ -234,7 +234,7 @@ public class TileQuarry extends TileMachine implements IMachine, IPowerReceptor,
headTrajectory = Math.atan2(target[2] - head[2], target[0] - head[0]);
}
private LinkedList<int[]> visitList = Lists.newLinkedList();
private final LinkedList<int[]> visitList = Lists.newLinkedList();
public boolean findTarget(boolean doSet) {
@ -251,7 +251,7 @@ public class TileQuarry extends TileMachine implements IMachine, IPowerReceptor,
if (visitList.isEmpty())
return false;
boolean foundTarget = false;
boolean foundTarget;
int[] target;
do {
if (visitList.isEmpty()) {
@ -260,7 +260,8 @@ public class TileQuarry extends TileMachine implements IMachine, IPowerReceptor,
target = visitList.removeFirst();
boolean alternativeTarget = false;
for (int y = target[1] + 1; y < yCoord + 3; y++) {
if (BlockUtil.canChangeBlock(worldObj, target[0], y, target[2]) && !BlockUtil.isSoftBlock(worldObj, target[0], y, target[2])) {
int blockID = worldObj.getBlockId(target[0], y, target[2]);
if (BlockUtil.canChangeBlock(blockID, worldObj, target[0], y, target[2]) && !BlockUtil.isSoftBlock(blockID, worldObj, target[0], y, target[2])) {
createColumnVisitList();
alternativeTarget = true;
break;
@ -278,6 +279,8 @@ public class TileQuarry extends TileMachine implements IMachine, IPowerReceptor,
*/
private void createColumnVisitList() {
visitList.clear();
Integer[][] columnHeights = new Integer[bluePrintBuilder.bluePrint.sizeX - 2][bluePrintBuilder.bluePrint.sizeZ - 2];
boolean[][] blockedColumns = new boolean[bluePrintBuilder.bluePrint.sizeX - 2][bluePrintBuilder.bluePrint.sizeZ - 2];
for (int searchY = yCoord + 3; searchY >= 0; --searchY) {
int startX, endX, incX;
@ -307,11 +310,20 @@ public class TileQuarry extends TileMachine implements IMachine, IPowerReceptor,
for (int searchZ = startZ; searchZ != endZ; searchZ += incZ) {
if (!blockedColumns[searchX][searchZ]) {
Integer height = columnHeights[searchX][searchZ];
int bx = box.xMin + searchX + 1, by = searchY, bz = box.zMin + searchZ + 1;
if (!BlockUtil.canChangeBlock(worldObj, bx, by, bz)) {
if (height == null)
columnHeights[searchX][searchZ] = height = worldObj.getHeightValue(bx, bz);
if (height < by)
continue;
int blockID = worldObj.getBlockId(bx, by, bz);
if (!BlockUtil.canChangeBlock(blockID, worldObj, bx, by, bz)) {
blockedColumns[searchX][searchZ] = true;
} else if (!BlockUtil.isSoftBlock(worldObj, bx, by, bz)) {
} else if (!BlockUtil.isSoftBlock(blockID, worldObj, bx, by, bz)) {
visitList.add(new int[] { bx, by, bz });
}
// Stop at two planes - generally any obstructions will have been found and will force a recompute prior to this
@ -321,7 +333,6 @@ public class TileQuarry extends TileMachine implements IMachine, IPowerReceptor,
}
}
}
}
@Override
@ -461,7 +472,8 @@ public class TileQuarry extends TileMachine implements IMachine, IPowerReceptor,
}
private boolean isQuarriableBlock(int bx, int by, int bz) {
return BlockUtil.canChangeBlock(worldObj, bx, by, bz) && !BlockUtil.isSoftBlock(worldObj, bx, by, bz);
int blockID = worldObj.getBlockId(bx, by, bz);
return BlockUtil.canChangeBlock(blockID, worldObj, bx, by, bz) && !BlockUtil.isSoftBlock(blockID, worldObj, bx, by, bz);
}
@Override
@ -529,7 +541,6 @@ public class TileQuarry extends TileMachine implements IMachine, IPowerReceptor,
}
int xSize = a.xMax() - a.xMin() + 1;
int ySize = a.yMax() - a.yMin() + 1;
int zSize = a.zMax() - a.zMin() + 1;
if (xSize < 3 || zSize < 3 || ((xSize * zSize) >> 8) >= chunkTicket.getMaxChunkListDepth()) {
@ -544,7 +555,7 @@ public class TileQuarry extends TileMachine implements IMachine, IPowerReceptor,
}
xSize = a.xMax() - a.xMin() + 1;
ySize = a.yMax() - a.yMin() + 1;
int ySize = a.yMax() - a.yMin() + 1;
zSize = a.zMax() - a.zMin() + 1;
box.initialize(a);
@ -555,7 +566,7 @@ public class TileQuarry extends TileMachine implements IMachine, IPowerReceptor,
}
if (useDefault) {
int xMin = 0, zMin = 0;
int xMin, zMin;
ForgeDirection o = ForgeDirection.values()[worldObj.getBlockMetadata(xCoord, yCoord, zCoord)].getOpposite();