package com.planet_ink.coffee_mud.Commands; import com.planet_ink.coffee_mud.core.interfaces.*; import com.planet_ink.coffee_mud.core.*; 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.Locales.interfaces.*; import com.planet_ink.coffee_mud.MOBS.interfaces.*; import com.planet_ink.coffee_mud.Races.interfaces.*; import java.util.*; import java.util.regex.*; /* Copyright 2000-2006 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 GModify extends StdCommand { public GModify(){} private String[] access={"GMODIFY"}; public String[] getAccessWords(){return access;} private static final int FLAG_CASESENSITIVE=1; private static final int FLAG_SUBSTRING=2; private static final int FLAG_OR=4; private static final int FLAG_AND=8; public static String getStat(Environmental E, String stat) { if((stat!=null)&&(stat.length()>0)&&(stat.equalsIgnoreCase("REJUV"))) { if(E.baseEnvStats().rejuv()==Integer.MAX_VALUE) return "0"; return ""+E.baseEnvStats().rejuv(); } return E.getStat(stat); } public static void setStat(Environmental E, String stat, String value) { if((stat!=null)&&(stat.length()>0)&&(stat.equalsIgnoreCase("REJUV"))) E.baseEnvStats().setRejuv(CMath.s_int(value)); else E.setStat(stat,value); } public static void gmodifydebugtell(MOB mob, String msg) { if(mob!=null) mob.tell(msg); Log.sysOut("GMODIFY",msg); } private static boolean tryModfy(MOB mob, Room room, Environmental E, DVector changes, DVector onfields, boolean noisy) { boolean didAnything=false; if(noisy) gmodifydebugtell(mob,E.name()+"/"+CMClass.className(E)); String field=null; String value=null; String equator=null; String stat=null; int codes=-1; Pattern pattern=null; boolean checkedOut=true; Matcher M=null; DVector matches=new DVector(3); int lastCode=FLAG_AND; for(int i=0;i<onfields.size();i++) { field=(String)onfields.elementAt(i,1); equator=(String)onfields.elementAt(i,2); value=(String)onfields.elementAt(i,3); codes=((Integer)onfields.elementAt(i,4)).intValue(); pattern=(Pattern)onfields.elementAt(i,5); if(noisy) gmodifydebugtell(mob,field+"/"+getStat(E,field)+"/"+value+"/"+getStat(E,field).equals(value)); int matchStart=-1; int matchEnd=-1; stat=getStat(E,field); if(equator.equals("$")&&(pattern!=null)) { if(!CMath.bset(codes,FLAG_SUBSTRING)) { if(stat.matches(value)) { matchStart=0; matchEnd=stat.length(); } } else { M=pattern.matcher(stat); M.reset(); if(M.find()) { matchStart=M.start(); matchEnd=M.end(); } } } else if(equator.equals("=")) { if(!CMath.bset(codes,FLAG_CASESENSITIVE)) { stat=stat.toLowerCase(); value=value.toLowerCase(); } if(CMath.bset(codes,FLAG_SUBSTRING)) { matchStart=stat.indexOf(value); matchEnd=matchStart+value.length(); } else if(stat.equals(value)) { matchStart=0; matchEnd=stat.length(); } } else if(equator.equals("!=")) { if(!CMath.bset(codes,FLAG_CASESENSITIVE)) { stat=stat.toLowerCase(); value=value.toLowerCase(); } if(CMath.bset(codes,FLAG_SUBSTRING)) { if(stat.indexOf(value)<0) { matchStart=0; matchEnd=stat.length(); } } else if(!stat.equals(value)) { matchStart=0; matchEnd=stat.length(); } } else if(equator.equals(">")) { if(!CMath.bset(codes,FLAG_CASESENSITIVE)) { stat=stat.toLowerCase(); value=value.toLowerCase(); } if(CMath.isNumber(stat)&&CMath.isNumber(value)) matchStart=(CMath.s_long(stat)>CMath.s_long(value))?0:-1; else matchStart=(stat.compareTo(value)>0)?0:-1; } else if(equator.equals("<")) { if(!CMath.bset(codes,FLAG_CASESENSITIVE)) { stat=stat.toLowerCase(); value=value.toLowerCase(); } if(CMath.isNumber(stat)&&CMath.isNumber(value)) matchStart=(CMath.s_long(stat)<CMath.s_long(value))?0:-1; else matchStart=(stat.compareTo(value)<0)?0:-1; } else if(equator.equals("<=")) { if(!CMath.bset(codes,FLAG_CASESENSITIVE)) { stat=stat.toLowerCase(); value=value.toLowerCase(); } if(CMath.isNumber(stat)&&CMath.isNumber(value)) matchStart=(CMath.s_long(stat)<=CMath.s_long(value))?0:-1; else matchStart=(stat.compareTo(value)<=0)?0:-1; } else if(equator.equals(">=")) { if(!CMath.bset(codes,FLAG_CASESENSITIVE)) { stat=stat.toLowerCase(); value=value.toLowerCase(); } if(CMath.isNumber(stat)&&CMath.isNumber(value)) matchStart=(CMath.s_long(stat)>=CMath.s_long(value))?0:-1; else matchStart=(stat.compareTo(value)>=0)?0:-1; } if(matchStart>=0) matches.addElement(field,new Integer(matchStart),new Integer(matchEnd)); if(CMath.bset(lastCode,FLAG_AND)) checkedOut=checkedOut&&(matchStart>=0); else if(CMath.bset(lastCode,FLAG_OR)) checkedOut=checkedOut||(matchStart>=0); else checkedOut=(matchStart>=0); lastCode=codes; } if(checkedOut) { if(changes.size()==0) mob.tell("Matched on "+E.name()+" from "+CMLib.map().getExtendedRoomID(room)+"."); else for(int i=0;i<changes.size();i++) { field=(String)changes.elementAt(i,1); value=(String)changes.elementAt(i,3); codes=((Integer)changes.elementAt(i,4)).intValue(); if(noisy) gmodifydebugtell(mob,E.name()+" wants to change "+field+" value "+getStat(E,field)+" to "+value+"/"+(!getStat(E,field).equals(value))); if(CMath.bset(codes,FLAG_SUBSTRING)) { int matchStart=-1; int matchEnd=-1; for(int m=0;m<matches.size();m++) if(((String)matches.elementAt(m,1)).equals(field)) { matchStart=((Integer)matches.elementAt(m,2)).intValue(); matchEnd=((Integer)matches.elementAt(m,3)).intValue(); } if(matchStart>=0) { stat=getStat(E,field); value=stat.substring(0,matchStart)+value+stat.substring(matchEnd); } } if(!getStat(E,field).equals(value)) { Log.sysOut("GMODIFY","The "+CMStrings.capitalizeAndLower(field)+" field on "+E.Name()+" in "+room.roomID()+" was changed from "+getStat(E,field)+" to "+value+"."); setStat(E,field,value); didAnything=true; } } } if(didAnything) { E.recoverEnvStats(); if(E instanceof MOB) { ((MOB)E).recoverCharStats(); ((MOB)E).recoverMaxState(); } E.text(); } return didAnything; } public void sortEnumeratedList(Enumeration e, Vector allKnownFields, StringBuffer allFieldsMsg) { for(;e.hasMoreElements();) { Environmental E=(Environmental)e.nextElement(); String[] fields=E.getStatCodes(); for(int x=0;x<fields.length;x++) if(!allKnownFields.contains(fields[x])) { allKnownFields.addElement(fields[x]); allFieldsMsg.append(fields[x]+" "); } } } public boolean execute(MOB mob, Vector commands) throws java.io.IOException { boolean noisy=CMSecurity.isDebugging("GMODIFY"); Vector placesToDo=new Vector(); String whole=CMParms.combine(commands,0); commands.removeElementAt(0); if(commands.size()==0) { mob.tell("GModify what?"); return false; } if(mob.isMonster()) { mob.tell("No can do."); return false; } if((commands.size()>0)&& ((String)commands.elementAt(0)).equalsIgnoreCase("?")) { StringBuffer allFieldsMsg=new StringBuffer(""); Vector allKnownFields=new Vector(); sortEnumeratedList(CMClass.mobTypes(),allKnownFields,allFieldsMsg); sortEnumeratedList(CMClass.basicItems(),allKnownFields,allFieldsMsg); sortEnumeratedList(CMClass.weapons(),allKnownFields,allFieldsMsg); sortEnumeratedList(CMClass.armor(),allKnownFields,allFieldsMsg); sortEnumeratedList(CMClass.clanItems(),allKnownFields,allFieldsMsg); sortEnumeratedList(CMClass.miscMagic(),allKnownFields,allFieldsMsg); sortEnumeratedList(CMClass.miscTech(),allKnownFields,allFieldsMsg); mob.tell("Valid field names are "+allFieldsMsg.toString()); return false; } if((commands.size()>0)&& ((String)commands.elementAt(0)).equalsIgnoreCase("room")) { if(!CMSecurity.isAllowed(mob,mob.location(),"GMODIFY")) { mob.tell("You are not allowed to do that here."); return false; } commands.removeElementAt(0); placesToDo.addElement(mob.location()); } if((commands.size()>0)&& ((String)commands.elementAt(0)).equalsIgnoreCase("area")) { if(!CMSecurity.isAllowed(mob,mob.location(),"GMODIFY")) { mob.tell("You are not allowed to do that here."); return false; } commands.removeElementAt(0); placesToDo.addElement(mob.location().getArea()); } if((commands.size()>0)&& ((String)commands.elementAt(0)).equalsIgnoreCase("world")) { if(!CMSecurity.isAllowedEverywhere(mob,"GMODIFY")) { mob.tell("You are not allowed to do that."); return false; } commands.removeElementAt(0); placesToDo=new Vector(); } DVector changes=new DVector(5); DVector onfields=new DVector(5); DVector use=null; Vector allKnownFields=new Vector(); StringBuffer allFieldsMsg=new StringBuffer(""); sortEnumeratedList(CMClass.mobTypes(),allKnownFields,allFieldsMsg); sortEnumeratedList(CMClass.basicItems(),allKnownFields,allFieldsMsg); sortEnumeratedList(CMClass.weapons(),allKnownFields,allFieldsMsg); sortEnumeratedList(CMClass.armor(),allKnownFields,allFieldsMsg); sortEnumeratedList(CMClass.clanItems(),allKnownFields,allFieldsMsg); sortEnumeratedList(CMClass.miscMagic(),allKnownFields,allFieldsMsg); sortEnumeratedList(CMClass.miscTech(),allKnownFields,allFieldsMsg); allKnownFields.addElement("REJUV"); allFieldsMsg.append("REJUV "); use=onfields; Vector newSet=new Vector(); StringBuffer s=new StringBuffer(""); for(int i=0;i<commands.size();i++) { String str=((String)commands.elementAt(i)); if((str.toUpperCase().startsWith("CHANGE=")) ||(str.toUpperCase().startsWith("WHEN="))) { if(s.length()>0) newSet.addElement(s.toString()); s=new StringBuffer(""); } if(str.indexOf(" ")>=0) str="\""+str+"\""; if(s.length()>0) s.append(" "+str); else s.append(str); } if(s.length()>0) newSet.addElement(s.toString()); for(int i=0;i<newSet.size();i++) { String str=((String)newSet.elementAt(i)); if(str.toUpperCase().startsWith("CHANGE=")) { use=changes; str=str.substring(7).trim(); } if(str.toUpperCase().startsWith("WHEN=")) { str=str.substring(5).trim(); use=onfields; } while(str.trim().length()>0) { int eq=-1; int divLen=0; Integer code=new Integer(0); while((divLen==0)&&((++eq)<str.length())) switch(str.charAt(eq)) { case '!': if((eq<(str.length()-1))&&(str.charAt(eq+1)=='=')) { divLen=2; break; } break; case '=': case '$': divLen=1; break; case '<': case '>': divLen=1; if((eq<(str.length()-1))&&(str.charAt(eq+1)=='=')) { divLen=2; break; } break; } if(divLen==0) { mob.tell("String '"+str+"' does not contain an equation divider. Even CHANGE needs at least an = sign!"); return false; } String equator=str.substring(eq,eq+divLen); String val=str.substring(eq+divLen); String key=str.substring(0,eq).trim(); int divBackLen=0; eq=-1; while((divBackLen==0)&&((++eq)<val.length())) switch(val.charAt(eq)) { case '&': if((eq<(val.length()-1))&&(val.charAt(eq+1)=='&')) { divBackLen=2; break; } break; case '|': if((eq<(val.length()-1))&&(val.charAt(eq+1)=='&')) { divBackLen=2; break; } break; } if(divBackLen==0) str=""; else { String attach=val.substring(eq,eq+divBackLen).trim(); if(attach.equals("&&")) code=new Integer(code.intValue()|FLAG_AND); else if(attach.equals("||")) code=new Integer(code.intValue()|FLAG_OR); str=val.substring(eq+divBackLen); val=val.substring(0,eq); } Pattern P=null; if(use==null) { mob.tell("'"+((String)commands.elementAt(i))+"' goes to an unknown parameter!"); return false; } while(val.trim().startsWith("[")) { int x2=val.indexOf("]"); if(x2<0) break; String cd=val.trim().substring(1,x2); if(cd.length()!=2) break; if(cd.equalsIgnoreCase("ss")) code=new Integer(code.intValue()|FLAG_SUBSTRING); if(cd.equalsIgnoreCase("cs")) code=new Integer(code.intValue()|FLAG_CASESENSITIVE); val=val.substring(x2+1); } if(equator.equals("$")) { int patCodes=Pattern.DOTALL; if(!CMath.bset(code.intValue(),FLAG_CASESENSITIVE)) patCodes=patCodes|Pattern.CASE_INSENSITIVE; P=Pattern.compile(val,patCodes); } key=key.toUpperCase().trim(); if(allKnownFields.contains(key)) use.addElement(key,equator,val,code,P); else { mob.tell("'"+key+"' is an unknown field name. Valid fields include: "+allFieldsMsg.toString()); return false; } } } if((onfields.size()==0)&&(changes.size()==0)) { mob.tell("You must specify either WHEN, or CHANGES parameters for valid matches to be made."); return false; } if(placesToDo.size()==0) for(Enumeration a=CMLib.map().areas();a.hasMoreElements();) { Area A=(Area)a.nextElement(); if(A.getCompleteMap().hasMoreElements() &&CMSecurity.isAllowed(mob,((Room)A.getCompleteMap().nextElement()),"GMODIFY")) placesToDo.addElement(A); } if(placesToDo.size()==0) { mob.tell("There are no rooms with data to gmodify!"); return false; } for(int i=placesToDo.size()-1;i>=0;i--) { if(placesToDo.elementAt(i) instanceof Area) { Area A=(Area)placesToDo.elementAt(i); placesToDo.removeElement(A); for(Enumeration r=A.getCompleteMap();r.hasMoreElements();) { Room R=(Room)r.nextElement(); if(CMSecurity.isAllowed(mob,R,"GMODIFY")) placesToDo.addElement(R); } } else if(placesToDo.elementAt(i) instanceof Room) if(mob.session()!=null) mob.session().rawPrint("."); else return false; } // now do the modification... if(mob.session()!=null) { if(changes.size()==0) mob.session().rawPrintln("Searching..."); else mob.session().rawPrint("Searching, modifying and saving..."); } if(noisy) gmodifydebugtell(mob,"Rooms to do: "+placesToDo.size()); if(noisy) gmodifydebugtell(mob,"When fields="+CMParms.toStringList(onfields.getDimensionVector(1))); if(noisy) gmodifydebugtell(mob,"Change fields="+CMParms.toStringList(changes.getDimensionVector(1))); Log.sysOut("GModify",mob.Name()+" "+whole+"."); for(int r=0;r<placesToDo.size();r++) { Room R=(Room)placesToDo.elementAt(r); if(!CMSecurity.isAllowed(mob,R,"GMODIFY")) continue; if((R==null)||(R.roomID()==null)||(R.roomID().length()==0)) continue; synchronized(("SYNC"+R.roomID()).intern()) { R=CMLib.map().getRoom(R); boolean oldMobility=R.getArea().getMobility(); if(changes.size()==0) { R=CMLib.coffeeMaker().makeNewRoomContent(R); if(R!=null) R.getArea().toggleMobility(false); } else { R.getArea().toggleMobility(false); CMLib.map().resetRoom(R); } if(R==null) continue; boolean savemobs=false; boolean saveitems=false; for(int i=0;i<R.numItems();i++) { Item I=R.fetchItem(i); if((I!=null)&&(tryModfy(mob,R,I,changes,onfields,noisy))) saveitems=true; } for(int m=0;m<R.numInhabitants();m++) { MOB M=R.fetchInhabitant(m); if((M!=null)&&(M.savable())) if(tryModfy(mob,R,M,changes,onfields,noisy)) savemobs=true; for(int i=0;i<M.inventorySize();i++) { Item I=M.fetchInventory(i); if((I!=null)&&(tryModfy(mob,R,I,changes,onfields,noisy))) savemobs=true; } if(CMLib.coffeeShops().getShopKeeper(M)!=null) { Vector V=CMLib.coffeeShops().getShopKeeper(M).getShop().getStoreInventory(); for(int i=0;i<V.size();i++) { if(V.elementAt(i) instanceof Item) { Item I=(Item)V.elementAt(i); if((I!=null)&&(tryModfy(mob,R,I,changes,onfields,noisy))) savemobs=true; } } } } if(saveitems) CMLib.database().DBUpdateItems(R); if(savemobs) CMLib.database().DBUpdateMOBs(R); if((mob.session()!=null)&&(changes.size()>0)) mob.session().rawPrint("."); R.getArea().toggleMobility(oldMobility); if(changes.size()==0) R.destroy(); } } if(mob.session()!=null) mob.session().rawPrintln("!\n\rDone!"); for(int i=0;i<placesToDo.size();i++) ((Room)placesToDo.elementAt(i)).getArea().toggleMobility(true); return false; } public boolean canBeOrdered(){return true;} public boolean securityCheck(MOB mob){return CMSecurity.isAllowedAnywhere(mob,"GMODIFY");} }