package com.planet_ink.coffee_mud.Locales; import com.planet_ink.coffee_mud.core.interfaces.*; import com.planet_ink.coffee_mud.core.smtp.SMTPserver; import com.planet_ink.coffee_mud.core.*; import com.planet_ink.coffee_mud.core.collections.*; import com.planet_ink.coffee_mud.Abilities.interfaces.*; import com.planet_ink.coffee_mud.Areas.interfaces.*; import com.planet_ink.coffee_mud.Areas.interfaces.GridZones.XYVector; 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.Locales.interfaces.*; import com.planet_ink.coffee_mud.MOBS.interfaces.*; import com.planet_ink.coffee_mud.Races.interfaces.*; import com.planet_ink.coffee_mud.Libraries.interfaces.*; import java.util.*; /* Copyright 2004-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. */ @SuppressWarnings({"unchecked","rawtypes"}) public class StdThinGrid extends StdRoom implements GridLocale { @Override public String ID() { return "StdThinGrid"; } protected String[] descriptions=new String[0]; protected String[] displayTexts=new String[0]; protected SVector<CrossExit> gridexits=new SVector<CrossExit>(1); protected int xsize=5; protected int ysize=5; protected int yLength=1; protected Exit ox=null; protected final SVector<ThinGridEntry> rooms=new SVector<ThinGridEntry>(); protected static boolean tickStarted=false; public StdThinGrid() { super(); myID=getClass().getName().substring(getClass().getName().lastIndexOf('.')+1); } @Override protected void cloneFix(Room E) { super.cloneFix(E); if(E instanceof StdThinGrid) { descriptions=((StdThinGrid)E).descriptions.clone(); displayTexts=((StdThinGrid)E).displayTexts.clone(); gridexits=((StdThinGrid)E).gridexits.copyOf(); } } protected static class ThinGridEntryConverter implements Converter<ThinGridEntry, Room> { public static ThinGridEntryConverter INSTANCE = new ThinGridEntryConverter(); @Override public Room convert(ThinGridEntry obj) { return obj.room; } } protected static class ThinGridEntry { public Room room; public XYVector xy; public ThinGridEntry(Room R, int x, int y) { room = R; xy = new XYVector(x, y); } } @Override public String getGridChildLocaleID() { return "StdRoom"; } @Override public int xGridSize() { return xsize; } @Override public int yGridSize() { return ysize; } @Override public void setXGridSize(int x) { if(x>0) xsize=x; } @Override public void setYGridSize(int y) { if(y>0) ysize=y; yLength=Integer.toString(ysize).length(); } @Override public void destroy() { super.destroy(); Room R=null; for(int i=rooms.size()-1;i>=0;i--) { R=rooms.elementAt(i).room; if(R!=null) R.destroy(); } rooms.clear(); descriptions=new String[0]; displayTexts=new String[0]; gridexits=new SVector(1); } @Override public void setDescription(String newDescription) { super.setDescription(newDescription); final Vector<String> descriptions=new Vector<String>(); int x=newDescription.toUpperCase().indexOf("<P>"); while(x>=0) { final String s=newDescription.substring(0,x).trim(); if(s.length()>0) descriptions.addElement(s); newDescription=newDescription.substring(x+3).trim(); x=newDescription.toUpperCase().indexOf("<P>"); } if(newDescription.length()>0) descriptions.addElement(newDescription); this.descriptions = descriptions.toArray(new String[0]); } @Override public void setDisplayText(String newDisplayText) { super.setDisplayText(newDisplayText); final Vector<String> displayTexts=new Vector<String>(); int x=newDisplayText.toUpperCase().indexOf("<P>"); while(x>=0) { final String s=newDisplayText.substring(0,x).trim(); if(s.length()>0) displayTexts.addElement(s); newDisplayText=newDisplayText.substring(x+3).trim(); x=newDisplayText.toUpperCase().indexOf("<P>"); } if(newDisplayText.length()>0) displayTexts.addElement(newDisplayText); this.displayTexts = displayTexts.toArray(new String[0]); } @Override public Room prepareRoomInDir(Room fromRoom, int direction) { if(amDestroyed) { final Room R=CMLib.map().getRoom(roomID()); if(R!=null) return R.prepareRoomInDir(fromRoom,direction); return super.prepareRoomInDir(fromRoom,direction); } return getAltRoomFrom(fromRoom,direction); } private int properRoomIndex(int x, int y) { if(rooms.size()==0) return 0; synchronized(rooms) { int start=0; int end=rooms.size()-1; int comp=0; final long total=((long)x<<31)+y; long comptotal=0; int mid=0; while(start<=end) { mid=(end+start)/2; comptotal=((long)rooms.elementAt(mid).xy.x<<31)+rooms.elementAt(mid).xy.y; comp=comptotal>total?1:(comptotal==total)?0:-1; if(comp==0) return mid; else if(comp>0) end=mid-1; else start=mid+1; } if(end<0) return 0; if(start>=rooms.size()) return rooms.size()-1; return mid; } } private void addSortedRoom(Room R, int x, int y) { if((x<0)||(y<0)||(y>=yGridSize())||(x>=xGridSize())||(R==null)) return ; synchronized(rooms) { final long total=((long)x<<31)+y; final int pos=properRoomIndex(x,y); final ThinGridEntry entry = new ThinGridEntry(R,x,y); if(pos>=rooms.size()) { rooms.addElement(entry); return; } final long comptotal=((long)rooms.elementAt(pos).xy.x<<31)+rooms.elementAt(pos).xy.y; final int comp=comptotal>total?1:(comptotal==total)?0:-1; if(comp==0) return; if(comp>0) rooms.add(pos,entry); else if(pos==rooms.size()-1) rooms.add(entry); else rooms.add(pos+1,entry); } } private Room getSortedRoom(int x,int y) { if(rooms.size()==0) return null; synchronized(rooms) { final int pos=properRoomIndex(x,y); if((rooms.elementAt(pos).xy.x==x)&&(rooms.elementAt(pos).xy.y==y)) return rooms.elementAt(pos).room; } return null; } protected Room getGridRoomIfExists(int x, int y) { final Room R=getSortedRoom(x,y); if(R!=null) R.setExpirationDate(System.currentTimeMillis()+WorldMap.ROOM_EXPIRATION_MILLIS); return R; } @Override public Room prepareGridLocale(Room fromRoom, Room toRoom, int direction) { final XYVector xy=getRoomXY(fromRoom); if((xy.x>=0)&&(xy.x<xGridSize())&&(xy.y>=0)&&(xy.y<yGridSize())) fillExitsOfGridRoom(fromRoom,xy.x,xy.y); return fromRoom.rawDoors()[direction]; } @Override public Room getGridChild(int x, int y) { return getMakeGridRoom(x,y); } @Override public Room getGridChild(XYVector xy) { return getGridChild(xy.x,xy.y); } protected Room getMakeSingleGridRoom(int x, int y) { if((x<0)||(y<0)||(y>=yGridSize())||(x>=xGridSize())) return null; Room R=getGridRoomIfExists(x,y); if(R==null) { synchronized(rooms) { R=getGridRoomIfExists(x,y); if(R!=null) return R; R=CMClass.getLocale(getGridChildLocaleID()); if(R==null) return null; R.setGridParent(this); R.setRoomID(""); R.setDisplayText(displayText()); R.setDescription(description()); int c=-1; if(displayTexts!=null) if(displayTexts.length>0) { c=CMLib.dice().roll(1,displayTexts.length,-1); R.setDisplayText(displayTexts[c]); } if(descriptions!=null) if(descriptions.length>0) { if((c<0)||(c>descriptions.length)||(descriptions.length!=displayTexts.length)) c=CMLib.dice().roll(1,descriptions.length,-1); R.setDescription(descriptions[c]); } for(int a=0;a<numEffects();a++) R.addEffect((Ability)fetchEffect(a).copyOf()); if(behaviors != null) { for(final Behavior B : behaviors) R.addBehavior((Behavior)B.copyOf()); } R.setExpirationDate(System.currentTimeMillis()+WorldMap.ROOM_EXPIRATION_MILLIS); addSortedRoom(R,x,y); R.setArea(getArea()); //R.giveASky(0); } } return R; } @Override public XYVector getRoomXY(Room room) { if((room.getGridParent()!=this) &&(room.getGridParent()!=null)) return null; try { for(final ThinGridEntry entry : rooms) { if(entry.room==room) return entry.xy; } } catch(final Exception x) { } return null; } @Override public XYVector getRoomXY(String roomID) { final Room room=CMLib.map().getRoom(roomID); if(room==null) return null; return getRoomXY(room); } protected void fillExitsOfGridRoom(Room R, int x, int y) { if((x<0)||(y<0)||(y>=yGridSize())||(x>=xGridSize())) return; synchronized(R.basePhyStats()) { final int mask=R.basePhyStats().sensesMask(); if(CMath.bset(mask,PhyStats.SENSE_ROOMGRIDSYNC)) return; R.basePhyStats().setSensesMask(mask|PhyStats.SENSE_ROOMGRIDSYNC); } // the adjacent rooms created by this method should also take // into account the possibility that they are on the edge. // it does NOT if(ox==null) ox=CMClass.getExit("Open"); Room R2=null; if(y>0) { R2=getMakeSingleGridRoom(x,y-1); if(R2!=null) linkRoom(R,R2,Directions.NORTH,ox,ox); } else if((rawDoors()[Directions.NORTH]!=null)&&(exits[Directions.NORTH]!=null)) linkRoom(R,rawDoors()[Directions.NORTH],Directions.NORTH,exits[Directions.NORTH],exits[Directions.NORTH]); if(x>0) { R2=getMakeSingleGridRoom(x-1,y); if(R2!=null) linkRoom(R,R2,Directions.WEST,ox,ox); } else if((rawDoors()[Directions.WEST]!=null)&&(exits[Directions.WEST]!=null)) linkRoom(R,rawDoors()[Directions.WEST],Directions.WEST,exits[Directions.WEST],exits[Directions.WEST]); if(y<(yGridSize()-1)) { R2=getMakeSingleGridRoom(x,y+1); if(R2!=null) linkRoom(R,R2,Directions.SOUTH,ox,ox); } else if((rawDoors()[Directions.SOUTH]!=null)&&(exits[Directions.SOUTH]!=null)) linkRoom(R,rawDoors()[Directions.SOUTH],Directions.SOUTH,exits[Directions.SOUTH],exits[Directions.SOUTH]); if(x<(xGridSize()-1)) { R2=getMakeSingleGridRoom(x+1,y); if(R2!=null) linkRoom(R,R2,Directions.EAST,ox,ox); } else if((rawDoors()[Directions.EAST]!=null)&&(exits[Directions.EAST]!=null)) linkRoom(R,rawDoors()[Directions.EAST],Directions.EAST,exits[Directions.EAST],exits[Directions.EAST]); if(Directions.NORTHEAST<Directions.NUM_DIRECTIONS()) { if((y>0)&&(x>0)) { R2=getMakeSingleGridRoom(x-1,y-1); if(R2!=null) linkRoom(R,R2,Directions.NORTHWEST,ox,ox); } else if((rawDoors()[Directions.NORTHWEST]!=null)&&(exits[Directions.NORTHWEST]!=null)) linkRoom(R,rawDoors()[Directions.NORTHWEST],Directions.NORTHWEST,exits[Directions.NORTHWEST],exits[Directions.NORTHWEST]); if((x>0)&&(y<(yGridSize()-1))) { R2=getMakeSingleGridRoom(x-1,y+1); if(R2!=null) linkRoom(R,R2,Directions.SOUTHWEST,ox,ox); } else if((rawDoors()[Directions.SOUTHWEST]!=null)&&(exits[Directions.SOUTHWEST]!=null)) linkRoom(R,rawDoors()[Directions.SOUTHWEST],Directions.SOUTHWEST,exits[Directions.SOUTHWEST],exits[Directions.SOUTHWEST]); if((x<(xGridSize()-1))&&(y>0)) { R2=getMakeSingleGridRoom(x+1,y-1); if(R2!=null) linkRoom(R,R2,Directions.NORTHEAST,ox,ox); } else if((rawDoors()[Directions.NORTHEAST]!=null)&&(exits[Directions.NORTHEAST]!=null)) linkRoom(R,rawDoors()[Directions.NORTHEAST],Directions.NORTHEAST,exits[Directions.NORTHEAST],exits[Directions.NORTHEAST]); if((x<(xGridSize()-1))&&(y<(yGridSize()-1))) { R2=getMakeSingleGridRoom(x+1,y+1); if(R2!=null) linkRoom(R,R2,Directions.SOUTHEAST,ox,ox); } else if((rawDoors()[Directions.SOUTHEAST]!=null)&&(exits[Directions.SOUTHEAST]!=null)) linkRoom(R,rawDoors()[Directions.SOUTHEAST],Directions.SOUTHEAST,exits[Directions.SOUTHEAST],exits[Directions.SOUTHEAST]); } for(int d=0;d<gridexits.size();d++) { final CrossExit EX=gridexits.elementAt(d); try { if((EX.out)&&(EX.x==x)&&(EX.y==y)) { switch(EX.dir) { case Directions.NORTH: if(EX.y==0) tryFillInExtraneousExternal(EX,ox,R); break; case Directions.SOUTH: if(EX.y==yGridSize()-1) tryFillInExtraneousExternal(EX,ox,R); break; case Directions.EAST: if(EX.x==xGridSize()-1) tryFillInExtraneousExternal(EX,ox,R); break; case Directions.WEST: if(EX.x==0) tryFillInExtraneousExternal(EX,ox,R); break; case Directions.NORTHEAST: if((EX.y==0)&&(EX.x==xGridSize()-1)) tryFillInExtraneousExternal(EX,ox,R); break; case Directions.SOUTHWEST: if((EX.y==yGridSize()-1)&&(EX.x==0)) tryFillInExtraneousExternal(EX,ox,R); break; case Directions.NORTHWEST: if((EX.y==0)&&(EX.x==0)) tryFillInExtraneousExternal(EX,ox,R); break; case Directions.SOUTHEAST: if((EX.y==yGridSize()-1)&&(EX.x==xGridSize()-1)) tryFillInExtraneousExternal(EX,ox,R); break; } } } catch(final Exception e) { } } synchronized(R.basePhyStats()) { R.basePhyStats().setSensesMask(CMath.unsetb(R.basePhyStats().sensesMask(),PhyStats.SENSE_ROOMGRIDSYNC)); } } public void tryFillInExtraneousExternal(CrossExit EX, Exit ox, Room linkFrom) { if(EX==null) return; Room linkTo=CMLib.map().getRoom(EX.destRoomID); if((linkTo!=null)&&(linkTo.getGridParent()!=null)) linkTo=linkTo.getGridParent(); if((linkTo!=null)&&(linkFrom.rawDoors()[EX.dir]!=linkTo)) { if(ox==null) ox=CMClass.getExit("Open"); linkFrom.rawDoors()[EX.dir]=linkTo; linkFrom.setRawExit(EX.dir,ox); } } protected Room getMakeGridRoom(int x, int y) { if((x<0)||(y<0)||(y>=yGridSize())||(x>=xGridSize())) return null; final Room R=getMakeSingleGridRoom(x,y); if(R==null) return null; fillExitsOfGridRoom(R,x,y); return R; } @Override public Iterator<CrossExit> outerExits() { return gridexits.iterator(); } @Override public void delOuterExit(CrossExit x) { gridexits.remove(x); } @Override public void addOuterExit(CrossExit x) { gridexits.addElement(x); } public Room getAltRoomFrom(Room loc, int direction) { if((loc==null)||(direction<0)) return null; final int opDirection=Directions.getOpDirectionCode(direction); final String roomID=CMLib.map().getExtendedRoomID(loc); for(int d=0;d<gridexits.size();d++) { final CrossExit EX=gridexits.elementAt(d); if((!EX.out) &&(EX.destRoomID.equalsIgnoreCase(roomID)) &&(EX.dir==direction) &&(EX.x>=0)&&(EX.y>=0)&&(EX.x<xGridSize())&&(EX.y<yGridSize())) return getMakeGridRoom(EX.x,EX.y); } final Room oldLoc=loc; if(loc.getGridParent()!=null) loc=loc.getGridParent(); if((oldLoc!=loc)&&(loc instanceof GridLocale)) { final XYVector xy=((GridLocale)loc).getRoomXY(oldLoc); if((xy.x>=0)&&(xy.y>=0)) switch(opDirection) { case Directions.EAST: if((((GridLocale)loc).yGridSize()==yGridSize())) return getMakeGridRoom(xGridSize()-1,xy.y); break; case Directions.WEST: if((((GridLocale)loc).yGridSize()==yGridSize())) return getMakeGridRoom(0,xy.y); break; case Directions.NORTH: if((((GridLocale)loc).xGridSize()==xGridSize())) return getMakeGridRoom(xy.x,0); break; case Directions.NORTHWEST: return getMakeGridRoom(0,0); case Directions.SOUTHEAST: return getMakeGridRoom(xGridSize()-1,yGridSize()-1); case Directions.NORTHEAST: return getMakeGridRoom(xGridSize()-1,0); case Directions.SOUTHWEST: return getMakeGridRoom(0,yGridSize()-1); case Directions.SOUTH: if((((GridLocale)loc).xGridSize()==xGridSize())) return getMakeGridRoom(xy.x,yGridSize()-1); break; } } int x=0; int y=0; switch(opDirection) { case Directions.NORTH: x=xGridSize()/2; break; case Directions.SOUTH: x=xGridSize()/2; y=yGridSize()-1; break; case Directions.EAST: x=xGridSize()-1; y=yGridSize()/2; break; case Directions.WEST: y=yGridSize()/2; break; case Directions.NORTHWEST: x=0; y=0; break; case Directions.NORTHEAST: x=xGridSize()-1; y=0; break; case Directions.SOUTHWEST: x=0; y=yGridSize()-1; break; case Directions.SOUTHEAST: x=xGridSize()-1; y=yGridSize()-1; break; case Directions.UP: case Directions.DOWN: x=xGridSize()/2; y=yGridSize()/2; break; } return getMakeGridRoom(x,y); } @Override public List<Room> getAllRooms() { getRandomGridChild(); return new ConvertingList<ThinGridEntry,Room>(rooms,ThinGridEntryConverter.INSTANCE); } @Override public Iterator<Room> getExistingRooms() { return new ConvertingIterator<ThinGridEntry,Room>(rooms.iterator(),ThinGridEntryConverter.INSTANCE); } protected Room alternativeLink(Room room, Room defaultRoom, int dir) { if(room.getGridParent()==this) for(int d=0;d<gridexits.size();d++) { final CrossExit EX=gridexits.elementAt(d); try { if((EX.out)&&(EX.dir==dir) &&(getGridRoomIfExists(EX.x,EX.y)==room)) { final Room R=CMLib.map().getRoom(EX.destRoomID); if(R!=null) { if(R.getGridParent()!=null) return R.getGridParent(); return R; } } }catch(final Exception e){} } return defaultRoom; } protected void halfLink(Room room, Room loc, int dirCode, Exit o) { if(room==null) return; if(loc==null) return; if(room.rawDoors()[dirCode]!=null) { if(room.rawDoors()[dirCode].getGridParent()==null) return; if(room.rawDoors()[dirCode].getGridParent().isMyGridChild(room.rawDoors()[dirCode])) return; room.rawDoors()[dirCode]=null; } if(o==null) o=CMClass.getExit("Open"); room.rawDoors()[dirCode]=alternativeLink(room,loc,dirCode); room.setRawExit(dirCode,o); } protected void linkRoom(Room room, Room loc, int dirCode, Exit o, Exit ao) { if(loc==null) return; if(room==null) return; final int opCode=Directions.getOpDirectionCode(dirCode); final Room dirR=room.rawDoors()[dirCode]; if(dirR!=null) { if(dirR.getGridParent()==null) return; if(dirR.getGridParent().isMyGridChild(dirR)) return; room.rawDoors()[dirCode]=null; } if(o==null) o=CMClass.getExit("Open"); room.rawDoors()[dirCode]=alternativeLink(room,loc,dirCode); room.setRawExit(dirCode,o); final Room opR=loc.rawDoors()[opCode]; if(opR!=null) { if(opR.getGridParent()==null) return; if(opR.getGridParent().isMyGridChild(opR)) return; loc.rawDoors()[opCode]=null; } loc.rawDoors()[opCode]=alternativeLink(loc,room,opCode); if(ao==null) { if((room.getGridParent()==loc.getGridParent()) &&(loc.rawDoors()[opCode]==room)) ao=o; else ao=CMClass.getExit("Open"); } loc.setRawExit(opCode,ao); } @Override public void buildGrid() { clearGrid(null); } @Override public boolean isMyGridChild(Room loc) { if(loc==null) return false; if(loc.getGridParent()==this) return true; if(loc.getGridParent()!=null) return false; try { for(final ThinGridEntry entry : rooms) { if(loc == entry.room) return true; } }catch(final Exception e){} // optimization return false; } @Override public void clearGrid(Room bringBackHere) { try { final WorldMap mapper=CMLib.map(); for(final ThinGridEntry entry : rooms) mapper.emptyRoom(entry.room,bringBackHere,true); for(final ThinGridEntry entry : rooms) entry.room.destroy(); rooms.clear(); } catch(final Exception e){Log.debugOut("StdThinGrid",e);} } @Override public String getGridChildCode(Room loc) { if(roomID().length()==0) return ""; try { for(final ThinGridEntry entry : rooms) { if(entry.room==loc) return roomID()+"#("+entry.xy.x+","+entry.xy.y+")"; } } catch(final Exception x) { } return ""; } @Override public int getGridChildX(Room loc) { try { for(final ThinGridEntry entry : rooms) if(entry.room==loc) return entry.xy.x; }catch(final Exception x){} return -1; } @Override public Room getRandomGridChild() { final int x=CMLib.dice().roll(1,xGridSize(),-1); final int y=CMLib.dice().roll(1,yGridSize(),-1); final Room R=getMakeGridRoom(x,y); if(R==null) Log.errOut("StdThinGrid",roomID()+" failed to get a random child!"); return R; } @Override public int getGridChildY(Room loc) { try { for(final ThinGridEntry entry : rooms) { if(entry.room==loc) return entry.xy.y; } } catch(final Exception x) { } return -1; } @Override public Room getGridChild(String childCode) { if(childCode.equalsIgnoreCase(roomID())) return this; if(!childCode.toUpperCase().startsWith(roomID().toUpperCase()+"#(")) return null; final int len=roomID().length()+2; final int comma=childCode.indexOf(',',len); if(comma<0) return null; final int x=CMath.s_int(childCode.substring(len,comma)); final int y=CMath.s_int(childCode.substring(comma+1,childCode.length()-1)); return getMakeGridRoom(x,y); } @Override public void executeMsg(final Environmental myHost, final CMMsg msg) { if((msg.targetMinor()==CMMsg.TYP_EXPIRE) &&(msg.target() instanceof Room)) { final Room R=(Room)msg.target(); if(R.getGridParent()==this) { if((roomID().length()>0)&&(getArea()!=null)) getArea().delProperRoomnumber(getGridChildCode(R)); try { for(final ThinGridEntry entry : rooms) { if(entry.room==R) rooms.remove(entry); } for(final ThinGridEntry entry : rooms) { for(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--) { if(entry.room.rawDoors()[d]==R) { entry.room.rawDoors()[d]=null; entry.room.setRawExit(d,null); } } } }catch(final Exception x){} } } super.executeMsg(myHost,msg); } @Override public boolean okMessage(final Environmental myHost, final CMMsg msg) { if(!super.okMessage(myHost,msg)) return false; if(msg.targetMinor()==CMMsg.TYP_ENTER) { if(msg.target()==this) { final MOB mob=msg.source(); if((mob.location()!=null)&&(mob.location().roomID().length()>0)) { int direction=-1; for(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--) { if(mob.location().getRoomInDir(d)==this) direction=d; } if(direction<0) { mob.tell(L("Some great evil is preventing your movement that way.")); return false; } msg.modify(msg.source(), getAltRoomFrom(mob.location(),direction), msg.tool(), msg.sourceCode(), msg.sourceMessage(), msg.targetCode(), msg.targetMessage(), msg.othersCode(), msg.othersMessage()); } } } return true; } private final static String[] MYCODES={"XSIZE","YSIZE"}; @Override public String getStat(String code) { switch(getStdGridCodeNum(code)) { case 0: return Integer.toString(xGridSize()); case 1: return Integer.toString(yGridSize()); default: return super.getStat(code); } } @Override public void setStat(String code, String val) { switch(getStdGridCodeNum(code)) { case 0: setXGridSize(CMath.s_parseIntExpression(val)); break; case 1: setYGridSize(CMath.s_parseIntExpression(val)); break; default: super.setStat(code, val); break; } } protected int getStdGridCodeNum(String code) { for(int i=0;i<MYCODES.length;i++) { if(code.equalsIgnoreCase(MYCODES[i])) return i; } return -1; } private static String[] codes=null; @Override public String[] getStatCodes() { return (codes != null) ? codes : (codes = CMProps.getStatCodesList(CMParms.appendToArray(STDCODES, MYCODES),this)); } }