001package fr.aumgn.dac2.shape; 002 003import java.util.ArrayDeque; 004import java.util.Deque; 005import java.util.HashSet; 006import java.util.Set; 007 008import org.bukkit.Material; 009import org.bukkit.World; 010import org.bukkit.block.Block; 011 012import fr.aumgn.bukkitutils.geom.Vector; 013import fr.aumgn.bukkitutils.geom.Vector2D; 014import fr.aumgn.dac2.DAC; 015import fr.aumgn.dac2.exceptions.TooLargeArbitraryShape; 016 017public class ArbitraryFlatShapeVisitor { 018 019 private static final int MAXIMUM_ITERATION = 100000; 020 021 private final DAC dac; 022 private final World world; 023 private final Material material; 024 private final byte data; 025 026 private final Set<Vector> visited; 027 private final Deque<Vector> queue; 028 029 private final Set<Vector2D> points; 030 private int minY; 031 private int maxY; 032 private int count; 033 034 public ArbitraryFlatShapeVisitor(DAC dac, World world, Vector pos) { 035 this.dac = dac; 036 this.world = world; 037 Block block = pos.toBlock(world); 038 this.material = block.getType(); 039 this.data = block.getData(); 040 041 this.visited = new HashSet<Vector>(); 042 this.queue = new ArrayDeque<Vector>(); 043 this.points = new HashSet<Vector2D>(); 044 045 visited.add(pos); 046 pushNeighbors(pos); 047 points.add(pos.to2D()); 048 minY = maxY = pos.getBlockY(); 049 050 count = 0; 051 } 052 053 public ArbitraryFlatShape visit() { 054 while (!queue.isEmpty()) { 055 visitQueue(); 056 057 count++; 058 if (count > MAXIMUM_ITERATION) { 059 throw new TooLargeArbitraryShape(dac); 060 } 061 } 062 063 return new ArbitraryFlatShape(points, minY, maxY); 064 } 065 066 private void visitQueue() { 067 Vector pos = queue.poll(); 068 if (visited.contains(pos)) { 069 return; 070 } 071 072 visited.add(pos); 073 Block block = pos.toBlock(world); 074 if (block.getType() != material || block.getData() != data) { 075 return; 076 } 077 078 points.add(pos.to2D()); 079 int y = pos.getBlockY(); 080 if (y < minY) { 081 minY = y; 082 } 083 if (y > maxY) { 084 maxY = y; 085 } 086 087 pushNeighbors(pos); 088 } 089 090 private void pushNeighbors(Vector pos) { 091 queue.add(pos.subtractX(1)); 092 queue.add(pos.addX(1)); 093 queue.add(pos.subtractY(1)); 094 queue.add(pos.addY(1)); 095 queue.add(pos.subtractZ(1)); 096 queue.add(pos.addZ(1)); 097 } 098}