package rescuecore2.standard.entities; import rescuecore2.worldmodel.Entity; import rescuecore2.worldmodel.EntityID; import rescuecore2.worldmodel.Property; import rescuecore2.worldmodel.WorldModel; import rescuecore2.worldmodel.EntityListener; import rescuecore2.worldmodel.properties.IntProperty; import rescuecore2.worldmodel.properties.EntityRefListProperty; import rescuecore2.misc.Pair; import java.util.List; import java.util.ArrayList; import java.awt.Shape; import java.awt.Polygon; /** The Area object. */ public abstract class Area extends StandardEntity { private IntProperty x; private IntProperty y; private EdgeListProperty edges; private EntityRefListProperty blockades; private Shape shape; private int[] apexList; private List<EntityID> neighbours; /** Construct a subclass of Area with entirely undefined property values. @param id The ID of this entity. */ protected Area(EntityID id) { super(id); x = new IntProperty(StandardPropertyURN.X); y = new IntProperty(StandardPropertyURN.Y); edges = new EdgeListProperty(StandardPropertyURN.EDGES); blockades = new EntityRefListProperty(StandardPropertyURN.BLOCKADES); registerProperties(x, y, edges, blockades); shape = null; apexList = null; neighbours = null; addEntityListener(new EdgesListener()); } /** Area copy constructor. @param other The Area to copy. */ protected Area(Area other) { super(other); x = new IntProperty(other.x); y = new IntProperty(other.y); edges = new EdgeListProperty(other.edges); blockades = new EntityRefListProperty(other.blockades); registerProperties(x, y, edges, blockades); shape = null; apexList = null; neighbours = null; addEntityListener(new EdgesListener()); } @Override public Pair<Integer, Integer> getLocation(WorldModel<? extends StandardEntity> world) { return new Pair<Integer, Integer>(x.getValue(), y.getValue()); } @Override public Property getProperty(String urn) { StandardPropertyURN type; try { type = StandardPropertyURN.fromString(urn); } catch (IllegalArgumentException e) { return super.getProperty(urn); } switch (type) { case X: return x; case Y: return y; case EDGES: return edges; case BLOCKADES: return blockades; default: return super.getProperty(urn); } } /** Get the X property. @return The X property. */ public IntProperty getXProperty() { return x; } /** Get the X coordinate. @return The X coordinate. */ public int getX() { return x.getValue(); } /** Set the X coordinate. @param x The new X coordinate. */ public void setX(int x) { this.x.setValue(x); } /** Find out if the X property has been defined. @return True if the X property has been defined, false otherwise. */ public boolean isXDefined() { return x.isDefined(); } /** Undefine the X property. */ public void undefineX() { x.undefine(); } /** Get the Y property. @return The Y property. */ public IntProperty getYProperty() { return y; } /** Get the Y coordinate. @return The Y coordinate. */ public int getY() { return y.getValue(); } /** Set the Y coordinate. @param y The new y coordinate. */ public void setY(int y) { this.y.setValue(y); } /** Find out if the Y property has been defined. @return True if the Y property has been defined, false otherwise. */ public boolean isYDefined() { return y.isDefined(); } /** Undefine the Y property. */ public void undefineY() { y.undefine(); } /** Get the edges property. @return The edges property. */ public EdgeListProperty getEdgesProperty() { return edges; } /** Get the edges of this area. @return The edges. */ public List<Edge> getEdges() { return edges.getValue(); } /** Set the edges. @param edges The new edges. */ public void setEdges(List<Edge> edges) { this.edges.setEdges(edges); } /** Find out if the edges property has been defined. @return True if the edges property has been defined, false otherwise. */ public boolean isEdgesDefined() { return edges.isDefined(); } /** Undefine the edges property. */ public void undefineEdges() { edges.undefine(); } /** Get the blockades property. @return The blockades property. */ public EntityRefListProperty getBlockadesProperty() { return blockades; } /** Get the blockades in this area. @return The blockades. */ public List<EntityID> getBlockades() { return blockades.getValue(); } /** Set the blockades in this area. @param blockades The new blockades. */ public void setBlockades(List<EntityID> blockades) { this.blockades.setValue(blockades); } /** Find out if the blockades property has been defined. @return True if the blockades property has been defined, false otherwise. */ public boolean isBlockadesDefined() { return blockades.isDefined(); } /** Undefine the blockades property. */ public void undefineBlockades() { blockades.undefine(); } /** Get the neighbours of this area. @return The neighbours. */ public List<EntityID> getNeighbours() { if (neighbours == null) { neighbours = new ArrayList<EntityID>(); for (Edge next : edges.getValue()) { if (next.isPassable()) { neighbours.add(next.getNeighbour()); } } } return neighbours; } /** Get the edge that crosses to a particular neighbour. @param neighbour The neighbour ID. @return The edge that crosses to the given neighbour, or null if no edges border that neighbour. */ public Edge getEdgeTo(EntityID neighbour) { for (Edge next : getEdges()) { if (neighbour.equals(next.getNeighbour())) { return next; } } return null; } /** Get the list of apexes for this area. @return The list of apexes. */ public int[] getApexList() { if (apexList == null) { List<Edge> e = getEdges(); apexList = new int[e.size() * 2]; int i = 0; for (Edge next : e) { apexList[i++] = next.getStartX(); apexList[i++] = next.getStartY(); } } return apexList; } /** Get this area as a Java Shape object. @return A Shape describing this area. */ public Shape getShape() { if (shape == null) { int[] apexes = getApexList(); int count = apexes.length / 2; int[] xs = new int[count]; int[] ys = new int[count]; for (int i = 0; i < count; ++i) { xs[i] = apexes[i * 2]; ys[i] = apexes[i * 2 + 1]; } shape = new Polygon(xs, ys, count); } return shape; } private class EdgesListener implements EntityListener { @Override public void propertyChanged(Entity e, Property p, Object oldValue, Object newValue) { if (p == edges) { shape = null; apexList = null; neighbours = null; } } } }