*/
public int apply(int[] data) throws MaxChangedBlocksException {
checkNotNull(data);
Vector minY = region.getMinimumPoint();
int originX = minY.getBlockX();
int originY = minY.getBlockY();
int originZ = minY.getBlockZ();
int maxY = region.getMaximumPoint().getBlockY();
BaseBlock fillerAir = new BaseBlock(BlockID.AIR);
int blocksChanged = 0;
// Apply heightmap
for (int z = 0; z < height; ++z) {
for (int x = 0; x < width; ++x) {
int index = z * width + x;
int curHeight = this.data[index];
// Clamp newHeight within the selection area
int newHeight = Math.min(maxY, data[index]);
// Offset x,z to be 'real' coordinates
int xr = x + originX;
int zr = z + originZ;
// We are keeping the topmost blocks so take that in account for the scale
double scale = (double) (curHeight - originY) / (double) (newHeight - originY);
// Depending on growing or shrinking we need to start at the bottom or top
if (newHeight > curHeight) {
// Set the top block of the column to be the same type (this might go wrong with rounding)
BaseBlock existing = session.getBlock(new Vector(xr, curHeight, zr));
// Skip water/lava
if (existing.getType() != BlockID.WATER && existing.getType() != BlockID.STATIONARY_WATER
&& existing.getType() != BlockID.LAVA && existing.getType() != BlockID.STATIONARY_LAVA) {
session.setBlock(new Vector(xr, newHeight, zr), existing);
++blocksChanged;
// Grow -- start from 1 below top replacing airblocks
for (int y = newHeight - 1 - originY; y >= 0; --y) {
int copyFrom = (int) (y * scale);
session.setBlock(new Vector(xr, originY + y, zr), session.getBlock(new Vector(xr, originY + copyFrom, zr)));
++blocksChanged;
}
}
} else if (curHeight > newHeight) {
// Shrink -- start from bottom
for (int y = 0; y < newHeight - originY; ++y) {
int copyFrom = (int) (y * scale);
session.setBlock(new Vector(xr, originY + y, zr), session.getBlock(new Vector(xr, originY + copyFrom, zr)));
++blocksChanged;
}
// Set the top block of the column to be the same type
// (this could otherwise go wrong with rounding)
session.setBlock(new Vector(xr, newHeight, zr), session.getBlock(new Vector(xr, curHeight, zr)));
++blocksChanged;
// Fill rest with air
for (int y = newHeight + 1; y <= curHeight; ++y) {
session.setBlock(new Vector(xr, y, zr), fillerAir);
++blocksChanged;
}
}
}
}