package com.arckenver.nations.object; import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; import java.util.UUID; import org.spongepowered.api.world.Location; import org.spongepowered.api.world.World; import com.flowpowered.math.vector.Vector2i; public class Region { private ArrayList<Rect> rects; private Hashtable<UUID, Rect> extrema; public Region() { this(new ArrayList<Rect>()); } public Region(ArrayList<Rect> rects) { this.rects = rects; this.extrema = new Hashtable<UUID, Rect>(); calculateExtr(); } private void calculateExtr() { for (Rect r : rects) { if (!extrema.containsKey(r.getWorld())) { extrema.put(r.getWorld(), new Rect(r.getWorld(), Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE)); } Rect rect = extrema.get(r.getWorld()); if (r.getMaxX() > rect.getMaxX()) rect.setMaxX(r.getMaxX()); if (r.getMinX() < rect.getMinX()) rect.setMinX(r.getMinX()); if (r.getMaxY() > rect.getMaxY()) rect.setMaxY(r.getMaxY()); if (r.getMinY() < rect.getMinY()) rect.setMinY(r.getMinY()); } } public ArrayList<Rect> getRects() { return rects; } public void addRect(Rect rect) { ArrayList<Rect> toAdd = new ArrayList<Rect>(); toAdd.add(rect); for (Iterator<Rect> it = rects.iterator(); it.hasNext();) { Rect r = it.next(); ArrayList<Rect> futureToAdd = new ArrayList<Rect>(); for (Rect rectToAdd : toAdd) { futureToAdd.addAll(rectToAdd.cutBy(r)); } if (r.useless()) it.remove(); toAdd = futureToAdd; } rects.addAll(toAdd); calculateExtr(); } public void removeRect(Rect rect) { ArrayList<Rect> futureRects = new ArrayList<Rect>(); for (Rect r : rects) { futureRects.addAll(r.cutBy(rect)); } rects = futureRects; calculateExtr(); } public int size() { int s = 0; for (Rect r : rects) { s += r.size(); } return s; } public boolean isInside(Location<World> loc) { Rect extr = extrema.get(loc.getExtent().getUniqueId()); Vector2i p = new Vector2i(loc.getBlockX(), loc.getBlockZ()); if (p.getX() < extr.getMinX() || p.getX() > extr.getMaxX() || p.getY() < extr.getMinY() || p.getY() > extr.getMaxY()) { return false; } for (Rect r : rects) { if (r.isInside(p)) { return true; } } return false; } public boolean isInside(Rect rect) { Rect extr = extrema.get(rect.getWorld()); if (rect.getMaxX() < extr.getMinX() || rect.getMinX() > extr.getMaxX() || rect.getMinY() < extr.getMinX() || rect.getMinY() > extr.getMaxY()) { return false; } ArrayList<Rect> cut = new ArrayList<Rect>(); cut.add(rect); for (Rect r : rects) { ArrayList<Rect> newCut = new ArrayList<Rect>(); for (Rect re : cut) { newCut.addAll(re.cutBy(r)); } cut = newCut; } return cut.isEmpty(); } public boolean isAdjacent(Vector2i point) { for (Rect r : rects) { if (r.isAdjacent(point)) { return true; } } return false; } public boolean isAdjacent(Rect rect) { for (Rect r : rects) { if (r.isAdjacent(rect)) { return true; } } return false; } public boolean intersects(Rect rect) { for (Rect r : rects) { if (r.intersects(rect)) { return true; } } return false; } public float distance(Location<World> loc) { float dist = Float.MAX_VALUE; for (Rect r : rects) { if (loc.getExtent().getUniqueId().equals(r.getWorld())) { dist = Math.min(dist, r.distance(new Vector2i(loc.getBlockX(), loc.getBlockZ()))); } } return dist; } public Region copy() { ArrayList<Rect> rectsCopy = new ArrayList<Rect>(); for (Rect r : rects) { rectsCopy.add(new Rect(r.getWorld(), r.getMinX(), r.getMaxX(), r.getMinY(), r.getMaxY())); } return new Region(rectsCopy); } }