public int apply(int[] data) throws MaxChangedBlocksException {
        checkNotNull(data);
        BlockVector3 minY = region.getMinimumPoint();
        int originX = minY.getBlockX();
        int originY = minY.getBlockY();
        int originZ = minY.getBlockZ();
        int maxY = region.getMaximumPoint().getBlockY();
        BlockState fillerAir = BlockTypes.AIR.getDefaultState();
        int blocksChanged = 0;
        BlockState tmpBlock = BlockTypes.AIR.getDefaultState();
        // Apply heightmap
        int index = 0;
        for (int z = 0; z < height; ++z) {
            int zr = z + originZ;
            for (int x = 0; x < width; ++x, index++) {
                if (this.invalid != null && this.invalid[index]) {
                    continue;
                }
                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;
                // 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)
                    BlockState existing = session.getBlock(xr, curHeight, zr);
                    // Skip water/lava
                    if (existing.getBlockType().getMaterial().isMovementBlocker()) {
                        int y0 = newHeight - 1;
                        for (int setY = y0, getY = curHeight - 1; setY >= curHeight; setY--, getY--) {
                            BlockState get;
                            if (getY >= 0 && getY < 256) {
                                get = session.getBlock(xr, getY, zr);
                            } else {
                                get = BlockTypes.AIR.getDefaultState();
                            }
                            if (get != BlockTypes.AIR.getDefaultState()) {
                                tmpBlock = get;
                            }
                            session.setBlock(xr, setY, zr, tmpBlock);
                            ++blocksChanged;
                        }
                        session.setBlock(xr, newHeight, zr, existing);
                        ++blocksChanged;
                    }
                } else if (curHeight > newHeight) {
                    // Set the top block of the column to be the same type
                    // (this could otherwise go wrong with rounding)
                    session.setBlock(xr, newHeight, zr, session.getBlock(xr, curHeight, zr));
                    ++blocksChanged;
                    // Fill rest with air
                    for (int y = newHeight + 1; y <= curHeight; ++y) {
                        session.setBlock(xr, y, zr, fillerAir);
                        ++blocksChanged;
                    }
                }
            }
        }
        // Drop trees to the floor -- TODO
        return blocksChanged;
    }
public int apply(int[] data) throws MaxChangedBlocksException {
        checkNotNull(data);
        BlockVector3 minY = region.getMinimumPoint();
        int originX = minY.getBlockX();
        int originY = minY.getBlockY();
        int originZ = minY.getBlockZ();
        int maxY = region.getMaximumPoint().getBlockY();
        BlockState fillerAir = BlockTypes.AIR.getDefaultState();
        int blocksChanged = 0;
        BlockState tmpBlock = BlockTypes.AIR.getDefaultState();
       
        int index = 0;
        for (int z = 0; z < height; ++z) {
            int zr = z + originZ;
            for (int x = 0; x < width; ++x, index++) {
                if (this.invalid != null && this.invalid[index]) {
                    continue;
                }
                int curHeight = this.data[index];
               
                int newHeight = Math.min(maxY, data[index]);
               
                int xr = x + originX;
               
                if (newHeight > curHeight) {
                   
                    BlockState existing = session.getBlock(xr, curHeight, zr);
                   
                    if (existing.getBlockType().getMaterial().isMovementBlocker()) {
                        int y0 = newHeight - 1;
                        for (int setY = y0, getY = curHeight - 1; setY >= curHeight; setY--, getY--) {
                            BlockState get;
                            if (getY >= 0 && getY < 256) {
                                get = session.getBlock(xr, getY, zr);
                            } else {
                                get = BlockTypes.AIR.getDefaultState();
                            }
                            if (get != BlockTypes.AIR.getDefaultState()) {
                                tmpBlock = get;
                            }
                            session.setBlock(xr, setY, zr, tmpBlock);
                            ++blocksChanged;
                        }
                        session.setBlock(xr, newHeight, zr, existing);
                        ++blocksChanged;
                    }
                } else if (curHeight > newHeight) {
                   
                   
                    session.setBlock(xr, newHeight, zr, session.getBlock(xr, curHeight, zr));
                    ++blocksChanged;
                   
                    for (int y = newHeight + 1; y <= curHeight; ++y) {
                        session.setBlock(xr, y, zr, fillerAir);
                        ++blocksChanged;
                    }
                }
            }
        }
       
        return blocksChanged;
    }
public int apply(int[] data) throws maxchangedblocksexception { checknotnull(data); blockvector3 miny = region.getminimumpoint(); int originx = miny.getblockx(); int originy = miny.getblocky(); int originz = miny.getblockz(); int maxy = region.getmaximumpoint().getblocky(); blockstate fillerair = blocktypes.air.getdefaultstate(); int blockschanged = 0; blockstate tmpblock = blocktypes.air.getdefaultstate(); int index = 0; for (int z = 0; z < height; ++z) { int zr = z + originz; for (int x = 0; x < width; ++x, index++) { if (this.invalid != null && this.invalid[index]) { continue; } int curheight = this.data[index]; int newheight = math.min(maxy, data[index]); int xr = x + originx; if (newheight > curheight) { blockstate existing = session.getblock(xr, curheight, zr); if (existing.getblocktype().getmaterial().ismovementblocker()) { int y0 = newheight - 1; for (int sety = y0, gety = curheight - 1; sety >= curheight; sety--, gety--) { blockstate get; if (gety >= 0 && gety < 256) { get = session.getblock(xr, gety, zr); } else { get = blocktypes.air.getdefaultstate(); } if (get != blocktypes.air.getdefaultstate()) { tmpblock = get; } session.setblock(xr, sety, zr, tmpblock); ++blockschanged; } session.setblock(xr, newheight, zr, existing); ++blockschanged; } } else if (curheight > newheight) { session.setblock(xr, newheight, zr, session.getblock(xr, curheight, zr)); ++blockschanged; for (int y = newheight + 1; y <= curheight; ++y) { session.setblock(xr, y, zr, fillerair); ++blockschanged; } } } } return blockschanged; }