001package fr.aumgn.dac2.shape.column;
002
003import java.util.Iterator;
004
005import org.apache.commons.lang.Validate;
006import org.bukkit.Material;
007import org.bukkit.World;
008import org.bukkit.block.Block;
009
010import com.google.common.collect.AbstractLinkedIterator;
011
012import fr.aumgn.bukkitutils.geom.Vector;
013import fr.aumgn.bukkitutils.geom.Vector2D;
014import fr.aumgn.dac2.shape.FlatShape;
015
016/**
017 * Represents a column of block in a FlatShape.
018 */
019public class Column implements Iterable<Vector> {
020
021    private final double minY;
022    private final double maxY;
023    private final Vector2D pt2D;
024
025    public Column(FlatShape shape, Vector2D pt2D) {
026        this.minY = shape.getMinY();
027        this.maxY = shape.getMaxY();
028        this.pt2D = pt2D;
029    }
030
031    public Vector2D getPos() {
032        return pt2D;
033    }
034
035    public Vector getBottom() {
036        return pt2D.to3D(minY);
037    }
038
039    public Vector getTop() {
040        return pt2D.to3D(maxY);
041    }
042
043    public Vector get(double y) {
044        Validate.isTrue(y >= minY && y <= maxY);
045        return pt2D.to3D(y);
046    }
047
048    public boolean isWater(World world) {
049        return isWater(world, pt2D.to3D(maxY));
050    }
051
052    public boolean isADAC(World world) {
053        boolean water = false;
054        Vector pt = pt2D.to3D(maxY);
055
056        water =  isWater(world, pt.subtractX(1));
057        water |= isWater(world, pt.addX(1));
058        water |= isWater(world, pt.subtractZ(1));
059        water |= isWater(world, pt.addZ(1));
060
061        return !water;
062    }
063
064    private boolean isWater(World world, Vector pos) {
065        Material type = pos.toBlock(world).getType();
066        return type == Material.WATER || type == Material.STATIONARY_WATER;
067    }
068
069    @Override
070    public Iterator<Vector> iterator() {
071        return new AbstractLinkedIterator<Vector>(pt2D.to3D(minY)) {
072            @Override
073            protected Vector computeNext(Vector pt) {
074                return (pt.getY() >= maxY) ? null : pt.addY(1);
075            }
076        };
077    }
078
079    public void reset(World world) {
080        set(world, Material.STATIONARY_WATER);
081    }
082
083    public void set(World world, Material material) {
084        set(world, material, (short) 0);
085    }
086
087    public void set(World world, Material material, short data) {
088        for (Vector pt : this) {
089            Block block = pt.toBlock(world);
090            block.setType(material);
091            block.setData((byte) data);
092        }
093    }
094
095    public void set(World world, ColumnPattern pattern) {
096        pattern.apply(world, this);
097    }
098}