package ring.movement; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlType; import ring.movement.PortalNotFoundException; import ring.movement.LocationManager; import ring.movement.Portal; import ring.nrapi.business.BusinessObject; import ring.commands.WorldObjectSearch; import ring.entities.Entity; import ring.items.Item; import ring.mobiles.Mobile; import ring.persistence.RingConstants; import ring.world.WorldObject; @XmlAccessorType(XmlAccessType.PROPERTY) @XmlRootElement @XmlType( namespace = RingConstants.RING_NAMESPACE, propOrder= { "model", "zoneID", "items", "mobiles", "entities" }) public class Room extends BusinessObject { private static final String NO_EXITS_STRING = "[B][RED]NO EXITS![R][WHITE]"; private List<Entity> entities = new ArrayList<Entity>(); private List<Mobile> mobiles = new ArrayList<Mobile>(); private List<Item> items = new ArrayList<Item>(); private RoomModel model = new RoomModel(); private Zone zone; @XmlElement public RoomModel getModel() { return model; } public void setModel(RoomModel model) { this.model = model; } @XmlElement public String getZoneID() { return "testID"; //return zone.getID(); } public void setZoneID(String id) { //TODO implement setZoneID //if zone already exists, compare the two, and change if necessary //else load new zone corresponding to ID and attempt to set zone to that. } @XmlTransient public Zone getZone() { return zone; } public void setZone(Zone zone) { this.zone = zone; setZoneID(zone.getID()); } @XmlElementWrapper(name = "entities") @XmlElement(name = "entity") public List<Entity> getEntities() { return entities; } public void setEntities(List<Entity> entities) { this.entities = entities; } @XmlElementWrapper(name = "mobiles") @XmlElement(name = "mobile") public List<Mobile> getMobiles() { return mobiles; } public void setMobiles(List<Mobile> mobiles) { this.mobiles = mobiles; } @XmlElementWrapper(name = "items") @XmlElement(name = "item") public List<Item> getItems() { return items; } public void setItems(List<Item> items) { this.items = items; } public void addMobile(Mobile mob) { mobiles.add(mob); mob.setParent(this); } public boolean removeMobile(Mobile mob) { if (mobiles.contains(mob)) { mob.setParent(null); return mobiles.remove(mob); } else { return false; } } public void addEntity(Entity ent) { entities.add(ent); ent.setParent(this); } public boolean removeEntity(Entity ent) { if (entities.contains(ent)) { ent.setParent(null); return entities.remove(ent); } else { return false; } } public void addItem(Item item) { item.setParent(this); items.add(item); } public boolean removeItem(Item item) { if (items.contains(item)) { item.setParent(null); return items.remove(item); } else { return false; } } /** * Convenience method for getting a list of exits in a * Room. Only returns exits that are plainly visible. * That is, it returns exits that have a search DC of 0. * @return The list of exits. */ public String getExitsString() { return getExitsString(0); } /** * Convenience method for getting a list of exits in a Room, * including hidden ones that are visible given the search check * parameter. * @param searchCheck * @return The list of exits found based on the search check result. */ public String getExitsString(int searchCheck) { List<Portal> exits = LocationManager.getPortals(this); if (exits == null) { return NO_EXITS_STRING; } String exitString = "[CYAN]"; //Add all exits to the string that are //that the search check allows us to see. for (Portal p : exits) { if (p.getSearchDC() > 0) { if (searchCheck >= p.getSearchDC()) { exitString += p.getDisplayName() + ", "; } } else { exitString += p.getDisplayName() + ", "; } } //Remove the last ", " and return //Or, if we have nothing... return an empty string. Bit of an ugly check. if (exitString.equals("[CYAN]")) { return ""; } else { return exitString.substring(0, exitString.length() - 2) + "[R]"; } } public String generateBlindExitsString(int searchCheck) { throw new UnsupportedOperationException(); } public String generateRandomOccupantsList(int searchCheck) { throw new UnsupportedOperationException(); } public String getEntityList() { String res = ""; if (entities == null || entities.isEmpty()) return res; StringBuilder sb = new StringBuilder(); for (Entity ent : getEntities()) { sb.append("[R][WHITE]") .append(ent.getName()) .append(" ") .append(ent.getDescriptor()) .append("[R][WHITE].\n"); } return res; } public String getMobileList(Mobile excludedMobile, int spotCheck) { if (mobiles == null || mobiles.isEmpty()) { return ""; } StringBuilder sb = new StringBuilder(); for (Mobile mob : getMobiles()) { if (mob != excludedMobile) { sb.append(mob.getShortDescription()).append("[R][WHITE] is here.\n"); } } return sb.toString(); } public String getMobileList(Mobile excludedMobile) { return getMobileList(excludedMobile, 0); } /** * Convenience method for querying the Location Manager for finding * the desired Portal. This method is equivalent to calling the following method: * LocationManager.getDestination(this, direction). * @param direction The string identifier of the desired Portal. * @return The Portal object, if one exists. null otherwise. */ public Portal getPortal(String direction) { try { return LocationManager.getPortal(this, direction); } catch (PortalNotFoundException e) { //TODO log this. e.printStackTrace(); System.out.println("uh oh"); return null; } } /** * Whether or not a Movable can enter this Room. Default implementation * allows all Movables to enter. * @param mov * @return */ public boolean canEnter(Mobile mov) { return mov.canMove(); } /** * Not specified by this class, because it does not extend WorldObject. * However, it is still useful to have. * @see ring.world.WorldObject#produceSearchList(Class...) * @param dataTypes * @return A list of world objects, filtered by data types. */ public List<WorldObject> produceSearchList(Class<?> ... dataTypes) { List<WorldObject> objs = new ArrayList<WorldObject>(); objs.addAll(this.getMobiles()); objs.addAll(this.getEntities()); return WorldObjectSearch.filterByDataType(objs, dataTypes); } /** * @see ring.world.WorldObject#produceSearchList(List) * @param dataTypes * @return A list of filtered world objects. */ public List<WorldObject> produceSearchList(List<Class<?>> dataTypes) { return produceSearchList(dataTypes.toArray(new Class<?>[0])); } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((entities == null) ? 0 : entities.hashCode()); result = prime * result + ((items == null) ? 0 : items.hashCode()); result = prime * result + ((mobiles == null) ? 0 : mobiles.hashCode()); result = prime * result + ((model == null) ? 0 : model.hashCode()); result = prime * result + ((zone == null) ? 0 : zone.hashCode()); return result; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; Room other = (Room) obj; if (entities == null) { if (other.entities != null) return false; } else if (!entities.equals(other.entities)) return false; if (items == null) { if (other.items != null) return false; } else if (!items.equals(other.items)) return false; if (mobiles == null) { if (other.mobiles != null) return false; } else if (!mobiles.equals(other.mobiles)) return false; if (model == null) { if (other.model != null) return false; } else if (!model.equals(other.model)) return false; if (zone == null) { if (other.zone != null) return false; } else if (!zone.equals(other.zone)) return false; return true; } }