package com.planet_ink.coffee_mud.Libraries; import com.planet_ink.coffee_mud.core.interfaces.*; import com.planet_ink.coffee_mud.core.*; import com.planet_ink.coffee_mud.core.CMSecurity.DbgFlag; import com.planet_ink.coffee_mud.core.collections.*; import com.planet_ink.coffee_mud.core.collections.MultiEnumeration.MultiEnumeratorBuilder; import com.planet_ink.coffee_mud.core.interfaces.BoundedObject; import com.planet_ink.coffee_mud.core.interfaces.BoundedObject.BoundedCube; import com.planet_ink.coffee_mud.core.interfaces.MsgListener; import com.planet_ink.coffee_mud.core.interfaces.PhysicalAgent; import com.planet_ink.coffee_mud.core.interfaces.PrivateProperty; import com.planet_ink.coffee_mud.core.interfaces.SpaceObject; import com.planet_ink.coffee_mud.Libraries.interfaces.*; import com.planet_ink.coffee_mud.Abilities.interfaces.*; import com.planet_ink.coffee_mud.Areas.interfaces.*; import com.planet_ink.coffee_mud.Behaviors.interfaces.*; import com.planet_ink.coffee_mud.CharClasses.interfaces.*; import com.planet_ink.coffee_mud.Commands.interfaces.*; import com.planet_ink.coffee_mud.Common.interfaces.*; import com.planet_ink.coffee_mud.Exits.interfaces.*; import com.planet_ink.coffee_mud.Items.interfaces.*; import com.planet_ink.coffee_mud.Items.interfaces.TechComponent.ShipDir; import com.planet_ink.coffee_mud.Locales.interfaces.*; import com.planet_ink.coffee_mud.MOBS.interfaces.*; import com.planet_ink.coffee_mud.Races.interfaces.*; import java.io.IOException; import java.lang.ref.WeakReference; import java.math.BigInteger; import java.util.*; import java.util.Map.Entry; /* Copyright 2001-2016 Bo Zimmerman Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ public class CMMap extends StdLibrary implements WorldMap { @Override public String ID(){return "CMMap";} public final int QUADRANT_WIDTH = 10; public static MOB deityStandIn = null; public long lastVReset = 0; public CMNSortSVec<Area> areasList = new CMNSortSVec<Area>(); public List<Deity> deitiesList = new SVector<Deity>(); public List<BoardableShip> shipList = new SVector<BoardableShip>(); public List<PostOffice> postOfficeList = new SVector<PostOffice>(); public List<Auctioneer> auctionHouseList = new SVector<Auctioneer>(); public List<Banker> bankList = new SVector<Banker>(); public RTree<SpaceObject> space = new RTree<SpaceObject>(); protected Map<String,Object>SCRIPT_HOST_SEMAPHORES = new Hashtable<String,Object>(); protected static final Comparator<Area> areaComparator = new Comparator<Area>() { @Override public int compare(Area o1, Area o2) { if(o1==null) return (o2==null)?0:-1; return o1.Name().compareToIgnoreCase(o2.Name()); } }; public Map<Integer,List<WeakReference<MsgListener>>> globalHandlers = new SHashtable<Integer,List<WeakReference<MsgListener>>>(); public Map<String,SLinkedList<LocatedPair>> scriptHostMap = new STreeMap<String,SLinkedList<LocatedPair>>(); private static final long EXPIRE_1MIN = 1*60*1000; private static final long EXPIRE_5MINS = 5*60*1000; private static final long EXPIRE_10MINS = 10*60*1000; private static final long EXPIRE_20MINS = 20*60*1000; private static final long EXPIRE_30MINS = 30*60*1000; private static final long EXPIRE_1HOUR = 60*60*1000; private static class LocatedPairImpl implements LocatedPair { final WeakReference<Room> roomW; final WeakReference<PhysicalAgent> objW; private LocatedPairImpl(Room room, PhysicalAgent host) { roomW = new WeakReference<Room>(room); objW = new WeakReference<PhysicalAgent>(host); } @Override public Room room() { return roomW.get(); } @Override public PhysicalAgent obj() { return objW.get(); } } private static Filterer<Area> planetsAreaFilter=new Filterer<Area>() { @Override public boolean passesFilter(Area obj) { return (obj instanceof SpaceObject) && (!(obj instanceof SpaceShip)); } }; private static Filterer<Area> mundaneAreaFilter=new Filterer<Area>() { @Override public boolean passesFilter(Area obj) { return !(obj instanceof SpaceObject); } }; protected int getGlobalIndex(List<Environmental> list, String name) { if(list.size()==0) return -1; int start=0; int end=list.size()-1; while(start<=end) { final int mid=(end+start)/2; final int comp=list.get(mid).Name().compareToIgnoreCase(name); if(comp==0) return mid; else if(comp>0) end=mid-1; else start=mid+1; } return -1; } @Override public void renamedArea(Area theA) { areasList.reSort(theA); } // areas @Override public int numAreas() { return areasList.size(); } @Override public void addArea(Area newOne) { areasList.add(newOne); if((newOne instanceof SpaceObject)&&(!space.contains((SpaceObject)newOne))) space.insert((SpaceObject)newOne); } @Override public void delArea(Area oneToDel) { areasList.remove(oneToDel); if((oneToDel instanceof SpaceObject)&&(space.contains((SpaceObject)oneToDel))) space.remove((SpaceObject)oneToDel); Resources.removeResource("SYSTEM_AREA_FINDER_CACHE"); } @Override public Area getModelArea(Area A) { if(A!=null) { if(CMath.bset(A.flags(),Area.FLAG_INSTANCE_CHILD)) { int x=A.Name().indexOf('_'); if(x>0) { Area A2=getArea(A.Name().substring(x+1)); if(A2!=null) return A2; } } } return A; } @Override public Area getArea(String calledThis) { final Map<String,Area> finder=getAreaFinder(); Area A=finder.get(calledThis.toLowerCase()); if((A!=null)&&(!A.amDestroyed())) return A; A=areasList.find(calledThis); if((A!=null)&&(!A.amDestroyed())) { if(!CMProps.getBoolVar(CMProps.Bool.MAPFINDSNOCACHE)) finder.put(calledThis.toLowerCase(), A); return A; } return null; } @Override public Area findAreaStartsWith(String calledThis) { final boolean disableCaching=CMProps.getBoolVar(CMProps.Bool.MAPFINDSNOCACHE); Area A=getArea(calledThis); if(A!=null) return A; final Map<String,Area> finder=getAreaFinder(); A=finder.get(calledThis.toLowerCase()); if((A!=null)&&(!A.amDestroyed())) return A; for(final Enumeration<Area> a=areas();a.hasMoreElements();) { A=a.nextElement(); if(A.Name().toUpperCase().startsWith(calledThis)) { if(!disableCaching) finder.put(calledThis.toLowerCase(), A); return A; } } return null; } @Override public Area findArea(String calledThis) { final boolean disableCaching=CMProps.getBoolVar(CMProps.Bool.MAPFINDSNOCACHE); Area A=findAreaStartsWith(calledThis); if(A!=null) return A; final Map<String,Area> finder=getAreaFinder(); A=finder.get(calledThis.toLowerCase()); if((A!=null)&&(!A.amDestroyed())) return A; for(final Enumeration<Area> a=areas();a.hasMoreElements();) { A=a.nextElement(); if(CMLib.english().containsString(A.Name(),calledThis)) { if(!disableCaching) finder.put(calledThis.toLowerCase(), A); return A; } } return null; } @Override public Enumeration<Area> areas() { return new IteratorEnumeration<Area>(areasList.iterator()); } @Override public Enumeration<Area> areasPlusShips() { final MultiEnumeration<Area> m=new MultiEnumeration<Area>(new IteratorEnumeration<Area>(areasList.iterator())); m.addEnumeration(shipAreaEnumerator(null)); return m; } @Override public Enumeration<Area> mundaneAreas() { return new FilteredEnumeration<Area>(areas(),mundaneAreaFilter); } @Override public Enumeration<Area> spaceAreas() { return new FilteredEnumeration<Area>(areas(),planetsAreaFilter); } @Override public Enumeration<String> roomIDs() { return new Enumeration<String>() { private volatile Enumeration<String> roomIDEnumerator=null; private volatile Enumeration<Area> areaEnumerator=areasPlusShips(); @Override public boolean hasMoreElements() { boolean hasMore = (roomIDEnumerator != null) && roomIDEnumerator.hasMoreElements(); while(!hasMore) { if((areaEnumerator == null)||(!areaEnumerator.hasMoreElements())) { roomIDEnumerator=null; areaEnumerator = null; return false; } final Area A=areaEnumerator.nextElement(); roomIDEnumerator=A.getProperRoomnumbers().getRoomIDs(); hasMore = (roomIDEnumerator != null) && roomIDEnumerator.hasMoreElements(); } return hasMore; } @Override public String nextElement() { return hasMoreElements() ? (String) roomIDEnumerator.nextElement() : null; } }; } @Override public Area getFirstArea() { if (areas().hasMoreElements()) return areas().nextElement(); return null; } @Override public Area getDefaultParentArea() { final String defaultParentAreaName=CMProps.getVar(CMProps.Str.DEFAULTPARENTAREA); if((defaultParentAreaName!=null)&&(defaultParentAreaName.trim().length()>0)) return getArea(defaultParentAreaName.trim()); return null; } @Override public Area getRandomArea() { Area A=null; while((numAreas()>0)&&(A==null)) { try { A=areasList.get(CMLib.dice().roll(1,numAreas(),-1)); }catch(final ArrayIndexOutOfBoundsException e){} } return A; } @Override public void addGlobalHandler(MsgListener E, int category) { if(E==null) return; List<WeakReference<MsgListener>> V=globalHandlers.get(Integer.valueOf(category)); if(V==null) { V=new SLinkedList<WeakReference<MsgListener>>(); globalHandlers.put(Integer.valueOf(category),V); } synchronized(V) { for (final WeakReference<MsgListener> W : V) { if(W.get()==E) return; } V.add(new WeakReference<MsgListener>(E)); } } @Override public void delGlobalHandler(MsgListener E, int category) { final List<WeakReference<MsgListener>> V=globalHandlers.get(Integer.valueOf(category)); if((E==null)||(V==null)) return; synchronized(V) { for (final WeakReference<MsgListener> W : V) { if(W.get()==E) V.remove(W); } } } @Override public MOB deity() { if(deities().hasMoreElements()) return deities().nextElement(); if((deityStandIn==null) ||(deityStandIn.amDestroyed()) ||(deityStandIn.amDead()) ||(deityStandIn.location()==null) ||(deityStandIn.location().isInhabitant(deityStandIn))) { if(deityStandIn!=null) deityStandIn.destroy(); final MOB everywhereMOB=CMClass.getMOB("StdMOB"); everywhereMOB.setName(L("god")); everywhereMOB.setLocation(this.getRandomRoom()); deityStandIn=everywhereMOB; } return deityStandIn; } @Override public MOB getFactoryMOBInAnyRoom() { return getFactoryMOB(this.getRandomRoom()); } @Override public MOB getFactoryMOB(Room R) { final MOB everywhereMOB=CMClass.getFactoryMOB(); everywhereMOB.setName(L("somebody")); everywhereMOB.setLocation(R); return everywhereMOB; } @Override public boolean isObjectInSpace(SpaceObject O) { synchronized(space) { return space.contains(O); } } @Override public void delObjectInSpace(SpaceObject O) { synchronized(space) { space.remove(O); } } @Override public void addObjectToSpace(SpaceObject O, long[] coords) { synchronized(space) { O.coordinates()[0]=coords[0]; O.coordinates()[1]=coords[1]; O.coordinates()[2]=coords[2]; space.insert(O); // won't accept dups, so is ok } } @Override public long getDistanceFrom(final long[] coord1, final long[] coord2) { return Math.round(Math.sqrt(CMath.mul((coord1[0]-coord2[0]),(coord1[0]-coord2[0])) +CMath.mul((coord1[1]-coord2[1]),(coord1[1]-coord2[1])) +CMath.mul((coord1[2]-coord2[2]),(coord1[2]-coord2[2])))); } @Override public long getDistanceFrom(SpaceObject O1, SpaceObject O2) { return getDistanceFrom(O1.coordinates(),O2.coordinates()); } @Override public String getSectorName(long[] coordinates) { final String[] xsecs=CMProps.getListFileStringList(CMProps.ListFile.TECH_SECTOR_X_NAMES); final String[] ysecs=CMProps.getListFileStringList(CMProps.ListFile.TECH_SECTOR_Y_NAMES); final String[] zsecs=CMProps.getListFileStringList(CMProps.ListFile.TECH_SECTOR_Z_NAMES); final long dmsPerXSector = SpaceObject.Distance.GalaxyRadius.dm / xsecs.length; final long dmsPerYSector = SpaceObject.Distance.GalaxyRadius.dm / ysecs.length; final long dmsPerZSector = SpaceObject.Distance.GalaxyRadius.dm / zsecs.length; final int secDeX = (int)((coordinates[0] % SpaceObject.Distance.GalaxyRadius.dm) / dmsPerXSector / 2); final int secDeY = (int)((coordinates[1] % SpaceObject.Distance.GalaxyRadius.dm) / dmsPerYSector / 2); final int secDeZ = (int)((coordinates[2] % SpaceObject.Distance.GalaxyRadius.dm) / dmsPerZSector / 2); final StringBuilder sectorName = new StringBuilder(""); sectorName.append(xsecs[(secDeX < 0)?(xsecs.length+secDeX):secDeX]).append(" "); sectorName.append(ysecs[(secDeY < 0)?(ysecs.length+secDeY):secDeY]).append(" "); sectorName.append(zsecs[(secDeZ < 0)?(zsecs.length+secDeZ):secDeZ]); return sectorName.toString(); } @Override public long[] getInSectorCoords(long[] coordinates) { final String[] xsecs=CMProps.getListFileStringList(CMProps.ListFile.TECH_SECTOR_X_NAMES); final String[] ysecs=CMProps.getListFileStringList(CMProps.ListFile.TECH_SECTOR_Y_NAMES); final String[] zsecs=CMProps.getListFileStringList(CMProps.ListFile.TECH_SECTOR_Z_NAMES); final long dmsPerXSector = SpaceObject.Distance.GalaxyRadius.dm / xsecs.length; final long dmsPerYSector = SpaceObject.Distance.GalaxyRadius.dm / ysecs.length; final long dmsPerZSector = SpaceObject.Distance.GalaxyRadius.dm / zsecs.length; final int secDeX = (int)((coordinates[0] % SpaceObject.Distance.GalaxyRadius.dm) / dmsPerXSector / (2 * (coordinates[0]<0?-1:1))); final int secDeY = (int)((coordinates[1] % SpaceObject.Distance.GalaxyRadius.dm) / dmsPerYSector / (2 * (coordinates[0]<0?-1:1))); final int secDeZ = (int)((coordinates[2] % SpaceObject.Distance.GalaxyRadius.dm) / dmsPerZSector / (2 * (coordinates[0]<0?-1:1))); long[] sectorCoords = Arrays.copyOf(coordinates, 3); for(int i=0;i<sectorCoords.length;i++) { if(sectorCoords[i]<0) sectorCoords[i]*=-1; } sectorCoords[0] -= (secDeX * dmsPerXSector) / 1000; sectorCoords[1] -= (secDeY * dmsPerYSector) / 1000; sectorCoords[2] -= (secDeZ * dmsPerZSector) / 1000; return sectorCoords; } @Override public void moveSpaceObject(SpaceObject O, double[] newDirection, long newAccelleration) { final double directionYaw = O.direction()[0]; double directionPitch = O.direction()[1]; if(directionPitch > Math.PI) directionPitch = Math.abs(Math.PI-directionPitch); final double facingYaw = newDirection[0]; double facingPitch = newDirection[1]; if(facingPitch > Math.PI) facingPitch = Math.abs(Math.PI-facingPitch); final double currentSpeed = O.speed(); final double acceleration = newAccelleration; final double directionCombinedAngle = directionYaw + directionPitch; final double facingCombinedAngle = facingYaw + facingPitch; final double anglesDelta = (directionCombinedAngle > facingCombinedAngle) ? (directionCombinedAngle - facingCombinedAngle) : (facingCombinedAngle - directionCombinedAngle); final double yawDelta = (directionYaw > facingYaw) ? (directionYaw - facingYaw) : (facingYaw - directionYaw); final double pitchDelta = (directionPitch > facingPitch) ? (directionPitch - facingPitch) : (facingPitch - directionPitch); final double accelerationMultiplier = acceleration / currentSpeed; double newDirectionYaw; if(yawDelta < 0.1) newDirectionYaw = directionYaw; else newDirectionYaw = directionYaw + ((directionYaw > facingYaw) ? -(accelerationMultiplier * Math.sin(yawDelta)) : (accelerationMultiplier * Math.sin(yawDelta))); if (newDirectionYaw < 0.0) newDirectionYaw = (Math.PI * 2.0) + newDirectionYaw; double newDirectionPitch; if(pitchDelta < 0.1) newDirectionPitch = directionPitch; else newDirectionPitch = directionPitch + ((directionPitch > facingPitch) ? -(accelerationMultiplier * Math.sin(pitchDelta)) : (accelerationMultiplier * Math.sin(pitchDelta))); if (newDirectionPitch < 0.0) newDirectionPitch = (Math.PI * 2.0) + newDirectionPitch; double newSpeed = currentSpeed + (acceleration * Math.cos(anglesDelta)); if(newSpeed < 0) { newSpeed = -newSpeed; newDirectionYaw = facingYaw; newDirectionPitch = facingPitch; } if((O.direction()[0]>Math.PI)&&(O.direction()[1]<=Math.PI)) newDirectionPitch=Math.PI+newDirectionPitch; O.direction()[0]=newDirectionYaw; O.direction()[1]=newDirectionPitch; O.setSpeed(newSpeed); } @Override public TechComponent.ShipDir getDirectionFromDir(double[] facing, double roll, double[] direction) { double yD = ((Math.toDegrees(facing[0]) % 360.0) - (Math.toDegrees(facing[0]) % 360.0)) % 360.0; if(yD < 0) yD = 360.0 + yD; double pD = ((Math.toDegrees(facing[1]) % 180.0) - (Math.toDegrees(direction[1]) % 180.0)) % 180.0; if(pD < 0) pD = 180.0 + pD; double rD = (yD + (Math.toDegrees(roll) % 360.0)) % 360.0; if(rD < 0) rD = 360.0 + rD; if(pD<45 || pD > 135) { if(yD < 45.0 || yD > 315.0) return ShipDir.AFT; if(yD> 135.0 && yD < 225.0) return ShipDir.FORWARD; } if(rD >= 315.0 || rD<45.0) return ShipDir.DORSEL; if(rD >= 45.0 && rD <135.0) return ShipDir.STARBOARD; if(rD >= 135.0 && rD <225.0) return ShipDir.VENTRAL; if(rD >= 225.0 && rD <315.0) return ShipDir.PORT; return ShipDir.AFT; } @Override public double[] getDirection(SpaceObject FROM, SpaceObject TO) { final double[] dir=new double[2]; final double x=TO.coordinates()[0]-FROM.coordinates()[0]; final double y=TO.coordinates()[1]-FROM.coordinates()[1]; final double z=TO.coordinates()[2]-FROM.coordinates()[2]; if((x!=0)||(y!=0)) { if(x<0) dir[0]=Math.PI-Math.asin(y/Math.sqrt((x*x)+(y*y))); else dir[0]=Math.asin(y/Math.sqrt((x*x)+(y*y))); } if((x!=0)||(y!=0)||(z!=0)) dir[1]=Math.acos(z/Math.sqrt((z*z)+(y*y)+(x*x))); if(dir[1] > Math.PI) dir[1] = Math.abs(Math.PI-dir[1]); return dir; } protected void moveSpaceObject(SpaceObject O, long x, long y, long z) { synchronized(space) { final boolean reAdd=space.contains(O); if(reAdd) space.remove(O); O.coordinates()[0]=x; O.coordinates()[1]=y; O.coordinates()[2]=z; if(reAdd) space.insert(O); } } @Override public void moveSpaceObject(SpaceObject O, long[] coords) { moveSpaceObject(O, coords[0], coords[1], coords[2]); } @Override public void moveSpaceObject(SpaceObject O) { if(O.speed()>0) { final double x1=Math.cos(O.direction()[0])*Math.sin(O.direction()[1]); final double y1=Math.sin(O.direction()[0])*Math.sin(O.direction()[1]); final double z1=Math.cos(O.direction()[1]); moveSpaceObject(O,O.coordinates()[0]+Math.round(CMath.mul(O.speed(),x1)), O.coordinates()[1]+Math.round(CMath.mul(O.speed(),y1)), O.coordinates()[2]+Math.round(CMath.mul(O.speed(),z1))); } } @Override public long[] moveSpaceObject(final long[] coordinates, final double[] direction, long speed) { if(speed>0) { final double x1=Math.cos(direction[0])*Math.sin(direction[1]); final double y1=Math.sin(direction[0])*Math.sin(direction[1]); final double z1=Math.cos(direction[1]); return new long[]{coordinates[0]+Math.round(CMath.mul(speed,x1)), coordinates[1]+Math.round(CMath.mul(speed,y1)), coordinates[2]+Math.round(CMath.mul(speed,z1))}; } return coordinates; } @Override public long[] getLocation(long[] oldLocation, double[] direction, long distance) { final double x1=Math.cos(direction[0])*Math.sin(direction[1]); final double y1=Math.sin(direction[0])*Math.sin(direction[1]); final double z1=Math.cos(direction[1]); final long[] location=new long[3]; location[0]=oldLocation[0]+Math.round(CMath.mul(distance,x1)); location[1]=oldLocation[1]+Math.round(CMath.mul(distance,y1)); location[2]=oldLocation[2]+Math.round(CMath.mul(distance,z1)); return location; } @Override public long getRelativeSpeed(SpaceObject O1, SpaceObject O2) { return Math.round(Math.sqrt(( CMath.bigMultiply(O1.speed(),O1.coordinates()[0]) .subtract(CMath.bigMultiply(O2.speed(),O2.coordinates()[0]).multiply(CMath.bigMultiply(O1.speed(),O1.coordinates()[0]))) .subtract(CMath.bigMultiply(O2.speed(),O2.coordinates()[0]))) .add(CMath.bigMultiply(O1.speed(),O1.coordinates()[1]) .subtract(CMath.bigMultiply(O2.speed(),O2.coordinates()[1]).multiply(CMath.bigMultiply(O1.speed(),O1.coordinates()[1]))) .subtract(CMath.bigMultiply(O2.speed(),O2.coordinates()[1]))) .add(CMath.bigMultiply(O1.speed(),O1.coordinates()[2]) .subtract(CMath.bigMultiply(O2.speed(),O2.coordinates()[2]).multiply(CMath.bigMultiply(O1.speed(),O1.coordinates()[2]))) .subtract(CMath.bigMultiply(O2.speed(),O2.coordinates()[2]))).doubleValue())); } @Override public SpaceObject findSpaceObject(String s, boolean exactOnly) { final Iterable<SpaceObject> i=new Iterable<SpaceObject>() { @Override public Iterator<SpaceObject> iterator() { return new EnumerationIterator<SpaceObject>(space.objects()); } }; return (SpaceObject)CMLib.english().fetchEnvironmental(i, s, exactOnly); } @Override public SpaceObject getSpaceObject(CMObject o, boolean ignoreMobs) { if(o instanceof SpaceObject) return (SpaceObject)o; if(o instanceof Item) { if(((Item)o).container()!=null) return getSpaceObject(((Item)o).container(),ignoreMobs); else return getSpaceObject(((Item)o).owner(),ignoreMobs); } if(o instanceof MOB) return ignoreMobs?null:getSpaceObject(((MOB)o).location(),false); if(o instanceof Room) return getSpaceObject(((Room)o).getArea(),ignoreMobs); if(o instanceof Area) for(final Enumeration<Area> a=((Area)o).getParents();a.hasMoreElements();) { final SpaceObject obj=getSpaceObject(a.nextElement(),ignoreMobs); if(obj != null) return obj; } return null; } @Override public Enumeration<SpaceObject> getSpaceObjects() { return this.space.objects(); } @Override public Enumeration<Entry<SpaceObject, List<WeakReference<TrackingVector<SpaceObject>>>>> getSpaceObjectEntries() { return this.space.objectEntries(); } @Override public List<SpaceObject> getSpaceObjectsByCenterpointWithin(final long[] centerCoordinates, long minDistance, long maxDistance) { final List<SpaceObject> within=new ArrayList<SpaceObject>(1); if((centerCoordinates==null)||(centerCoordinates.length!=3)) return within; synchronized(space) { space.query(within, new BoundedObject.BoundedCube(centerCoordinates, maxDistance)); } if(within.size()<1) return within; for (final Iterator<SpaceObject> o=within.iterator();o.hasNext();) { SpaceObject O=o.next(); final long dist=getDistanceFrom(O.coordinates(),centerCoordinates); if((dist<minDistance)||(dist>maxDistance)) o.remove(); } return within; } @Override public List<SpaceObject> getSpaceObjectsWithin(final SpaceObject ofObj, long minDistance, long maxDistance) { final List<SpaceObject> within=new ArrayList<SpaceObject>(1); if(ofObj==null) return within; synchronized(space) { space.query(within, new BoundedObject.BoundedCube(ofObj.coordinates(), maxDistance)); } for (final Iterator<SpaceObject> o=within.iterator();o.hasNext();) { SpaceObject O=o.next(); if(O!=ofObj) { final long dist=Math.round(Math.abs(getDistanceFrom(O,ofObj) - O.radius() - ofObj.radius())); if((dist<minDistance)||(dist>maxDistance)) o.remove(); } } if(within.size()<=1) return within; Collections.sort(within, new Comparator<SpaceObject>() { @Override public int compare(SpaceObject o1, SpaceObject o2) { final long distTo1=getDistanceFrom(o1,ofObj); final long distTo2=getDistanceFrom(o2,ofObj); if(distTo1==distTo2) return 0; return distTo1>distTo2?1:-1; } }); return within; } @Override public String createNewExit(Room from, Room room, int direction) { Room opRoom=from.rawDoors()[direction]; if((opRoom!=null)&&(opRoom.roomID().length()==0)) opRoom=null; Room reverseRoom=null; if(opRoom!=null) reverseRoom=opRoom.rawDoors()[Directions.getOpDirectionCode(direction)]; if((reverseRoom!=null)&&(reverseRoom==from)) return "Opposite room already exists and heads this way. One-way link created."; Exit thisExit=null; synchronized(("SYNC"+from.roomID()).intern()) { from=getRoom(from); if(opRoom!=null) from.rawDoors()[direction]=null; from.rawDoors()[direction]=room; thisExit=from.getRawExit(direction); if(thisExit==null) { thisExit=CMClass.getExit("StdOpenDoorway"); from.setRawExit(direction,thisExit); } CMLib.database().DBUpdateExits(from); } synchronized(("SYNC"+room.roomID()).intern()) { room=getRoom(room); if(room.rawDoors()[Directions.getOpDirectionCode(direction)]==null) { room.rawDoors()[Directions.getOpDirectionCode(direction)]=from; room.setRawExit(Directions.getOpDirectionCode(direction),thisExit); CMLib.database().DBUpdateExits(room); } } return ""; } @Override public int numRooms() { int total=0; for(final Enumeration<Area> e=areas();e.hasMoreElements();) total+=e.nextElement().properSize(); return total; } @Override public boolean sendGlobalMessage(MOB host, int category, CMMsg msg) { final List<WeakReference<MsgListener>> V=globalHandlers.get(Integer.valueOf(category)); if(V==null) return true; synchronized(V) { try { MsgListener O=null; Environmental E=null; for(final WeakReference<MsgListener> W : V) { O=W.get(); if(O instanceof Environmental) { E=(Environmental)O; if(!CMLib.flags().isInTheGame(E,true)) { if(!CMLib.flags().isInTheGame(E,false)) delGlobalHandler(E,category); } else if(!E.okMessage(host,msg)) return false; } else if(O!=null) { if(!O.okMessage(host, msg)) return false; } else V.remove(W); } for(final WeakReference<MsgListener> W : V) { O=W.get(); if(O !=null) O.executeMsg(host,msg); } } catch(final java.lang.ArrayIndexOutOfBoundsException xx){} catch(final Exception x){Log.errOut("CMMap",x);} } return true; } @Override public String getExtendedRoomID(final Room R) { if(R==null) return ""; if(R.roomID().length()>0) return R.roomID(); final Area A=R.getArea(); if(A==null) return ""; final GridLocale GR=R.getGridParent(); if(GR!=null) return GR.getGridChildCode(R); return R.roomID(); } @Override public String getDescriptiveExtendedRoomID(final Room room) { if(room==null) return ""; final String roomID = getExtendedRoomID(room); if(roomID.length()>0) return roomID; final GridLocale gridParentRoom=room.getGridParent(); if((gridParentRoom!=null)&&(gridParentRoom.roomID().length()==0)) { for(int dir=0;dir<Directions.NUM_DIRECTIONS();dir++) { final Room attachedRoom = gridParentRoom.rawDoors()[dir]; if(attachedRoom != null) { final String attachedRoomID = getExtendedRoomID(attachedRoom); if(attachedRoomID.length()>0) return Directions.getFromCompassDirectionName(Directions.getOpDirectionCode(dir))+" "+attachedRoomID; } } } Area area=room.getArea(); if((area==null)&&(gridParentRoom!=null)) area=gridParentRoom.getArea(); if(area == null) return ""; return area.Name()+"#?"; } @Override public String getExtendedTwinRoomIDs(final Room R1,final Room R2) { final String R1s=getExtendedRoomID(R1); final String R2s=getExtendedRoomID(R2); if(R1s.compareTo(R2s)>0) return R1s+"_"+R2s; else return R2s+"_"+R1s; } @Override public Room getRoom(Enumeration<Room> roomSet, String calledThis) { try { if(calledThis==null) return null; if(calledThis.endsWith(")")) { final int child=calledThis.lastIndexOf("#("); if(child>1) { Room R=getRoom(roomSet,calledThis.substring(0,child)); if((R!=null)&&(R instanceof GridLocale)) { R=((GridLocale)R).getGridChild(calledThis); if(R!=null) return R; } } } Room R=null; if(roomSet==null) { final int x=calledThis.indexOf('#'); if(x>=0) { final Area A=getArea(calledThis.substring(0,x)); if(A!=null) R=A.getRoom(calledThis); if(R!=null) return R; } for(final Enumeration<Area> e=this.areas();e.hasMoreElements();) { R = e.nextElement().getRoom(calledThis); if(R!=null) return R; } for(final Enumeration<Area> e=shipAreaEnumerator(null);e.hasMoreElements();) { R = e.nextElement().getRoom(calledThis); if(R!=null) return R; } } else { for(final Enumeration<Room> e=roomSet;e.hasMoreElements();) { R=e.nextElement(); if(R.roomID().equalsIgnoreCase(calledThis)) return R; } } } catch (final java.util.NoSuchElementException x) { } return null; } @Override public List<Room> findRooms(Enumeration<Room> rooms, MOB mob, String srchStr, boolean displayOnly, int timePct) { final Vector<Room> roomsV=new Vector<Room>(); if((srchStr.charAt(0)=='#')&&(mob!=null)&&(mob.location()!=null)) addWorldRoomsLiberally(roomsV,getRoom(mob.location().getArea().Name()+srchStr)); else addWorldRoomsLiberally(roomsV,getRoom(srchStr)); addWorldRoomsLiberally(roomsV,findRooms(rooms,mob,srchStr,displayOnly,false,timePct)); return roomsV; } @Override public Room findFirstRoom(Enumeration<Room> rooms, MOB mob, String srchStr, boolean displayOnly, int timePct) { final Vector<Room> roomsV=new Vector<Room>(); if((srchStr.charAt(0)=='#')&&(mob!=null)&&(mob.location()!=null)) addWorldRoomsLiberally(roomsV,getRoom(mob.location().getArea().Name()+srchStr)); else addWorldRoomsLiberally(roomsV,getRoom(srchStr)); if(roomsV.size()>0) return roomsV.firstElement(); addWorldRoomsLiberally(roomsV,findRooms(rooms,mob,srchStr,displayOnly,true,timePct)); if(roomsV.size()>0) return roomsV.firstElement(); return null; } public List<Room> findRooms(Enumeration<Room> rooms, MOB mob, String srchStr, boolean displayOnly, boolean returnFirst, int timePct) { final List<Room> foundRooms=new Vector<Room>(); Vector<Room> completeRooms=null; try { completeRooms=new XVector<Room>(rooms); } catch(final Exception nse) { Log.errOut("CMMap",nse); completeRooms=new Vector<Room>(); } final long delay=Math.round(CMath.s_pct(timePct+"%") * 1000); Enumeration<Room> enumSet; enumSet=completeRooms.elements(); while(enumSet.hasMoreElements()) { findRoomsByDisplay(mob,enumSet,foundRooms,srchStr,returnFirst,delay); if((returnFirst)&&(foundRooms.size()>0)) return foundRooms; if(enumSet.hasMoreElements()) CMLib.s_sleep(1000 - delay); } if(!displayOnly) { enumSet=completeRooms.elements(); while(enumSet.hasMoreElements()) { findRoomsByDesc(mob,enumSet,foundRooms,srchStr,returnFirst,delay); if((returnFirst)&&(foundRooms.size()>0)) return foundRooms; if(enumSet.hasMoreElements()) CMLib.s_sleep(1000 - delay); } } return foundRooms; } protected void findRoomsByDisplay(MOB mob, Enumeration<Room> rooms, List<Room> foundRooms, String srchStr, boolean returnFirst, long maxTime) { final long startTime=System.currentTimeMillis(); try { srchStr=srchStr.toUpperCase(); final boolean useTimer=maxTime>1; Room room; for(;rooms.hasMoreElements();) { room=rooms.nextElement(); if((CMLib.english().containsString(CMStrings.removeColors(room.displayText(mob)),srchStr)) &&((mob==null)||CMLib.flags().canAccess(mob,room))) foundRooms.add(room); if((useTimer)&&((System.currentTimeMillis()-startTime)>maxTime)) return; } } catch (final NoSuchElementException nse) { } } protected void findRoomsByDesc(MOB mob, Enumeration<Room> rooms, List<Room> foundRooms, String srchStr, boolean returnFirst, long maxTime) { final long startTime=System.currentTimeMillis(); try { srchStr=srchStr.toUpperCase(); final boolean useTimer=maxTime>1; for(;rooms.hasMoreElements();) { final Room room=rooms.nextElement(); if((CMLib.english().containsString(CMStrings.removeColors(room.description()),srchStr)) &&((mob==null)||CMLib.flags().canAccess(mob,room))) foundRooms.add(room); if((useTimer)&&((System.currentTimeMillis()-startTime)>maxTime)) return; } } catch (final NoSuchElementException nse) { } } @Override public List<MOB> findInhabitants(Enumeration<Room> rooms, MOB mob, String srchStr, int timePct) { return findInhabitants(rooms,mob,srchStr,false,timePct); } @Override public MOB findFirstInhabitant(Enumeration<Room> rooms, MOB mob, String srchStr, int timePct) { final List<MOB> found=findInhabitants(rooms,mob,srchStr,true,timePct); if(found.size()>0) return found.get(0); return null; } public List<MOB> findInhabitants(Enumeration<Room> rooms, MOB mob, String srchStr, boolean returnFirst, int timePct) { final Vector<MOB> found=new Vector<MOB>(); long delay=Math.round(CMath.s_pct(timePct+"%") * 1000); if(delay>1000) delay=1000; final boolean useTimer = delay>1; final boolean allRoomsAllowed=(mob==null); long startTime=System.currentTimeMillis(); Room room; for(;rooms.hasMoreElements();) { room=rooms.nextElement(); if((room != null) && (allRoomsAllowed || CMLib.flags().canAccess(mob,room))) { found.addAll(room.fetchInhabitants(srchStr)); if((returnFirst)&&(found.size()>0)) return found; } if((useTimer)&&((System.currentTimeMillis()-startTime)>delay)) CMLib.s_sleep(1000 - delay); startTime=System.currentTimeMillis(); } return found; } @Override public List<Item> findInventory(Enumeration<Room> rooms, MOB mob, String srchStr, int timePct) { return findInventory(rooms,mob,srchStr,false,timePct); } @Override public Item findFirstInventory(Enumeration<Room> rooms, MOB mob, String srchStr, int timePct) { final List<Item> found=findInventory(rooms,mob,srchStr,true,timePct); if(found.size()>0) return found.get(0); return null; } public List<Item> findInventory(Enumeration<Room> rooms, MOB mob, String srchStr, boolean returnFirst, int timePct) { final List<Item> found=new Vector<Item>(); long delay=Math.round(CMath.s_pct(timePct+"%") * 1000); if(delay>1000) delay=1000; final boolean useTimer = delay>1; long startTime=System.currentTimeMillis(); MOB M; Room room; if(rooms==null) { for(final Enumeration<MOB> e=CMLib.players().players();e.hasMoreElements();) { M=e.nextElement(); if(M!=null) found.addAll(M.findItems(srchStr)); if((returnFirst)&&(found.size()>0)) return found; } } else for(;rooms.hasMoreElements();) { room=rooms.nextElement(); if((room != null) && ((mob==null)||CMLib.flags().canAccess(mob,room))) { for(int m=0;m<room.numInhabitants();m++) { M=room.fetchInhabitant(m); if(M!=null) found.addAll(M.findItems(srchStr)); } if((returnFirst)&&(found.size()>0)) return found; } if((useTimer)&&((System.currentTimeMillis()-startTime)>delay)) CMLib.s_sleep(1000 - delay); startTime=System.currentTimeMillis(); } return found; } @Override public List<Environmental> findShopStock(Enumeration<Room> rooms, MOB mob, String srchStr, int timePct) { return findShopStock(rooms,mob,srchStr,false,false,timePct); } @Override public Environmental findFirstShopStock(Enumeration<Room> rooms, MOB mob, String srchStr, int timePct) { final List<Environmental> found=findShopStock(rooms,mob,srchStr,true,false,timePct); if(found.size()>0) return found.get(0); return null; } @Override public List<Environmental> findShopStockers(Enumeration<Room> rooms, MOB mob, String srchStr, int timePct) { return findShopStock(rooms,mob,srchStr,false,true,timePct); } @Override public Environmental findFirstShopStocker(Enumeration<Room> rooms, MOB mob, String srchStr, int timePct) { final List<Environmental> found=findShopStock(rooms,mob,srchStr,true,true,timePct); if(found.size()>0) return found.get(0); return null; } public List<Environmental> findShopStock(Enumeration<Room> rooms, MOB mob, String srchStr, boolean returnFirst, boolean returnStockers, int timePct) { final XVector<Environmental> found=new XVector<Environmental>(); long delay=Math.round(CMath.s_pct(timePct+"%") * 1000); if(delay>1000) delay=1000; final boolean useTimer = delay>1; long startTime=System.currentTimeMillis(); MOB M=null; Item I=null; final HashSet<ShopKeeper> stocks=new HashSet<ShopKeeper>(1); final HashSet<Area> areas=new HashSet<Area>(); ShopKeeper SK=null; final boolean allRoomsAllowed=(mob==null); if(rooms==null) { for(final Enumeration<MOB> e=CMLib.players().players();e.hasMoreElements();) { M=e.nextElement(); if(M!=null) { SK=CMLib.coffeeShops().getShopKeeper(M); if((SK!=null)&&(!stocks.contains(SK))) { stocks.add(SK); final Iterator<Environmental> ei=SK.getShop().getStoreInventory(srchStr); if(ei.hasNext()) { if(returnFirst) return (returnStockers)?new XVector<Environmental>(M):new XVector<Environmental>(ei); if(returnStockers) found.add(M); else found.addAll(ei); } } for(int i=0;i<M.numItems();i++) { I=M.getItem(i); if(I!=null) { SK=CMLib.coffeeShops().getShopKeeper(I); if((SK!=null)&&(!stocks.contains(SK))) { stocks.add(SK); final Iterator<Environmental> ei=SK.getShop().getStoreInventory(srchStr); if(ei.hasNext()) { if(returnFirst) return (returnStockers)?new XVector<Environmental>(I):new XVector<Environmental>(ei); if(returnStockers) found.add(I); else found.addAll(ei); } } } } } if((useTimer)&&((System.currentTimeMillis()-startTime)>delay)) { try { Thread.sleep(1000 - delay); startTime = System.currentTimeMillis(); } catch (final Exception ex) { } } } } else for(;rooms.hasMoreElements();) { final Room room=rooms.nextElement(); if((room != null) && (allRoomsAllowed||CMLib.flags().canAccess(mob,room))) { if(!areas.contains(room.getArea())) areas.add(room.getArea()); SK=CMLib.coffeeShops().getShopKeeper(room); if((SK!=null)&&(!stocks.contains(SK))) { stocks.add(SK); final Iterator<Environmental> ei=SK.getShop().getStoreInventory(srchStr); if(ei.hasNext()) { if(returnFirst) return (returnStockers)?new XVector<Environmental>(room):new XVector<Environmental>(ei); if(returnStockers) found.add(room); else found.addAll(ei); } } for(int m=0;m<room.numInhabitants();m++) { M=room.fetchInhabitant(m); if(M!=null) { SK=CMLib.coffeeShops().getShopKeeper(M); if((SK!=null)&&(!stocks.contains(SK))) { stocks.add(SK); final Iterator<Environmental> ei=SK.getShop().getStoreInventory(srchStr); if(ei.hasNext()) { if(returnFirst) return (returnStockers)?new XVector<Environmental>(M):new XVector<Environmental>(ei); if(returnStockers) found.add(M); else found.addAll(ei); } } } } for(int i=0;i<room.numItems();i++) { I=room.getItem(i); if(I!=null) { SK=CMLib.coffeeShops().getShopKeeper(I); if((SK!=null)&&(!stocks.contains(SK))) { stocks.add(SK); final Iterator<Environmental> ei=SK.getShop().getStoreInventory(srchStr); if(ei.hasNext()) { if(returnFirst) return (returnStockers)?new XVector<Environmental>(I):new XVector<Environmental>(ei); if(returnStockers) found.add(I); else found.addAll(ei); } } } } } if((useTimer)&&((System.currentTimeMillis()-startTime)>delay)) CMLib.s_sleep(1000 - delay); startTime=System.currentTimeMillis(); } for (final Area A : areas) { SK=CMLib.coffeeShops().getShopKeeper(A); if((SK!=null)&&(!stocks.contains(SK))) { stocks.add(SK); final Iterator<Environmental> ei=SK.getShop().getStoreInventory(srchStr); if(ei.hasNext()) { if(returnFirst) return (returnStockers)?new XVector<Environmental>(A):new XVector<Environmental>(ei); if(returnStockers) found.add(A); else found.addAll(ei); } } } return found; } @Override public List<Item> findRoomItems(Enumeration<Room> rooms, MOB mob, String srchStr, boolean anyItems, int timePct) { return findRoomItems(rooms,mob,srchStr,anyItems,false,timePct); } @Override public Item findFirstRoomItem(Enumeration<Room> rooms, MOB mob, String srchStr, boolean anyItems, int timePct) { final List<Item> found=findRoomItems(rooms,mob,srchStr,anyItems,true,timePct); if(found.size()>0) return found.get(0); return null; } public List<Item> findRoomItems(Enumeration<Room> rooms, MOB mob, String srchStr, boolean anyItems, boolean returnFirst, int timePct) { final Vector<Item> found=new Vector<Item>(); long delay=Math.round(CMath.s_pct(timePct+"%") * 1000); if(delay>1000) delay=1000; final boolean useTimer = delay>1; long startTime=System.currentTimeMillis(); final boolean allRoomsAllowed=(mob==null); Room room; for(;rooms.hasMoreElements();) { room=rooms.nextElement(); if((room != null) && (allRoomsAllowed||CMLib.flags().canAccess(mob,room))) { found.addAll(anyItems?room.findItems(srchStr):room.findItems(null,srchStr)); if((returnFirst)&&(found.size()>0)) return found; } if((useTimer)&&((System.currentTimeMillis()-startTime)>delay)) CMLib.s_sleep(1000 - delay); startTime=System.currentTimeMillis(); } return found; } @Override public Room getRoom(Room room) { if(room==null) return null; if(room.amDestroyed()) return getRoom(getExtendedRoomID(room)); return room; } @Override public Room getRoom(String calledThis) { return getRoom(null,calledThis); } @Override public Enumeration<Room> rooms() { return new AllAreasRoomEnumerator(false); } @Override public Enumeration<Room> roomsFilled() { return new AllAreasRoomEnumerator(true); } @Override public Room getRandomRoom() { Room R=null; int numRooms=-1; while((R==null)&&((numRooms=numRooms())>0)) { try { final int which=CMLib.dice().roll(1,numRooms,-1); int total=0; for(final Enumeration<Area> e=areas();e.hasMoreElements();) { final Area A=e.nextElement(); if(which<(total+A.properSize())) { R = A.getRandomProperRoom(); break; } total+=A.properSize(); } } catch (final NoSuchElementException e) { } } return R; } public int numDeities() { return deitiesList.size(); } protected void addDeity(Deity newOne) { if (!deitiesList.contains(newOne)) deitiesList.add(newOne); } protected void delDeity(Deity oneToDel) { deitiesList.remove(oneToDel); } @Override public Deity getDeity(String calledThis) { for (final Deity D : deitiesList) if (D.Name().equalsIgnoreCase(calledThis)) return D; return null; } @Override public Enumeration<Deity> deities() { return new IteratorEnumeration<Deity>(deitiesList.iterator()); } public int numShips() { return shipList.size(); } protected void addShip(BoardableShip newOne) { if (!shipList.contains(newOne)) shipList.add(newOne); } protected void delShip(BoardableShip oneToDel) { shipList.remove(oneToDel); } @Override public BoardableShip getShip(String calledThis) { for (final BoardableShip S : shipList) { if (S.Name().equalsIgnoreCase(calledThis)) return S; } return null; } @Override public Enumeration<BoardableShip> ships() { return new IteratorEnumeration<BoardableShip>(shipList.iterator()); } public Enumeration<Room> shipsRoomEnumerator(final Area inA) { return new Enumeration<Room>() { private Enumeration<Room> cur = null; private Enumeration<Area> cA = shipAreaEnumerator(inA); @Override public boolean hasMoreElements() { boolean hasMore = (cur != null) && cur.hasMoreElements(); while(!hasMore) { if((cA == null)||(!cA.hasMoreElements())) { cur=null; cA = null; return false; } cur = cA.nextElement().getProperMap(); hasMore = (cur != null) && cur.hasMoreElements(); } return hasMore; } @Override public Room nextElement() { if(!hasMoreElements()) throw new NoSuchElementException(); return cur.nextElement(); } }; } public Enumeration<Area> shipAreaEnumerator(final Area inA) { return new Enumeration<Area>() { private volatile Area nextArea=null; private volatile Enumeration<BoardableShip> shipsEnum=ships(); @Override public boolean hasMoreElements() { while(nextArea == null) { if((shipsEnum==null)||(!shipsEnum.hasMoreElements())) { shipsEnum=null; return false; } final BoardableShip ship=shipsEnum.nextElement(); if((ship!=null)&&(ship.getShipArea()!=null)) { if((inA==null)||(areaLocation(ship)==inA)) nextArea=ship.getShipArea(); } } return (nextArea != null); } @Override public Area nextElement() { if(!hasMoreElements()) throw new NoSuchElementException(); final Area A=nextArea; this.nextArea=null; return A; } }; } public int numPostOffices() { return postOfficeList.size(); } protected void addPostOffice(PostOffice newOne) { if(!postOfficeList.contains(newOne)) postOfficeList.add(newOne); } protected void delPostOffice(PostOffice oneToDel) { postOfficeList.remove(oneToDel); } @Override public PostOffice getPostOffice(String chain, String areaNameOrBranch) { for (final PostOffice P : postOfficeList) { if((P.postalChain().equalsIgnoreCase(chain)) &&(P.postalBranch().equalsIgnoreCase(areaNameOrBranch))) return P; } final Area A=findArea(areaNameOrBranch); if(A==null) return null; for (final PostOffice P : postOfficeList) { if((P.postalChain().equalsIgnoreCase(chain)) &&(getStartArea(P)==A)) return P; } return null; } @Override public Enumeration<PostOffice> postOffices() { return new IteratorEnumeration<PostOffice>(postOfficeList.iterator()); } @Override public Enumeration<Auctioneer> auctionHouses() { return new IteratorEnumeration<Auctioneer>(auctionHouseList.iterator()); } public int numAuctionHouses() { return auctionHouseList.size(); } protected void addAuctionHouse(Auctioneer newOne) { if (!auctionHouseList.contains(newOne)) { auctionHouseList.add(newOne); } } protected void delAuctionHouse(Auctioneer oneToDel) { auctionHouseList.remove(oneToDel); } @Override public Auctioneer getAuctionHouse(String chain, String areaNameOrBranch) { for (final Auctioneer C : auctionHouseList) { if((C.auctionHouse().equalsIgnoreCase(chain)) &&(C.auctionHouse().equalsIgnoreCase(areaNameOrBranch))) return C; } final Area A=findArea(areaNameOrBranch); if(A==null) return null; for (final Auctioneer C : auctionHouseList) { if((C.auctionHouse().equalsIgnoreCase(chain)) &&(getStartArea(C)==A)) return C; } return null; } public int numBanks() { return bankList.size(); } protected void addBank(Banker newOne) { if (!bankList.contains(newOne)) bankList.add(newOne); } protected void delBank(Banker oneToDel) { bankList.remove(oneToDel); } @Override public Banker getBank(String chain, String areaNameOrBranch) { for (final Banker B : bankList) { if((B.bankChain().equalsIgnoreCase(chain)) &&(B.bankChain().equalsIgnoreCase(areaNameOrBranch))) return B; } final Area A=findArea(areaNameOrBranch); if(A==null) return null; for (final Banker B : bankList) { if((B.bankChain().equalsIgnoreCase(chain)) &&(getStartArea(B)==A)) return B; } return null; } @Override public Enumeration<Banker> banks() { return new IteratorEnumeration<Banker>(bankList.iterator()); } @Override public Iterator<String> bankChains(Area AreaOrNull) { final HashSet<String> H=new HashSet<String>(); for (final Banker B : bankList) { if((!H.contains(B.bankChain())) &&((AreaOrNull==null) ||(getStartArea(B)==AreaOrNull) ||(AreaOrNull.isChild(getStartArea(B))))) H.add(B.bankChain()); } return H.iterator(); } @Override public void renameRooms(Area A, String oldName, List<Room> allMyDamnRooms) { final List<Room> onesToRenumber=new Vector<Room>(); for(Room R : allMyDamnRooms) { synchronized(("SYNC"+R.roomID()).intern()) { R=getRoom(R); R.setArea(A); if(oldName!=null) { if(R.roomID().toUpperCase().startsWith(oldName.toUpperCase()+"#")) { Room R2=A.getRoom(A.Name()+"#"+R.roomID().substring(oldName.length()+1)); if(R2 == null) R2=getRoom(A.Name()+"#"+R.roomID().substring(oldName.length()+1)); if((R2==null)||(!R2.roomID().startsWith(A.Name()+"#"))) { final String oldID=R.roomID(); R.setRoomID(A.Name()+"#"+R.roomID().substring(oldName.length()+1)); CMLib.database().DBReCreate(R,oldID); } else onesToRenumber.add(R); } else CMLib.database().DBUpdateRoom(R); } } } if(oldName!=null) { for(final Room R: onesToRenumber) { final String oldID=R.roomID(); R.setRoomID(A.getNewRoomID(R,-1)); CMLib.database().DBReCreate(R,oldID); } } } @Override public int getRoomDir(Room from, Room to) { if((from==null)||(to==null)) return -1; for(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--) if(from.getRoomInDir(d)==to) return d; return -1; } @Override public Area getTargetArea(Room from, Exit to) { final Room R=getTargetRoom(from, to); if(R==null) return null; return R.getArea(); } @Override public Room getTargetRoom(Room from, Exit to) { if((from==null)||(to==null)) return null; final int d=getExitDir(from, to); if(d<0) return null; return from.getRoomInDir(d); } @Override public int getExitDir(Room from, Exit to) { if((from==null)||(to==null)) return -1; for(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--) { if(from.getExitInDir(d)==to) return d; if(from.getRawExit(d)==to) return d; if(from.getReverseExit(d)==to) return d; } return -1; } @Override public Room findConnectingRoom(Room room) { if(room==null) return null; Room R=null; final Vector<Room> otherChoices=new Vector<Room>(); for(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--) { R=room.getRoomInDir(d); if(R!=null) { for(int d1=Directions.NUM_DIRECTIONS()-1;d1>=0;d1--) { if(R.getRoomInDir(d1)==room) { if(R.getArea()==room.getArea()) return R; otherChoices.addElement(R); } } } } for(final Enumeration<Room> e=rooms();e.hasMoreElements();) { R=e.nextElement(); if(R==room) continue; for(int d1=Directions.NUM_DIRECTIONS()-1;d1>=0;d1--) { if(R.getRoomInDir(d1)==room) { if(R.getArea()==room.getArea()) return R; otherChoices.addElement(R); } } } if(otherChoices.size()>0) return otherChoices.firstElement(); return null; } @Override public boolean isClearableRoom(Room R) { if((R==null)||(R.amDestroyed())) return true; MOB M=null; Room sR=null; for(int i=0;i<R.numInhabitants();i++) { M=R.fetchInhabitant(i); if(M==null) continue; sR=M.getStartRoom(); if((sR!=null) &&(!sR.roomID().equals(R.roomID()))) return false; if(M.session()!=null) return false; } Item I=null; for(int i=0;i<R.numItems();i++) { I=R.getItem(i); if((I!=null) &&((I.expirationDate()!=0) ||((I instanceof DeadBody)&&(((DeadBody)I).isPlayerCorpse())) ||((I instanceof PrivateProperty)&&(((PrivateProperty)I).getOwnerName().length()>0)))) return false; } for(final Enumeration<Ability> a=R.effects();a.hasMoreElements();) { final Ability A=a.nextElement(); if((A!=null)&&(!A.isSavable())) return false; } return true; } @Override public boolean explored(Room R) { if((R==null) ||(CMath.bset(R.phyStats().sensesMask(),PhyStats.SENSE_ROOMUNEXPLORABLE)) ||(R.getArea()==null)) return false; return false; } public class AllAreasRoomEnumerator implements Enumeration<Room> { private Enumeration<Area> curAreaEnumeration=areasPlusShips(); private Enumeration<Room> curRoomEnumeration=null; private boolean addSkys = false; public AllAreasRoomEnumerator(boolean includeSkys) { addSkys = includeSkys; } @Override public boolean hasMoreElements() { boolean hasMore = (curRoomEnumeration!=null)&&(curRoomEnumeration.hasMoreElements()); while(!hasMore) { if((curAreaEnumeration == null)||(!curAreaEnumeration.hasMoreElements())) { curRoomEnumeration = null; curAreaEnumeration = null; return false; } if(addSkys) curRoomEnumeration=curAreaEnumeration.nextElement().getFilledProperMap(); else curRoomEnumeration=curAreaEnumeration.nextElement().getProperMap(); hasMore = (curRoomEnumeration!=null)&&(curRoomEnumeration.hasMoreElements()); } return hasMore; } @Override public Room nextElement() { if(!hasMoreElements()) throw new NoSuchElementException(); return curRoomEnumeration.nextElement(); } } @Override public void obliterateRoom(Room deadRoom) { for(final Enumeration<Ability> a=deadRoom.effects();a.hasMoreElements();) { final Ability A=a.nextElement(); if(A!=null) { A.unInvoke(); deadRoom.delEffect(A); } } try { for(final Enumeration<Room> r=rooms();r.hasMoreElements();) { Room R=r.nextElement(); synchronized(("SYNC"+R.roomID()).intern()) { R=getRoom(R); if(R==null) continue; boolean changes=false; for(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--) { final Room thatRoom=R.rawDoors()[d]; if(thatRoom==deadRoom) { R.rawDoors()[d]=null; changes=true; if((R.getRawExit(d)!=null)&&(R.getRawExit(d).isGeneric())) { final Exit GE=R.getRawExit(d); GE.setTemporaryDoorLink(deadRoom.roomID()); } } } if(changes) CMLib.database().DBUpdateExits(R); } } }catch(final NoSuchElementException e){} emptyRoom(deadRoom,null,true); deadRoom.destroy(); if(deadRoom instanceof GridLocale) ((GridLocale)deadRoom).clearGrid(null); CMLib.database().DBDeleteRoom(deadRoom); } @Override public void emptyAreaAndDestroyRooms(Area area) { for(final Enumeration<Ability> a=area.effects();a.hasMoreElements();) { final Ability A=a.nextElement(); if(A!=null) { A.unInvoke(); area.delEffect(A); } } for(final Enumeration<Room> e=area.getProperMap();e.hasMoreElements();) { final Room R=e.nextElement(); emptyRoom(R,null,true); R.destroy(); } } @Override public Room roomLocation(Environmental E) { if(E==null) return null; if((E instanceof Area)&&(!((Area)E).isProperlyEmpty())) return ((Area)E).getRandomProperRoom(); else if(E instanceof Room) return (Room)E; else if(E instanceof MOB) return ((MOB)E).location(); else if((E instanceof Item)&&(((Item)E).owner() instanceof Room)) return (Room)((Item)E).owner(); else if((E instanceof Item)&&(((Item)E).owner() instanceof MOB)) return ((MOB)((Item)E).owner()).location(); else if(E instanceof Ability) return roomLocation(((Ability)E).affecting()); else if(E instanceof Exit) return roomLocation(((Exit)E).lastRoomUsedFrom()); return null; } @Override public Area getStartArea(Environmental E) { if(E instanceof Area) return (Area)E; final Room R=getStartRoom(E); if(R==null) return null; return R.getArea(); } @Override public Room getStartRoom(Environmental E) { if(E ==null) return null; if(E instanceof MOB) return ((MOB)E).getStartRoom(); if(E instanceof Item) { if(((Item)E).owner() instanceof MOB) return getStartRoom(((Item)E).owner()); if(CMLib.flags().isGettable((Item)E)) return null; } if(E instanceof Ability) return getStartRoom(((Ability)E).affecting()); if((E instanceof Area)&&(!((Area)E).isProperlyEmpty())) return ((Area)E).getRandomProperRoom(); if(E instanceof Room) return (Room)E; return roomLocation(E); } @Override public ThreadGroup getOwnedThreadGroup(CMObject E) { final Area area=areaLocation(E); if(area != null) { final int theme=area.getTheme(); if((theme>0)&&(theme<Area.THEME_NAMES.length)) return CMProps.getPrivateOwner(Area.THEME_NAMES[theme]+"AREAS"); } return null; } @Override public Area areaLocation(CMObject E) { if(E==null) return null; if(E instanceof Area) return (Area)E; else if(E instanceof Room) return ((Room)E).getArea(); else if(E instanceof MOB) return areaLocation(((MOB)E).location()); else if(E instanceof Item) return areaLocation(((Item) E).owner()); else if((E instanceof Ability)&&(((Ability)E).affecting()!=null)) return areaLocation(((Ability)E).affecting()); else if(E instanceof Exit) return areaLocation(((Exit)E).lastRoomUsedFrom()); return null; } @Override public Room getSafeRoomToMovePropertyTo(Room room, PrivateProperty I) { if(I instanceof BoardableShip) { final Room R=getRoom(((BoardableShip)I).getHomePortID()); if((R!=null)&&(R!=room)&&(!R.amDestroyed())) return R; } if(room != null) { Room R=null; if(room.getGridParent()!=null) { R=getRoom(room.getGridParent()); if((R!=null)&&(R!=room)&&(!R.amDestroyed())&&(R.roomID().length()>0)) return R; } for(int d=0;d<Directions.NUM_DIRECTIONS();d++) { R=getRoom(room.getRoomInDir(d)); if((R!=null)&&(R!=room)&&(!R.amDestroyed())&&(R.roomID().length()>0)) return R; } if(room.getGridParent()!=null) { for(int d=0;d<Directions.NUM_DIRECTIONS();d++) { R=getRoom(room.getGridParent().getRoomInDir(d)); if((R!=null)&&(R!=room)&&(!R.amDestroyed())&&(R.roomID().length()>0)) return R; } } final Area A=room.getArea(); if(A!=null) { for(int i=0;i<A.numberOfProperIDedRooms();i++) { R=getRoom(A.getRandomProperRoom()); if((R!=null)&&(R!=room)&&(!R.amDestroyed())&&(R.roomID().length()>0)) return R; } } } for(int i=0;i<100;i++) { final Room R=getRoom(this.getRandomRoom()); if((R!=null)&&(R!=room)&&(!R.amDestroyed())&&(R.roomID().length()>0)) return R; } return null; } @Override public void emptyRoom(Room room, Room toRoom, boolean clearPlayers) { if(room==null) return; MOB M=null; if(toRoom != null) { for(final Enumeration<MOB> i=room.inhabitants();i.hasMoreElements();) { M=i.nextElement(); if(M!=null) toRoom.bringMobHere(M,false); } } else if(clearPlayers) { for(final Enumeration<MOB> i=room.inhabitants();i.hasMoreElements();) { M=i.nextElement(); if((M!=null) && (M.isPlayer())) M.getStartRoom().bringMobHere(M,true); } } for(final Enumeration<MOB> i=room.inhabitants();i.hasMoreElements();) { M=i.nextElement(); if((M!=null) &&(!M.isPlayer()) &&(M.isSavable()) &&((M.amFollowing()==null)||(!M.amFollowing().isPlayer()))) { if((M.getStartRoom()==null) ||(M.getStartRoom()==room) ||(M.getStartRoom().ID().length()==0)) M.destroy(); else M.getStartRoom().bringMobHere(M,false); } } Item I=null; if(toRoom != null) { for(final Enumeration<Item> i=room.items();i.hasMoreElements();) { I=i.nextElement(); if(I!=null) toRoom.moveItemTo(I,ItemPossessor.Expire.Player_Drop); } } else { for(final Enumeration<Item> i=room.items();i.hasMoreElements();) { I=i.nextElement(); if(I != null) { if((I instanceof PrivateProperty)&&((((PrivateProperty)I).getOwnerName().length()>0))) { final Room R=this.getSafeRoomToMovePropertyTo(room, (PrivateProperty)I); if((R!=null)&&(R!=room)) R.moveItemTo(I,ItemPossessor.Expire.Player_Drop); } else I.destroy(); } } } room.clearSky(); CMLib.threads().clearDebri(room,0); if(room instanceof GridLocale) for(final Iterator<Room> r=((GridLocale)room).getExistingRooms();r.hasNext();) emptyRoom(r.next(), toRoom, clearPlayers); } @Override public void obliterateArea(Area A) { if(A==null) return; final LinkedList<Room> rooms=new LinkedList<Room>(); Room R=null; Enumeration<Room> e=A.getCompleteMap(); while(e.hasMoreElements()) { for(int i=0;(i<100)&&e.hasMoreElements();i++) { R=e.nextElement(); if((R!=null)&&(R.roomID()!=null)) rooms.add(R); } if(rooms.size()==0) break; for(final Iterator<Room> e2=rooms.iterator();e2.hasNext();) { R=e2.next(); if((R!=null)&&(R.roomID().length()>0)) obliterateRoom(R); e2.remove(); } e=A.getCompleteMap(); } CMLib.database().DBDeleteArea(A); delArea(A); A.destroy(); // why not? } public CMMsg resetMsg=null; @Override public void resetRoom(Room room) { resetRoom(room,false); } @Override public void resetRoom(Room room, boolean rebuildGrids) { if(room==null) return; if(room.roomID().length()==0) return; synchronized(("SYNC"+room.roomID()).intern()) { room=getRoom(room); if((rebuildGrids)&&(room instanceof GridLocale)) ((GridLocale)room).clearGrid(null); final boolean mobile=room.getMobility(); room.toggleMobility(false); if(resetMsg==null) resetMsg=CMClass.getMsg(CMClass.sampleMOB(),room,CMMsg.MSG_ROOMRESET,null); resetMsg.setTarget(room); room.executeMsg(room,resetMsg); if(room.isSavable()) emptyRoom(room,null,false); for(final Enumeration<Ability> a=room.effects();a.hasMoreElements();) { final Ability A=a.nextElement(); if((A!=null)&&(A.canBeUninvoked())) A.unInvoke(); } if(room.isSavable()) { CMLib.database().DBReReadRoomData(room); CMLib.database().DBReadContent(room.roomID(),room,true); } room.startItemRejuv(); room.setResource(-1); room.toggleMobility(mobile); } } @Override public Room findWorldRoomLiberally(MOB mob, String cmd, String srchWhatAERIPMVK, int timePct, long maxMillis) { final List<Room> rooms=findWorldRoomsLiberally(mob,cmd,srchWhatAERIPMVK,null,true,timePct, maxMillis); if((rooms!=null)&&(rooms.size()!=0)) return rooms.get(0); return null; } @Override public List<Room> findWorldRoomsLiberally(MOB mob, String cmd, String srchWhatAERIPMVK, int timePct, long maxMillis) { return findWorldRoomsLiberally(mob,cmd,srchWhatAERIPMVK,null,false,timePct,maxMillis); } @Override public Room findAreaRoomLiberally(MOB mob, Area A,String cmd, String srchWhatAERIPMVK, int timePct) { final List<Room> rooms=findWorldRoomsLiberally(mob,cmd,srchWhatAERIPMVK,A,true,timePct,120); if((rooms!=null)&&(rooms.size()!=0)) return rooms.get(0); return null; } @Override public List<Room> findAreaRoomsLiberally(MOB mob, Area A,String cmd, String srchWhatAERIPMVK, int timePct) { return findWorldRoomsLiberally(mob,cmd,srchWhatAERIPMVK,A,false,timePct,120); } protected Room addWorldRoomsLiberally(List<Room> rooms, List<? extends Environmental> choicesV) { if(choicesV==null) return null; if(rooms!=null) { for(final Environmental E : choicesV) addWorldRoomsLiberally(rooms,roomLocation(E)); return null; } else { Room room=null; int tries=0; while(((room==null)||(room.roomID().length()==0))&&((++tries)<200)) room=roomLocation(choicesV.get(CMLib.dice().roll(1,choicesV.size(),-1))); return room; } } protected Room addWorldRoomsLiberally(List<Room> rooms, Room room) { if(room==null) return null; if(rooms!=null) { if(!rooms.contains(room)) rooms.add(room); return null; } return room; } protected Room addWorldRoomsLiberally(List<Room>rooms, Area area) { if((area==null)||(area.isProperlyEmpty())) return null; return addWorldRoomsLiberally(rooms,area.getRandomProperRoom()); } protected List<Room> returnResponse(List<Room> rooms, Room room) { if(rooms!=null) return rooms; if(room==null) return new Vector<Room>(1); return new XVector<Room>(room); } protected boolean enforceTimeLimit(final long startTime, final long maxMillis) { if(maxMillis<=0) return false; return ((System.currentTimeMillis() - startTime)) > maxMillis; } protected List<MOB> checkMOBCachedList(List<MOB> list) { if (list != null) { for(final Environmental E : list) if(E.amDestroyed()) return null; } return list; } protected List<Item> checkInvCachedList(List<Item> list) { if (list != null) { for(final Item E : list) if((E.amDestroyed())||(!(E.owner() instanceof MOB))) return null; } return list; } protected List<Item> checkRoomItemCachedList(List<Item> list) { if (list != null) { for(final Item E : list) if((E.amDestroyed())||(!(E.owner() instanceof Room))) return null; } return list; } @SuppressWarnings("unchecked") public Map<String,List<MOB>> getMOBFinder() { Map<String,List<MOB>> finder=(Map<String,List<MOB>>)Resources.getResource("SYSTEM_MOB_FINDER_CACHE"); if(finder==null) { finder=new PrioritizingLimitedMap<String,List<MOB>>(10,EXPIRE_5MINS,EXPIRE_10MINS,100); Resources.submitResource("SYSTEM_MOB_FINDER_CACHE",finder); } return finder; } @SuppressWarnings("unchecked") public Map<String,Area> getAreaFinder() { Map<String,Area> finder=(Map<String,Area>)Resources.getResource("SYSTEM_AREA_FINDER_CACHE"); if(finder==null) { finder=new PrioritizingLimitedMap<String,Area>(50,EXPIRE_30MINS,EXPIRE_1HOUR,100); Resources.submitResource("SYSTEM_AREA_FINDER_CACHE",finder); } return finder; } @SuppressWarnings("unchecked") public Map<String,List<Item>> getRoomItemFinder() { Map<String,List<Item>> finder=(Map<String,List<Item>>)Resources.getResource("SYSTEM_RITEM_FINDER_CACHE"); if(finder==null) { finder=new PrioritizingLimitedMap<String,List<Item>>(10,EXPIRE_5MINS,EXPIRE_10MINS,100); Resources.submitResource("SYSTEM_RITEM_FINDER_CACHE",finder); } return finder; } @SuppressWarnings("unchecked") public Map<String,List<Item>> getInvItemFinder() { Map<String,List<Item>> finder=(Map<String,List<Item>>)Resources.getResource("SYSTEM_IITEM_FINDER_CACHE"); if(finder==null) { finder=new PrioritizingLimitedMap<String,List<Item>>(10,EXPIRE_1MIN,EXPIRE_10MINS,100); Resources.submitResource("SYSTEM_IITEM_FINDER_CACHE",finder); } return finder; } @SuppressWarnings("unchecked") public Map<String,List<Environmental>> getStockFinder() { Map<String,List<Environmental>> finder=(Map<String,List<Environmental>>)Resources.getResource("SYSTEM_STOCK_FINDER_CACHE"); if(finder==null) { finder=new PrioritizingLimitedMap<String,List<Environmental>>(10,EXPIRE_10MINS,EXPIRE_1HOUR,100); Resources.submitResource("SYSTEM_STOCK_FINDER_CACHE",finder); } return finder; } @SuppressWarnings("unchecked") public Map<String,List<Room>> getRoomFinder() { Map<String,List<Room>> finder=(Map<String,List<Room>>)Resources.getResource("SYSTEM_ROOM_FINDER_CACHE"); if(finder==null) { finder=new PrioritizingLimitedMap<String,List<Room>>(20,EXPIRE_20MINS,EXPIRE_1HOUR,100); Resources.submitResource("SYSTEM_ROOM_FINDER_CACHE",finder); } return finder; } protected List<Room> findWorldRoomsLiberally(MOB mob, String cmd, String srchWhatAERIPMVK, Area area, boolean returnFirst, int timePct, long maxMillis) { Room room=null; // wish this stuff could be cached, even temporarily, however, // far too much of the world is dynamic, and far too many searches // are looking for dynamic things. the cached results would be useless // as soon as they are put away -- that's why the limited caches time them out! final boolean disableCaching= CMProps.getBoolVar(CMProps.Bool.MAPFINDSNOCACHE); final Vector<Room> rooms=(returnFirst)?null:new Vector<Room>(); final Room curRoom=(mob!=null)?mob.location():null; boolean searchWeakAreas=false; boolean searchStrictAreas=false; boolean searchRooms=false; boolean searchPlayers=false; boolean searchItems=false; boolean searchInhabs=false; boolean searchInventories=false; boolean searchStocks=false; final char[] flags = srchWhatAERIPMVK.toUpperCase().toCharArray(); for (final char flag : flags) { switch(flag) { case 'E': searchWeakAreas=true; break; case 'A': searchStrictAreas=true; break; case 'R': searchRooms=true; break; case 'P': searchPlayers=true; break; case 'I': searchItems=true; break; case 'M': searchInhabs=true; break; case 'V': searchInventories=true; break; case 'K': searchStocks=true; break; } } final long startTime = System.currentTimeMillis(); if(searchRooms) { final int dirCode=Directions.getGoodDirectionCode(cmd); if((dirCode>=0)&&(curRoom!=null)) room=addWorldRoomsLiberally(rooms,curRoom.rawDoors()[dirCode]); if(room==null) room=addWorldRoomsLiberally(rooms,getRoom(cmd)); if((room == null) && (curRoom != null) && (curRoom.getArea()!=null)) room=addWorldRoomsLiberally(rooms,curRoom.getArea().getRoom(cmd)); } if(room==null) { // first get room ids if((cmd.charAt(0)=='#')&&(curRoom!=null)&&(searchRooms)) { room=addWorldRoomsLiberally(rooms,getRoom(curRoom.getArea().Name()+cmd)); if(room == null) room=addWorldRoomsLiberally(rooms,curRoom.getArea().getRoom(curRoom.getArea().Name()+cmd)); } else { final String srchStr=cmd; if(searchPlayers) { // then look for players final MOB M=CMLib.sessions().findPlayerOnline(srchStr,false); if(M!=null) room=addWorldRoomsLiberally(rooms,M.location()); } if(enforceTimeLimit(startTime,maxMillis)) return returnResponse(rooms,room); // search areas strictly if(searchStrictAreas && (room==null) && (area==null)) { area=getArea(srchStr); if((area!=null) &&(area.properSize()>0) &&(area.getProperRoomnumbers().roomCountAllAreas()>0)) room=addWorldRoomsLiberally(rooms,area); area=null; } if(enforceTimeLimit(startTime,maxMillis)) return returnResponse(rooms,room); final Area A=area; final MultiEnumeratorBuilder<Room> roomer = new MultiEnumeratorBuilder<Room>() { @SuppressWarnings("unchecked") @Override public MultiEnumeration<Room> getList() { if(A==null) return new MultiEnumeration<Room>(roomsFilled()); else return new MultiEnumeration<Room>(new Enumeration[]{A.getProperMap(),shipsRoomEnumerator(A)}); } }; // no good, so look for room inhabitants if(searchInhabs && room==null) { final Map<String,List<MOB>> finder=getMOBFinder(); List<MOB> candidates=null; if((mob==null)||(mob.isMonster())) { candidates=checkMOBCachedList(finder.get(srchStr.toLowerCase())); if(returnFirst&&(candidates!=null)&&(candidates.size()>1)) candidates=new XVector<MOB>(candidates.get(0)); } if(candidates==null) { candidates=findInhabitants(roomer.getList(), mob, srchStr,returnFirst, timePct); if((!disableCaching)&&(!returnFirst)&&((mob==null)||(mob.isMonster()))) finder.put(srchStr.toLowerCase(), candidates); } if(candidates.size()>0) room=addWorldRoomsLiberally(rooms,candidates); } if(enforceTimeLimit(startTime,maxMillis)) return returnResponse(rooms,room); // now check room text if(searchRooms && room==null) { final Map<String,List<Room>> finder=getRoomFinder(); List<Room> candidates=null; if((mob==null)||(mob.isMonster())) { candidates=finder.get(srchStr.toLowerCase()); if(returnFirst&&(candidates!=null)&&(candidates.size()>1)) candidates=new XVector<Room>(candidates.get(0)); } if(candidates==null) { candidates=findRooms(roomer.getList(), mob, srchStr, false,returnFirst, timePct); if((!disableCaching)&&(!returnFirst)&&((mob==null)||(mob.isMonster()))) finder.put(srchStr.toLowerCase(), candidates); } if(candidates.size()>0) room=addWorldRoomsLiberally(rooms,candidates); } if(enforceTimeLimit(startTime,maxMillis)) return returnResponse(rooms,room); // check floor items if(searchItems && room==null) { final Map<String,List<Item>> finder=getRoomItemFinder(); List<Item> candidates=null; if((mob==null)||(mob.isMonster())) { candidates=checkRoomItemCachedList(finder.get(srchStr.toLowerCase())); if(returnFirst&&(candidates!=null)&&(candidates.size()>1)) candidates=new XVector<Item>(candidates.get(0)); } if(candidates==null) { candidates=findRoomItems(roomer.getList(), mob, srchStr, false,returnFirst,timePct); if((!disableCaching)&&(!returnFirst)&&((mob==null)||(mob.isMonster()))) finder.put(srchStr.toLowerCase(), candidates); } if(candidates.size()>0) room=addWorldRoomsLiberally(rooms,candidates); } if(enforceTimeLimit(startTime,maxMillis)) return returnResponse(rooms,room); if(enforceTimeLimit(startTime,maxMillis)) return returnResponse(rooms,room); // check inventories if(searchInventories && room==null) { final Map<String,List<Item>> finder=getInvItemFinder(); List<Item> candidates=null; if((mob==null)||(mob.isMonster())) { candidates=checkInvCachedList(finder.get(srchStr.toLowerCase())); if(returnFirst&&(candidates!=null)&&(candidates.size()>1)) candidates=new XVector<Item>(candidates.get(0)); } if(candidates==null) { candidates=findInventory(roomer.getList(), mob, srchStr, returnFirst,timePct); if((!disableCaching)&&(!returnFirst)&&((mob==null)||(mob.isMonster()))) finder.put(srchStr.toLowerCase(), candidates); } if(candidates.size()>0) room=addWorldRoomsLiberally(rooms,candidates); } if(enforceTimeLimit(startTime,maxMillis)) return returnResponse(rooms,room); // check stocks if(searchStocks && room==null) { final Map<String,List<Environmental>> finder=getStockFinder(); List<Environmental> candidates=null; if((mob==null)||(mob.isMonster())) { candidates=finder.get(srchStr.toLowerCase()); if(returnFirst&&(candidates!=null)&&(candidates.size()>1)) candidates=new XVector<Environmental>(candidates.get(0)); } if(candidates==null) { candidates=findShopStock(roomer.getList(), mob, srchStr, returnFirst,false,timePct); if((!disableCaching)&&(!returnFirst)&&((mob==null)||(mob.isMonster()))) finder.put(srchStr.toLowerCase(), candidates); } if(candidates.size()>0) room=addWorldRoomsLiberally(rooms,candidates); } if(enforceTimeLimit(startTime,maxMillis)) return returnResponse(rooms,room); // search areas weakly if(searchWeakAreas && (room==null) && (A==null)) { Area A2=findArea(srchStr); if((A2!=null) &&(A2.properSize()>0) &&(A2.getProperRoomnumbers().roomCountAllAreas()>0)) room=addWorldRoomsLiberally(rooms,A2); } } } final List<Room> responseSet = returnResponse(rooms,room); return responseSet; } @Override public boolean isHere(CMObject E2, Room here) { if(E2==null) return false; else if(E2==here) return true; else if((E2 instanceof MOB) &&(((MOB)E2).location()==here)) return true; else if((E2 instanceof Item) &&(((Item)E2).owner()==here)) return true; else if((E2 instanceof Item) &&(((Item)E2).owner()!=null) &&(((Item)E2).owner() instanceof MOB) &&(((MOB)((Item)E2).owner()).location()==here)) return true; else if(E2 instanceof Exit) { for(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--) if(here.getRawExit(d)==E2) return true; } return false; } @Override public boolean isHere(CMObject E2, Area here) { if(E2==null) return false; else if(E2==here) return true; else if(E2 instanceof Room) return ((Room)E2).getArea()==here; else if(E2 instanceof MOB) return isHere(((MOB)E2).location(),here); else if(E2 instanceof Item) return isHere(((Item)E2).owner(),here); return false; } protected PairVector<MOB,String> getAllPlayersHere(Area area, boolean includeLocalFollowers) { final PairVector<MOB,String> playersHere=new PairVector<MOB,String>(); MOB M=null; Room R=null; for(final Session S : CMLib.sessions().localOnlineIterable()) { M=S.mob(); R=(M!=null)?M.location():null; if((R!=null)&&(R.getArea()==area)&&(M!=null)) { playersHere.addElement(M,getExtendedRoomID(R)); if(includeLocalFollowers) { MOB M2=null; final Set<MOB> H=M.getGroupMembers(new HashSet<MOB>()); for(final Iterator<MOB> i=H.iterator();i.hasNext();) { M2=i.next(); if((M2!=M)&&(M2.location()==R)) playersHere.addElement(M2,getExtendedRoomID(R)); } } } } return playersHere; } @Override public void resetArea(Area area) { final Area.State oldFlag=area.getAreaState(); area.setAreaState(Area.State.FROZEN); final PairVector<MOB,String> playersHere=getAllPlayersHere(area,true); final PairVector<PrivateProperty, String> propertyHere=new PairVector<PrivateProperty, String>(); for(int p=0;p<playersHere.size();p++) { final MOB M=playersHere.elementAt(p).first; final Room R=M.location(); R.delInhabitant(M); } for(final Enumeration<BoardableShip> b=ships();b.hasMoreElements();) { final BoardableShip ship=b.nextElement(); final Room R=roomLocation(ship); if((R!=null) &&(R.getArea()==area) &&(ship instanceof PrivateProperty) &&(((PrivateProperty)ship).getOwnerName().length()>0) &&(ship instanceof Item)) { R.delItem((Item)ship); propertyHere.add((PrivateProperty)ship,CMLib.map().getExtendedRoomID(R)); } } for(final Enumeration<Room> r=area.getProperMap();r.hasMoreElements();) resetRoom(r.nextElement()); area.fillInAreaRooms(); for(int p=0;p<playersHere.size();p++) { final MOB M=playersHere.elementAt(p).first; Room R=getRoom(playersHere.elementAt(p).second); if(R==null) R=M.getStartRoom(); if(R==null) R=getStartRoom(M); if(R!=null) R.bringMobHere(M,false); } for(int p=0;p<propertyHere.size();p++) { final PrivateProperty P=propertyHere.elementAt(p).first; Room R=getRoom(propertyHere.elementAt(p).second); if((R==null)||(R.amDestroyed())) R=getSafeRoomToMovePropertyTo((R==null)?area.getRandomProperRoom():R,P); if(R!=null) R.moveItemTo((Item)P); } CMLib.database().DBReadAreaData(area); area.setAreaState(oldFlag); } @Override public boolean hasASky(Room room) { if((room==null) ||(room.domainType()==Room.DOMAIN_OUTDOORS_UNDERWATER) ||((room.domainType()&Room.INDOORS)>0)) return false; return true; } @Override public void registerWorldObjectDestroyed(Area area, Room room, CMObject o) { if(o instanceof Deity) delDeity((Deity)o); if(o instanceof BoardableShip) delShip((BoardableShip)o); if(o instanceof PostOffice) delPostOffice((PostOffice)o); if(o instanceof Banker) delBank((Banker)o); if(o instanceof Auctioneer) delAuctionHouse((Auctioneer)o); if(o instanceof PhysicalAgent) { final PhysicalAgent AE=(PhysicalAgent)o; if((area == null) && (room!=null)) area = room.getArea(); if(area == null) area =getStartArea(AE); delScriptHost(area, AE); } } @Override public void registerWorldObjectLoaded(Area area, Room room, final CMObject o) { if(o instanceof Deity) addDeity((Deity)o); if(o instanceof BoardableShip) addShip((BoardableShip)o); if(o instanceof PostOffice) addPostOffice((PostOffice)o); if(o instanceof Banker) addBank((Banker)o); if(o instanceof Auctioneer) addAuctionHouse((Auctioneer)o); if(o instanceof PhysicalAgent) { final PhysicalAgent AE=(PhysicalAgent)o; if(room == null) room = getStartRoom(AE); if((area == null) && (room!=null)) area = room.getArea(); if(area == null) area = getStartArea(AE); addScriptHost(area, room, AE); if(o instanceof MOB) for(final Enumeration<Item> i=((MOB)o).items();i.hasMoreElements();) addScriptHost(area, room, i.nextElement()); } } protected void cleanScriptHosts(final SLinkedList<LocatedPair> hosts, final PhysicalAgent oneToDel, final boolean fullCleaning) { PhysicalAgent PA; for (final LocatedPair W : hosts) { if(W==null) hosts.remove(W); else { PA=W.obj(); if((PA==null) ||(PA==oneToDel) ||(PA.amDestroyed()) ||((fullCleaning)&&(!isAQualifyingScriptHost(PA)))) hosts.remove(W); } } } protected boolean isAQualifyingScriptHost(final PhysicalAgent host) { if(host==null) return false; for(final Enumeration<Behavior> e = host.behaviors();e.hasMoreElements();) { final Behavior B=e.nextElement(); if((B!=null) && B.isSavable() && (B instanceof ScriptingEngine)) return true; } for(final Enumeration<ScriptingEngine> e = host.scripts();e.hasMoreElements();) { final ScriptingEngine SE=e.nextElement(); if((SE!=null) && SE.isSavable()) return true; } return false; } @Override public int numSpaceObjects() { return space.count(); } protected boolean isAScriptHost(final Area area, final PhysicalAgent host) { if(area == null) return false; return isAScriptHost(scriptHostMap.get(area.Name()), host); } protected boolean isAScriptHost(final SLinkedList<LocatedPair> hosts, final PhysicalAgent host) { if((hosts==null)||(host==null)||(hosts.size()==0)) return false; for (final LocatedPair W : hosts) { if(W.obj()==host) return true; } return false; } protected final Object getScriptHostSemaphore(final Area area) { final Object semaphore; if(SCRIPT_HOST_SEMAPHORES.containsKey(area.Name())) semaphore=SCRIPT_HOST_SEMAPHORES.get(area.Name()); else { synchronized(SCRIPT_HOST_SEMAPHORES) { semaphore=new Object(); SCRIPT_HOST_SEMAPHORES.put(area.Name(), semaphore); } } return semaphore; } protected void addScriptHost(Area area, Room room, PhysicalAgent host) { if((area==null) || (host == null)) return; if(!isAQualifyingScriptHost(host)) return; synchronized(getScriptHostSemaphore(area)) { SLinkedList<LocatedPair> hosts = scriptHostMap.get(area.Name()); if(hosts == null) { hosts=new SLinkedList<LocatedPair>(); scriptHostMap.put(area.Name(), hosts); } else { cleanScriptHosts(hosts, null, false); if(isAScriptHost(hosts,host)) return; } hosts.add(new LocatedPairImpl(room, host)); } } protected void delScriptHost(Area area, final PhysicalAgent oneToDel) { if(oneToDel == null) return; if(area == null) for(final Area A : areasList) if(isAScriptHost(A,oneToDel)) { area = A; break; } if(area == null) return; synchronized(getScriptHostSemaphore(area)) { final SLinkedList<LocatedPair> hosts = scriptHostMap.get(area.Name()); if(hosts==null) return; cleanScriptHosts(hosts, oneToDel, false); } } @Override @SuppressWarnings("unchecked") public Enumeration<LocatedPair> scriptHosts(final Area area) { final LinkedList<List<LocatedPair>> V = new LinkedList<List<LocatedPair>>(); if(area == null) { for(final String areaKey : scriptHostMap.keySet()) V.add(scriptHostMap.get(areaKey)); } else { final SLinkedList<LocatedPair> hosts = scriptHostMap.get(area.Name()); if(hosts==null) return EmptyEnumeration.INSTANCE; V.add(hosts); } if(V.size()==0) return EmptyEnumeration.INSTANCE; final MultiListEnumeration<LocatedPair> me=new MultiListEnumeration<LocatedPair>(V,true); return new Enumeration<LocatedPair>() { @Override public boolean hasMoreElements() { return me.hasMoreElements(); } @Override public LocatedPair nextElement() { final LocatedPair W = me.nextElement(); final PhysicalAgent E = W.obj(); if(((E==null) || (E.amDestroyed())) && hasMoreElements()) return nextElement(); return W; } }; } @Override public boolean activate() { if(serviceClient==null) { name="THMap"+Thread.currentThread().getThreadGroup().getName().charAt(0); serviceClient=CMLib.threads().startTickDown(this, Tickable.TICKID_SUPPORT|Tickable.TICKID_SOLITARYMASK, MudHost.TIME_SAVETHREAD_SLEEP, 1); } return true; } @Override public boolean tick(Tickable ticking, int tickID) { try { if((!CMSecurity.isDisabled(CMSecurity.DisFlag.SAVETHREAD)) &&(!CMSecurity.isDisabled(CMSecurity.DisFlag.MAPTHREAD))) { isDebugging=CMSecurity.isDebugging(DbgFlag.MAPTHREAD); tickStatus=Tickable.STATUS_ALIVE; if(checkDatabase()) roomMaintSweep(); } Resources.savePropResources(); } finally { tickStatus=Tickable.STATUS_NOT; setThreadStatus(serviceClient,"sleeping"); } return true; } @Override public boolean shutdown() { final boolean debugMem = CMSecurity.isDebugging(CMSecurity.DbgFlag.SHUTDOWN); for(Enumeration<Area> a=areasList.elements();a.hasMoreElements();) { try { final Area A = a.nextElement(); if(A!=null) { CMProps.setUpAllLowVar(CMProps.Str.MUDSTATUS,"Shutting down Map area '"+A.Name()+"'..."); for(Enumeration<Room> r=A.getProperMap();r.hasMoreElements();) { try { final Room R=r.nextElement(); A.delProperRoom(R); R.destroy(); } catch(Exception e) { } } } if(debugMem) { try { Object obj = new Object(); WeakReference<Object> ref = new WeakReference<Object>(obj); obj = null; System.gc(); System.runFinalization(); while(ref.get() != null) { System.gc(); } Thread.sleep(3000); } catch (final Exception e) { } final long free=Runtime.getRuntime().freeMemory()/1024; final long total=Runtime.getRuntime().totalMemory()/1024; if(A!=null) Log.debugOut("Memory: CMMap: "+A.Name()+": "+(total-free)+"/"+total); } } catch (Exception e) { } } areasList.clear(); deitiesList.clear(); shipList.clear(); space.clear(); globalHandlers.clear(); if(CMLib.threads().isTicking(this, TICKID_SUPPORT|Tickable.TICKID_SOLITARYMASK)) { CMLib.threads().deleteTick(this, TICKID_SUPPORT|Tickable.TICKID_SOLITARYMASK); serviceClient=null; } return true; } public void roomMaintSweep() { final boolean corpsesOnly=CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMITEMS); final boolean noMobs=CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMMOBS); setThreadStatus(serviceClient,"expiration sweep"); final long currentTime=System.currentTimeMillis(); final boolean debug=CMSecurity.isDebugging(CMSecurity.DbgFlag.VACUUM); final MOB expireM=getFactoryMOB(null); try { final List<Environmental> stuffToGo=new ArrayList<Environmental>(); Item I=null; MOB M=null; Room R=null; final List<Room> roomsToGo=new ArrayList<Room>(); final CMMsg expireMsg=CMClass.getMsg(expireM,R,null,CMMsg.MSG_EXPIRE,null); for(final Enumeration<Room> r=rooms();r.hasMoreElements();) { R=r.nextElement(); expireM.setLocation(R); expireMsg.setTarget(R); if((R.expirationDate()!=0) &&(currentTime>R.expirationDate()) &&(R.okMessage(R,expireMsg))) roomsToGo.add(R); else if(!R.amDestroyed()) { stuffToGo.clear(); for(int i=0;i<R.numItems();i++) { I=R.getItem(i); if((I!=null) &&((!corpsesOnly)||(I instanceof DeadBody)) &&(I.expirationDate()!=0) &&(I.owner()==R) &&(currentTime>I.expirationDate())) stuffToGo.add(I); } for(int i=0;i<R.numInhabitants();i++) { M=R.fetchInhabitant(i); if((M!=null) &&(!noMobs) &&(M.expirationDate()!=0) &&(currentTime>M.expirationDate())) stuffToGo.add(M); } } if(stuffToGo.size()>0) { boolean success=true; for(int s=0;s<stuffToGo.size();s++) { final Environmental E=stuffToGo.get(s); setThreadStatus(serviceClient,"expiring "+E.Name()); expireMsg.setTarget(E); if(R.okMessage(expireM,expireMsg)) R.sendOthers(expireM,expireMsg); else success=false; if(debug) Log.sysOut("UTILITHREAD","Expired "+E.Name()+" in "+getExtendedRoomID(R)+": "+success); } stuffToGo.clear(); } } for(int r=0;r<roomsToGo.size();r++) { R=roomsToGo.get(r); expireM.setLocation(R); expireMsg.setTarget(R); setThreadStatus(serviceClient,"expirating room "+getExtendedRoomID(R)); if(debug) { String roomID=getExtendedRoomID(R); if(roomID.length()==0) roomID="(unassigned grid room, probably in the air)"; if(debug) Log.sysOut("UTILITHREAD","Expired "+roomID+"."); } R.sendOthers(expireM,expireMsg); } } catch(final java.util.NoSuchElementException e) {} setThreadStatus(serviceClient,"title sweeping"); final List<String> playerList=CMLib.database().getUserList(); try { for(final Enumeration<Room> r=rooms();r.hasMoreElements();) { final Room R=r.nextElement(); final LandTitle T=CMLib.law().getLandTitle(R); if(T!=null) { setThreadStatus(serviceClient,"checking title in "+R.roomID()+": "+Runtime.getRuntime().freeMemory()); T.updateLot(playerList); setThreadStatus(serviceClient,"title sweeping"); } } } catch(final NoSuchElementException nse) {} setThreadStatus(serviceClient,"cleaning scripts"); for(final String areaKey : scriptHostMap.keySet()) cleanScriptHosts(scriptHostMap.get(areaKey), null, true); final long lastDateTime=System.currentTimeMillis()-(5*TimeManager.MILI_MINUTE); setThreadStatus(serviceClient,"checking"); try { for(final Enumeration<Room> r=rooms();r.hasMoreElements();) { final Room R=r.nextElement(); for(int m=0;m<R.numInhabitants();m++) { final MOB mob=R.fetchInhabitant(m); if((mob!=null)&&(mob.lastTickedDateTime()>0)&&(mob.lastTickedDateTime()<lastDateTime)) { final boolean ticked=CMLib.threads().isTicking(mob,Tickable.TICKID_MOB); final boolean isDead=mob.amDead(); final Room startR=mob.getStartRoom(); final String wasFrom=(startR!=null)?startR.roomID():"NULL"; if(!ticked) { if(CMLib.players().getPlayer(mob.Name())==null) { if(ticked) { // we have a dead group.. let the group handler deal with it. Log.errOut(serviceClient.getName(),mob.name()+" in room "+R.roomID()+" unticked in dead group (Home="+wasFrom+") since: "+CMLib.time().date2String(mob.lastTickedDateTime())+"."); continue; } else Log.errOut(serviceClient.getName(),mob.name()+" in room "+R.roomID()+" unticked (is ticking="+(ticked)+", dead="+isDead+", Home="+wasFrom+") since: "+CMLib.time().date2String(mob.lastTickedDateTime())+"."+(ticked?"":" This mob has been destroyed. May he rest in peace.")); } else Log.errOut(serviceClient.getName(),"Player "+mob.name()+" in room "+R.roomID()+" unticked (is ticking="+(ticked)+", dead="+isDead+", Home="+wasFrom+") since: "+CMLib.time().date2String(mob.lastTickedDateTime())+"."+(ticked?"":" This mob has been put aside.")); setThreadStatus(serviceClient,"destroying unticked mob "+mob.name()); if(CMLib.players().getPlayer(mob.Name())==null) mob.destroy(); R.delInhabitant(mob); setThreadStatus(serviceClient,"checking"); } } } } } catch(final java.util.NoSuchElementException e) { } finally { if(expireM!=null) expireM.destroy(); } } protected final static char[] cmfsFilenameifyChars=new char[]{'/','\\',' '}; protected String cmfsFilenameify(String str) { return CMStrings.replaceAllofAny(str, cmfsFilenameifyChars, '_').toLowerCase().trim(); } // this is a beautiful idea, but im scared of the memory of all the final refs protected void addMapStatFiles(final List<CMFile.CMVFSFile> rootFiles, final Room R, final Environmental E, final CMFile.CMVFSDir root) { rootFiles.add(new CMFile.CMVFSDir(root,root.getPath()+"stats/") { @Override protected CMFile.CMVFSFile[] getFiles() { final List<CMFile.CMVFSFile> myFiles=new Vector<CMFile.CMVFSFile>(); final String[] stats=E.getStatCodes(); final String oldName=E.Name(); for (final String statName : stats) { final String statValue=E.getStat(statName); myFiles.add(new CMFile.CMVFSFile(this.getPath()+statName,256,System.currentTimeMillis(),"SYS") { @Override public int getMaskBits(MOB accessor) { if(accessor==null) return this.mask; if((E instanceof Area)&&(CMSecurity.isAllowed(accessor,((Area)E).getRandomProperRoom(),CMSecurity.SecFlag.CMDAREAS))) return this.mask; else if(CMSecurity.isAllowed(accessor,R,CMSecurity.SecFlag.CMDROOMS)) return this.mask; else if((E instanceof MOB) && CMSecurity.isAllowed(accessor,R,CMSecurity.SecFlag.CMDMOBS)) return this.mask; else if((E instanceof Item) && CMSecurity.isAllowed(accessor,R,CMSecurity.SecFlag.CMDITEMS)) return this.mask; return this.mask|48; } @Override public Object readData() { return statValue; } @Override public void saveData(String filename, int vfsBits, String author, Object O) { E.setStat(statName, O.toString()); if(E instanceof Area) CMLib.database().DBUpdateArea(oldName, (Area)E); else if(E instanceof Room) CMLib.database().DBUpdateRoom((Room)E); else if(E instanceof MOB) CMLib.database().DBUpdateMOB(R.roomID(), (MOB)E); else if(E instanceof Item) CMLib.database().DBUpdateItem(R.roomID(), (Item)E); } }); } Collections.sort(myFiles,CMFile.CMVFSDir.fcomparator); return myFiles.toArray(new CMFile.CMVFSFile[0]); } }); } @Override public CMFile.CMVFSDir getMapRoot(final CMFile.CMVFSDir root) { return new CMFile.CMVFSDir(root,root.getPath()+"map/") { @Override protected CMFile.CMVFSFile[] getFiles() { final List<CMFile.CMVFSFile> myFiles=new Vector<CMFile.CMVFSFile>(numAreas()); for(final Enumeration<Area> a=CMLib.map().areas();a.hasMoreElements();) { final Area A=a.nextElement(); myFiles.add(new CMFile.CMVFSFile(this.getPath()+cmfsFilenameify(A.Name())+".cmare",48,System.currentTimeMillis(),"SYS") { @Override public Object readData() { return CMLib.coffeeMaker().getAreaXML(A, null, null, null, true); } }); myFiles.add(new CMFile.CMVFSDir(this,this.getPath()+cmfsFilenameify(A.Name())+"/") { @Override protected CMFile.CMVFSFile[] getFiles() { final List<CMFile.CMVFSFile> myFiles=new Vector<CMFile.CMVFSFile>(); for(final Enumeration<Room> r=A.getFilledProperMap();r.hasMoreElements();) { final Room R=r.nextElement(); if(R.roomID().length()>0) { String roomID=R.roomID(); if(roomID.startsWith(A.Name()+"#")) roomID=roomID.substring(A.Name().length()+1); myFiles.add(new CMFile.CMVFSFile(this.getPath()+cmfsFilenameify(R.roomID())+".cmare",48,System.currentTimeMillis(),"SYS") { @Override public Object readData() { return CMLib.coffeeMaker().getRoomXML(R, null, null, true); } }); myFiles.add(new CMFile.CMVFSDir(this,this.getPath()+cmfsFilenameify(roomID).toLowerCase()+"/") { @Override protected CMFile.CMVFSFile[] getFiles() { final List<CMFile.CMVFSFile> myFiles=new Vector<CMFile.CMVFSFile>(); myFiles.add(new CMFile.CMVFSFile(this.getPath()+"items.cmare",48,System.currentTimeMillis(),"SYS") { @Override public Object readData() { return CMLib.coffeeMaker().getRoomItems(R, new TreeMap<String,List<Item>>(), null, null); } }); myFiles.add(new CMFile.CMVFSFile(this.path+"mobs.cmare",48,System.currentTimeMillis(),"SYS") { @Override public Object readData() { return CMLib.coffeeMaker().getRoomMobs(R, null, null, new TreeMap<String,List<MOB>>()); } }); myFiles.add(new CMFile.CMVFSDir(this,this.path+"mobs/") { @Override protected CMFile.CMVFSFile[] getFiles() { final List<CMFile.CMVFSFile> myFiles=new Vector<CMFile.CMVFSFile>(); final Room R2=CMLib.coffeeMaker().makeNewRoomContent(R, false); for(int i=0;i<R2.numInhabitants();i++) { final MOB M=R2.fetchInhabitant(i); myFiles.add(new CMFile.CMVFSFile(this.path+cmfsFilenameify(R2.getContextName(M))+".cmare",48,System.currentTimeMillis(),"SYS") { @Override public Object readData() { return CMLib.coffeeMaker().getMobXML(M); } }); myFiles.add(new CMFile.CMVFSDir(this,this.path+cmfsFilenameify(R2.getContextName(M))+"/") { @Override protected CMFile.CMVFSFile[] getFiles() { final List<CMFile.CMVFSFile> myFiles=new Vector<CMFile.CMVFSFile>(); addMapStatFiles(myFiles,R,M,this); Collections.sort(myFiles,CMFile.CMVFSDir.fcomparator); return myFiles.toArray(new CMFile.CMVFSFile[0]); } }); } Collections.sort(myFiles,CMFile.CMVFSDir.fcomparator); return myFiles.toArray(new CMFile.CMVFSFile[0]); } }); myFiles.add(new CMFile.CMVFSDir(this,this.path+"items/") { @Override protected CMFile.CMVFSFile[] getFiles() { final List<CMFile.CMVFSFile> myFiles=new Vector<CMFile.CMVFSFile>(); final Room R2=CMLib.coffeeMaker().makeNewRoomContent(R, false); if(R2 != null) { for(int i=0;i<R2.numItems();i++) { final Item I=R2.getItem(i); myFiles.add(new CMFile.CMVFSFile(this.path+cmfsFilenameify(R2.getContextName(I))+".cmare",48,System.currentTimeMillis(),"SYS") { @Override public Object readData() { return CMLib.coffeeMaker().getItemXML(I); } }); myFiles.add(new CMFile.CMVFSDir(this,this.path+cmfsFilenameify(R2.getContextName(I))+"/") { @Override protected CMFile.CMVFSFile[] getFiles() { final List<CMFile.CMVFSFile> myFiles=new Vector<CMFile.CMVFSFile>(); addMapStatFiles(myFiles,R,I,this); Collections.sort(myFiles,CMFile.CMVFSDir.fcomparator); return myFiles.toArray(new CMFile.CMVFSFile[0]); } }); } Collections.sort(myFiles,CMFile.CMVFSDir.fcomparator); return myFiles.toArray(new CMFile.CMVFSFile[0]); } return new CMFile.CMVFSFile[0]; } }); addMapStatFiles(myFiles,R,R,this); Collections.sort(myFiles,CMFile.CMVFSDir.fcomparator); return myFiles.toArray(new CMFile.CMVFSFile[0]); } }); } } addMapStatFiles(myFiles,null,A,this); Collections.sort(myFiles,CMFile.CMVFSDir.fcomparator); return myFiles.toArray(new CMFile.CMVFSFile[0]); } }); } Collections.sort(myFiles,CMFile.CMVFSDir.fcomparator); return myFiles.toArray(new CMFile.CMVFSFile[0]); } }; } }