001package fr.aumgn.dac2.game.colonnisation;
002
003import java.util.ArrayDeque;
004import java.util.Deque;
005import java.util.HashSet;
006import java.util.Set;
007
008import org.bukkit.World;
009import org.bukkit.block.Block;
010
011import fr.aumgn.bukkitutils.geom.Vector2D;
012import fr.aumgn.dac2.arena.Arena;
013import fr.aumgn.dac2.arena.regions.Pool;
014import fr.aumgn.dac2.config.Color;
015import fr.aumgn.dac2.shape.FlatShape;
016
017public class PoolVisitor {
018
019    private final Color color;
020    private final World world;
021    private final FlatShape shape;
022    private final int y;
023    private final Set<Vector2D> visited;
024    private final Deque<Vector2D> queue;
025
026    private int count;
027
028    public PoolVisitor(Arena arena, Color color) {
029        this(arena.getWorld(), arena.getPool(), color);
030    }
031
032    public PoolVisitor(World world, Pool pool, Color color) {
033        this.color = color;
034        this.world = world;
035        this.shape = pool.getShape();
036        this.y = (int) shape.getMaxY() - 1;
037        this.visited = new HashSet<Vector2D>();
038        this.queue = new ArrayDeque<Vector2D>();
039
040    }
041
042    public int visit(Vector2D pos) {
043        visited.clear();
044        queue.clear();
045        count = 0;
046
047        visited.add(pos);
048        pushNeighbors(pos);
049        while (!queue.isEmpty()) {
050            visit();
051        }
052
053        return count + 1;
054    }
055
056    private boolean isValid(Vector2D pos) {
057        if (!shape.contains2D(pos)) {
058            return false;
059        }
060
061        return isValidBlock(pos);
062    }
063
064    private boolean isValidBlock(Vector2D pos) {
065        Block block = pos.to3D(y).toBlock(world);
066        return block.getType() == color.block && block.getData() == color.data;
067    }
068
069    private void visit() {
070        Vector2D pos = queue.poll();
071        if (visited.contains(pos)) {
072            return;
073        }
074
075        visited.add(pos);
076        if (!isValid(pos)) {
077            return;
078        }
079
080        count++;
081        pushNeighbors(pos);
082    }
083
084    private void pushNeighbors(Vector2D pos) {
085        queue.add(pos.subtractX(1));
086        queue.add(pos.addX(1));
087        queue.add(pos.subtractZ(1));
088        queue.add(pos.addZ(1));
089    }
090}