package com.planet_ink.coffee_mud.core.database; import com.planet_ink.coffee_mud.core.interfaces.*; import com.planet_ink.coffee_mud.core.*; import com.planet_ink.coffee_mud.core.CMSecurity.SecFlag; import com.planet_ink.coffee_mud.core.CMSecurity.SecGroup; import com.planet_ink.coffee_mud.core.collections.*; import com.planet_ink.coffee_mud.core.database.DBConnector.DBPreparedBatchEntry; 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.Common.interfaces.Clan.MemberRecord; import com.planet_ink.coffee_mud.Exits.interfaces.*; import com.planet_ink.coffee_mud.Items.interfaces.*; import com.planet_ink.coffee_mud.Libraries.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.sql.*; import java.util.*; import java.util.Map.Entry; /* * Copyright 2000-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 MOBloader { protected DBConnector DB=null; public MOBloader(DBConnector newDB) { DB=newDB; } protected Room emptyRoom=null; public MOB DBReadUserOnly(final String name, final String[] locationID) { if((name==null)||(name.length()==0)) return null; DBConnection D=null; MOB mob=null; int oldDisposition=0; try { D=DB.DBFetch(); ResultSet R=D.query("SELECT * FROM CMCHAR WHERE CMUSERID='"+name+"'"); if(R.next()) { mob=CMClass.getMOB(DBConnections.getRes(R,"CMCHID")); if(mob == null) { mob=CMClass.getMOB("StdMOB"); if(mob == null) return null; } oldDisposition=mob.basePhyStats().disposition(); mob.basePhyStats().setDisposition(PhyStats.IS_NOT_SEEN|PhyStats.IS_SNEAKING); mob.phyStats().setDisposition(PhyStats.IS_NOT_SEEN|PhyStats.IS_SNEAKING); final CharStats stats=mob.baseCharStats(); final CharState state=mob.baseState(); final PlayerStats pstats=(PlayerStats)CMClass.getCommon("DefaultPlayerStats"); mob.setPlayerStats(pstats); final String username=DBConnections.getRes(R,"CMUSERID"); final String password=DBConnections.getRes(R,"CMPASS"); mob.setName(username); pstats.setPassword(password); stats.setMyClasses(DBConnections.getRes(R,"CMCLAS")); stats.setStat(CharStats.STAT_STRENGTH,CMath.s_int(DBConnections.getRes(R,"CMSTRE"))); stats.setMyRace(CMClass.getRace(DBConnections.getRes(R,"CMRACE"))); stats.setStat(CharStats.STAT_DEXTERITY,CMath.s_int(DBConnections.getRes(R,"CMDEXT"))); stats.setStat(CharStats.STAT_CONSTITUTION,CMath.s_int(DBConnections.getRes(R,"CMCONS"))); stats.setStat(CharStats.STAT_GENDER,DBConnections.getRes(R,"CMGEND").charAt(0)); stats.setStat(CharStats.STAT_WISDOM,CMath.s_int(DBConnections.getRes(R,"CMWISD"))); stats.setStat(CharStats.STAT_INTELLIGENCE,CMath.s_int(DBConnections.getRes(R,"CMINTE"))); stats.setStat(CharStats.STAT_CHARISMA,CMath.s_int(DBConnections.getRes(R,"CMCHAR"))); state.setHitPoints(CMath.s_int(DBConnections.getRes(R,"CMHITP"))); stats.setMyLevels(DBConnections.getRes(R,"CMLEVL")); int level=0; for(int i=0;i<mob.baseCharStats().numClasses();i++) level+=stats.getClassLevel(mob.baseCharStats().getMyClass(i)); mob.basePhyStats().setLevel(level); state.setMana(CMath.s_int(DBConnections.getRes(R,"CMMANA"))); state.setMovement(CMath.s_int(DBConnections.getRes(R,"CMMOVE"))); mob.setDescription(DBConnections.getRes(R,"CMDESC")); final int align=(CMath.s_int(DBConnections.getRes(R,"CMALIG"))); if((CMLib.factions().getFaction(CMLib.factions().AlignID())!=null)&&(align>=0)) CMLib.factions().setAlignmentOldRange(mob,align); mob.setExperience(CMath.s_int(DBConnections.getRes(R,"CMEXPE"))); //mob.setExpNextLevel(CMath.s_int(DBConnections.getRes(R,"CMEXLV"))); mob.setWorshipCharID(DBConnections.getRes(R,"CMWORS")); mob.setPractices(CMath.s_int(DBConnections.getRes(R,"CMPRAC"))); mob.setTrains(CMath.s_int(DBConnections.getRes(R,"CMTRAI"))); mob.setAgeMinutes(CMath.s_long(DBConnections.getRes(R,"CMAGEH"))); mob.setMoney(CMath.s_int(DBConnections.getRes(R,"CMGOLD"))); mob.setWimpHitPoint(CMath.s_int(DBConnections.getRes(R,"CMWIMP"))); mob.setQuestPoint(CMath.s_int(DBConnections.getRes(R,"CMQUES"))); String roomID=DBConnections.getRes(R,"CMROID"); if(roomID==null) roomID=""; final int x=roomID.indexOf("||"); if(x>=0) { locationID[0]=roomID.substring(x+2); mob.setLocation(CMLib.map().getRoom(locationID[0])); roomID=roomID.substring(0,x); } mob.setStartRoom(CMLib.map().getRoom(roomID)); pstats.setLastDateTime(CMath.s_long(DBConnections.getRes(R,"CMDATE"))); pstats.setChannelMask((int)DBConnections.getLongRes(R,"CMCHAN")); mob.basePhyStats().setAttackAdjustment(CMath.s_int(DBConnections.getRes(R,"CMATTA"))); mob.basePhyStats().setArmor(CMath.s_int(DBConnections.getRes(R,"CMAMOR"))); mob.basePhyStats().setDamage(CMath.s_int(DBConnections.getRes(R,"CMDAMG"))); mob.setAttributesBitmap(CMath.s_int(DBConnections.getRes(R,"CMBTMP"))); mob.setLiegeID(DBConnections.getRes(R,"CMLEIG")); mob.basePhyStats().setHeight((int)DBConnections.getLongRes(R,"CMHEIT")); mob.basePhyStats().setWeight((int)DBConnections.getLongRes(R,"CMWEIT")); pstats.setPrompt(DBConnections.getRes(R,"CMPRPT")); final String colorStr=DBConnections.getRes(R,"CMCOLR"); if((colorStr!=null)&&(colorStr.length()>0)&&(!colorStr.equalsIgnoreCase("NULL"))) pstats.setColorStr(colorStr); pstats.setLastIP(DBConnections.getRes(R,"CMLSIP")); mob.setClan("", Integer.MIN_VALUE); // delete all sequence pstats.setEmail(DBConnections.getRes(R,"CMEMAL")); final String buf=DBConnections.getRes(R,"CMPFIL"); pstats.setXML(buf); stats.setNonBaseStatsFromString(DBConnections.getRes(R,"CMSAVE")); List<String> V9=CMParms.parseSemicolons(CMLib.xml().returnXMLValue(buf,"TATTS"),true); for(final Enumeration<Tattoo> e=mob.tattoos();e.hasMoreElements();) mob.delTattoo(e.nextElement()); for(int v=0;v<V9.size();v++) mob.addTattoo(parseTattoo(V9.get(v))); V9=CMParms.parseSemicolons(CMLib.xml().returnXMLValue(buf,"EDUS"),true); mob.delAllExpertises(); for(int v=0;v<V9.size();v++) mob.addExpertise(V9.get(v)); // check for a non-existant birthday and fix it if(pstats.getBirthday()==null) stats.setStat(CharStats.STAT_AGE, pstats.initializeBirthday(CMLib.time().localClock(mob.getStartRoom()),(int)Math.round(CMath.div(mob.getAgeMinutes(),60.0)),stats.getMyRace())); final TimeClock C=CMLib.time().localClock(mob.getStartRoom()); // check for a messed up/reset birthday and fix it if((pstats.getBirthday()[PlayerStats.BIRTHDEX_YEAR]==1) ||(pstats.getBirthday()[PlayerStats.BIRTHDEX_YEAR]>C.getYear())) { final int age = mob.baseCharStats().getStat(CharStats.STAT_AGE); if((pstats.getBirthday()[PlayerStats.BIRTHDEX_MONTH]==1) &&(pstats.getBirthday()[PlayerStats.BIRTHDEX_DAY]==1)) { if((age > 1)&&(C.getYear() > age)) pstats.initializeBirthday(C,(int)Math.round(CMath.div(mob.getAgeMinutes(),60.0)),stats.getMyRace()); Log.warnOut("MOBloader","Reset the birthday of player '"+mob.Name()+"' (Might have been holdover from being first-year player)"); } if((age > 1)&&(C.getYear() > age)) { pstats.getBirthday()[PlayerStats.BIRTHDEX_YEAR]=C.getYear()-age; pstats.getBirthday()[PlayerStats.BIRTHDEX_LASTYEARCELEBRATED]=C.getYear(); } } mob.setImage(CMLib.xml().returnXMLValue(buf,"IMG")); final List<XMLLibrary.XMLTag> CleanXML=CMLib.xml().parseAllXML(DBConnections.getRes(R,"CMMXML")); R.close(); if(pstats.getSavedPose().length()>0) mob.setDisplayText(pstats.getSavedPose()); CMLib.coffeeMaker().setFactionFromXML(mob,CleanXML); if((CMProps.isUsingAccountSystem())&&(pstats.getAccount()==null)) { // yes, this can happen when you wiggle in and out of the account system. for(final Enumeration<PlayerAccount> a = CMLib.players().accounts(); a.hasMoreElements();) { final PlayerAccount pA=a.nextElement(); if(pA.findPlayer(mob.Name())!=null) { pstats.setAccount(pA); break; } } } CMLib.achievements().loadPlayerSkillAwards(mob, pstats); } R.close(); R=D.query("SELECT * FROM CMCHCL WHERE CMUSERID='"+name+"'"); while(R.next() && (mob!=null)) { final String clanID=DBConnections.getRes(R,"CMCLAN"); final int clanRole = this.BuildClanMemberRole(R); final Clan C=CMLib.clans().getClan(clanID); if(C!=null) mob.setClan(C.clanID(), clanRole); } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } if(mob != null) { mob.basePhyStats().setDisposition(oldDisposition); mob.recoverPhyStats(); } return mob; } public MOB DBRead(final String name) { if((name==null)||(name.length()==0)) return null; if(emptyRoom==null) emptyRoom=CMClass.getLocale("StdRoom"); final String[] oldLocID=new String[1]; if(CMLib.players().getPlayer(name)!=null) return CMLib.players().getPlayer(name); final MOB mob=DBReadUserOnly(name,oldLocID); if(mob == null) return null; final int oldDisposition=mob.basePhyStats().disposition(); mob.basePhyStats().setDisposition(PhyStats.IS_NOT_SEEN|PhyStats.IS_SNEAKING); mob.phyStats().setDisposition(PhyStats.IS_NOT_SEEN|PhyStats.IS_SNEAKING); CMLib.players().addPlayer(mob); mob.recoverPhyStats(); mob.recoverCharStats(); Room oldLoc=mob.location(); boolean inhab=false; if(oldLoc!=null) inhab=oldLoc.isInhabitant(mob); mob.setLocation(emptyRoom); DBConnection D=null; // now grab the items try { D=DB.DBFetch(); final ResultSet R=D.query("SELECT * FROM CMCHIT WHERE CMUSERID='"+mob.Name()+"'"); final Hashtable<String,Item> itemNums=new Hashtable<String,Item>(); final Hashtable<Item,String> itemLocs=new Hashtable<Item,String>(); while(R.next()) { final String itemNum=DBConnections.getRes(R,"CMITNM"); final String itemID=DBConnections.getRes(R,"CMITID"); final Item newItem=CMClass.getItem(itemID); if(newItem==null) Log.errOut("MOB","Couldn't find item '"+itemID+"'"); else { itemNums.put(itemNum,newItem); boolean addToMOB=true; String text=DBConnections.getResQuietly(R,"CMITTX"); int roomX; if(text.startsWith("<ROOM") && ((roomX=text.indexOf("/>"))>=0)) { final String roomXML=text.substring(0,roomX+2); text=text.substring(roomX+2); newItem.setMiscText(text); final List<XMLLibrary.XMLTag> xml=CMLib.xml().parseAllXML(roomXML); if((xml!=null)&&(xml.size()>0)) { final String roomID=xml.get(0).parms().get("ID"); final long expirationDate=CMath.s_long(xml.get(0).parms().get("EXPIRE")); if(roomID.startsWith("SPACE.") && (newItem instanceof SpaceObject)) { CMLib.map().addObjectToSpace((SpaceObject)newItem,CMParms.toLongArray(CMParms.parseCommas(roomID.substring(6), true))); addToMOB=false; } else { final Room itemR=CMLib.map().getRoom(roomID); if(itemR!=null) { if(newItem instanceof BoardableShip) ((BoardableShip)newItem).dockHere(itemR); else itemR.addItem(newItem); newItem.setExpirationDate(expirationDate); addToMOB=false; } } } } else { newItem.setMiscText(text); } if((oldLoc==null) &&(newItem instanceof BoardableShip)) { final Area area=((BoardableShip)newItem).getShipArea(); if(area != null) oldLoc=area.getRoom(oldLocID[0]); } final String loc=DBConnections.getResQuietly(R,"CMITLO"); if(loc.length()>0) { final Item container=itemNums.get(loc); if(container instanceof Container) newItem.setContainer((Container)container); else itemLocs.put(newItem,loc); } newItem.wearAt((int)DBConnections.getLongRes(R,"CMITWO")); newItem.setUsesRemaining((int)DBConnections.getLongRes(R,"CMITUR")); newItem.basePhyStats().setLevel((int)DBConnections.getLongRes(R,"CMITLV")); newItem.basePhyStats().setAbility((int)DBConnections.getLongRes(R,"CMITAB")); newItem.basePhyStats().setHeight((int)DBConnections.getLongRes(R,"CMHEIT")); newItem.recoverPhyStats(); if(addToMOB) mob.addItem(newItem); else { CMLib.map().registerWorldObjectLoaded(null, null, newItem); mob.playerStats().getExtItems().addItem(newItem); } } } for(final Enumeration<Item> e=itemLocs.keys();e.hasMoreElements();) { final Item keyItem=e.nextElement(); final String location=itemLocs.get(keyItem); final Item container=itemNums.get(location); if(container instanceof Container) { keyItem.setContainer((Container)container); keyItem.recoverPhyStats(); container.recoverPhyStats(); } } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } D=null; if(oldLoc!=null) { mob.setLocation(oldLoc); if(inhab&&(!oldLoc.isInhabitant(mob))) oldLoc.addInhabitant(mob); } // now grab the abilities try { D=DB.DBFetch(); final ResultSet R=D.query("SELECT * FROM CMCHAB WHERE CMUSERID='"+mob.Name()+"'"); while(R.next()) { final String abilityID=DBConnections.getRes(R,"CMABID"); int proficiency=(int)DBConnections.getLongRes(R,"CMABPF"); if((proficiency==Integer.MIN_VALUE)||(proficiency==Integer.MIN_VALUE+1)) { if(abilityID.equalsIgnoreCase("ScriptingEngine")) { if(CMClass.getCommon("DefaultScriptingEngine")==null) Log.errOut("MOB","Couldn't find scripting engine!"); else { final String xml=DBConnections.getRes(R,"CMABTX"); if(xml.length()>0) CMLib.coffeeMaker().setGenScripts(mob,CMLib.xml().parseAllXML(xml),true); } } else { final Behavior newBehavior=CMClass.getBehavior(abilityID); if(newBehavior==null) Log.errOut("MOB","Couldn't find behavior '"+abilityID+"'"); else { newBehavior.setParms(DBConnections.getRes(R,"CMABTX")); mob.addBehavior(newBehavior); } } } else { final Ability newAbility=CMClass.getAbility(abilityID); if(newAbility==null) Log.errOut("MOB","Couldn't find ability '"+abilityID+"'"); else { if((proficiency<0)||(proficiency==Integer.MAX_VALUE)) { if(proficiency==Integer.MAX_VALUE) { newAbility.setProficiency(CMLib.ableMapper().getMaxProficiency(newAbility.ID())); mob.addNonUninvokableEffect(newAbility); newAbility.setMiscText(DBConnections.getRes(R,"CMABTX")); }else { proficiency=proficiency+200; newAbility.setProficiency(proficiency); newAbility.setMiscText(DBConnections.getRes(R,"CMABTX")); final Ability newAbility2=(Ability)newAbility.copyOf(); mob.addNonUninvokableEffect(newAbility); mob.addAbility(newAbility2); } }else { newAbility.setProficiency(proficiency); newAbility.setMiscText(DBConnections.getRes(R,"CMABTX")); mob.addAbility(newAbility); } } } } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } D=null; mob.basePhyStats().setDisposition(oldDisposition); mob.recoverPhyStats(); if(mob.baseCharStats()!=null) { mob.baseCharStats().getCurrentClass().startCharacter(mob,false,true); final int oldWeight=mob.basePhyStats().weight(); final int oldHeight=mob.basePhyStats().height(); mob.baseCharStats().getMyRace().startRacing(mob,true); if(oldWeight>0) mob.basePhyStats().setWeight(oldWeight); if(oldHeight>0) mob.basePhyStats().setHeight(oldHeight); } mob.recoverCharStats(); mob.recoverPhyStats(); mob.recoverMaxState(); mob.resetToMaxState(); CMLib.threads().suspendResumeRecurse(mob, false, true); return mob; } public List<String> getUserList() { DBConnection D=null; final Vector<String> V=new Vector<String>(); try { D=DB.DBFetch(); final ResultSet R=D.query("SELECT * FROM CMCHAR"); if(R!=null) while(R.next()) { final String username=DBConnections.getRes(R,"CMUSERID"); V.addElement(username); } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } return V; } protected PlayerLibrary.ThinPlayer parseThinUser(ResultSet R) { try { final String name=DBConnections.getRes(R,"CMUSERID"); String cclass=DBConnections.getRes(R,"CMCLAS"); final int x=cclass.lastIndexOf(';'); CharClass C=null; if((x>0)&&(x<cclass.length()-2)) { C=CMClass.getCharClass(cclass.substring(x+1)); if(C!=null) cclass=C.name(); } final String charClass=(cclass); final String rrace=DBConnections.getRes(R,"CMRACE"); final Race R2=CMClass.getRace(rrace); final String race; if(R2!=null) race=(R2.name()); else race=rrace; final List<String> lvls=CMParms.parseSemicolons(DBConnections.getRes(R,"CMLEVL"), true); int calcLevel=0; for(final String lvl : lvls) calcLevel+=CMath.s_int(lvl); final int level = calcLevel; final int age=(int)DBConnections.getLongRes(R,"CMAGEH"); final MOB M=CMLib.players().getPlayer(name); final long last; if((M!=null)&&(M.lastTickedDateTime()>0)) last=M.lastTickedDateTime(); else last=DBConnections.getLongRes(R,"CMDATE"); final String lsIP=DBConnections.getRes(R,"CMLSIP"); final String email=DBConnections.getRes(R,"CMEMAL"); final String ip=lsIP; final int exp=CMath.s_int(DBConnections.getRes(R,"CMEXPE")); final int expLvl=CMath.s_int(DBConnections.getRes(R,"CMEXLV")); return new PlayerLibrary.ThinPlayer() { @Override public String name() { return name; } @Override public String charClass() { return charClass; } @Override public String race() { return race; } @Override public int level() { return level; } @Override public int age() { return age; } @Override public long last() { return last; } @Override public String email() { return email; } @Override public String ip() { return ip; } @Override public int exp() { return exp; } @Override public int expLvl() { return expLvl; } }; }catch(final Exception e) { Log.errOut("MOBloader",e); } return null; } public PlayerLibrary.ThinPlayer getThinUser(String name) { DBConnection D=null; PlayerLibrary.ThinPlayer thisUser=null; try { D=DB.DBFetch(); final ResultSet R=D.query("SELECT * FROM CMCHAR WHERE CMUSERID='"+name+"'"); if(R!=null) while(R.next()) thisUser=parseThinUser(R); } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } return thisUser; } public List<PlayerLibrary.ThinPlayer> getExtendedUserList() { DBConnection D=null; final Vector<PlayerLibrary.ThinPlayer> allUsers=new Vector<PlayerLibrary.ThinPlayer>(); try { D=DB.DBFetch(); final ResultSet R=D.query("SELECT * FROM CMCHAR"); if(R!=null) while(R.next()) { final PlayerLibrary.ThinPlayer thisUser=parseThinUser(R); if(thisUser != null) allUsers.addElement(thisUser); } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } return allUsers; } public Tattoo parseTattoo(String tattoo) { if(tattoo==null) return (Tattoo)CMClass.getCommon("DefaultTattoo"); int tickDown = 0; if((tattoo.length()>0) &&(Character.isDigit(tattoo.charAt(0)))) { final int x=tattoo.indexOf(' '); if((x>0) &&(CMath.isNumber(tattoo.substring(0,x).trim()))) { tickDown=CMath.s_int(tattoo.substring(0,x)); tattoo=tattoo.substring(x+1).trim(); } } final Tattoo T=(Tattoo)CMClass.getCommon("DefaultTattoo"); return T.set(tattoo, tickDown); } public List<PlayerLibrary.ThinPlayer> vassals(MOB mob, String liegeID) { DBConnection D=null; List<PlayerLibrary.ThinPlayer> list=new ArrayList<PlayerLibrary.ThinPlayer>(); try { D=DB.DBFetch(); final ResultSet R=D.query("SELECT * FROM CMCHAR WHERE CMLEIG='"+liegeID+"'"); if(R!=null) while(R.next()) list.add(this.parseThinUser(R)); } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } return list; } public List<PlayerLibrary.ThinPlayer> worshippers(String deityID) { DBConnection D=null; final List<PlayerLibrary.ThinPlayer> DV=new Vector<PlayerLibrary.ThinPlayer>(); try { D=DB.DBFetch(); final ResultSet R=D.query("SELECT * FROM CMCHAR WHERE CMWORS='"+deityID+"'"); if(R!=null) while(R.next()) { DV.add(parseThinUser(R)); } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } return DV; } public List<MOB> DBScanFollowers(MOB mob) { DBConnection D=null; final Vector<MOB> V=new Vector<MOB>(); // now grab the followers try { D=DB.DBFetch(); final ResultSet R=D.query("SELECT * FROM CMCHFO WHERE CMUSERID='"+mob.Name()+"'"); while(R.next()) { final String MOBID=DBConnections.getRes(R,"CMFOID"); final MOB newMOB=CMClass.getMOB(MOBID); if(newMOB==null) Log.errOut("MOB","Couldn't find MOB '"+MOBID+"'"); else { newMOB.setMiscText(DBConnections.getResQuietly(R,"CMFOTX")); newMOB.basePhyStats().setLevel(((int)DBConnections.getLongRes(R,"CMFOLV"))); newMOB.basePhyStats().setAbility((int)DBConnections.getLongRes(R,"CMFOAB")); newMOB.basePhyStats().setRejuv(PhyStats.NO_REJUV); newMOB.recoverPhyStats(); newMOB.recoverCharStats(); newMOB.recoverMaxState(); newMOB.resetToMaxState(); V.addElement(newMOB); } } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } return V; } public void DBReadFollowers(MOB mob, boolean bringToLife) { Room location=mob.location(); if(location==null) location=mob.getStartRoom(); final List<MOB> V=DBScanFollowers(mob); for(int v=0;v<V.size();v++) { final MOB newMOB=V.get(v); final Room room=(location==null)?newMOB.getStartRoom():location; newMOB.setStartRoom(room); newMOB.setLocation(room); newMOB.setFollowing(mob); if((newMOB.getStartRoom()!=null) &&(CMLib.law().doesHavePriviledgesHere(mob,newMOB.getStartRoom())) &&((newMOB.location()==null) ||(!CMLib.law().doesHavePriviledgesHere(mob,newMOB.location())))) { newMOB.setLocation(newMOB.getStartRoom()); } if(bringToLife) { newMOB.bringToLife(mob.location(),true); mob.location().showOthers(newMOB,null,CMMsg.MSG_OK_ACTION,CMLib.lang().L("<S-NAME> appears!")); } } } public void DBUpdateEmail(MOB mob) { final PlayerStats pstats=mob.playerStats(); if(pstats==null) return; DB.update("UPDATE CMCHAR SET CMEMAL='"+pstats.getEmail()+"' WHERE CMUSERID='"+mob.Name()+"'"); } private int BuildClanMemberRole(ResultSet R) { return (int)DBConnections.getLongRes(R,"CMCLRO"); } private MemberRecord BuildClanMemberRecord(ResultSet R) { final String username=DB.getRes(R,"CMUSERID"); final int clanRole = BuildClanMemberRole(R); int mobpvps=0; int playerpvps=0; final String stats=DB.getRes(R,"CMCLSTS"); if(stats!=null) { final String[] splitstats=stats.split(";"); if(splitstats.length>0) mobpvps=CMath.s_int(splitstats[0]); if(splitstats.length>1) playerpvps=CMath.s_int(splitstats[1]); } return new Clan.MemberRecord(username,clanRole,mobpvps,playerpvps); } public MemberRecord DBGetClanMember(String clan, String name) { DBConnection D=null; try { D=DB.DBFetch(); final ResultSet R=D.query("SELECT * FROM CMCHCL where CMCLAN='"+clan+"' and CMUSERID='"+name+"'"); if(R!=null) while(R.next()) { return BuildClanMemberRecord(R); } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } return null; } public List<Clan.MemberRecord> DBClanMembers(String clan) { final List<Clan.MemberRecord> members = new Vector<Clan.MemberRecord>(); DBConnection D=null; try { D=DB.DBFetch(); final ResultSet R=D.query("SELECT * FROM CMCHCL where CMCLAN='"+clan+"'"); if(R!=null) while(R.next()) { members.add(BuildClanMemberRecord(R)); } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } return members; } public void DBUpdateClanMembership(String name, String clan, int role) { final MOB M=CMLib.players().getPlayer(name); if(M!=null) { M.setClan(clan, role); } DBConnection D=null; try { D=DB.DBFetch(); if(role<0) { DB.update("DELETE FROM CMCHCL WHERE CMUSERID='"+name+"' AND CMCLAN='"+clan+"'"); if(CMSecurity.isDebugging(CMSecurity.DbgFlag.CLANMEMBERS)) Log.debugOut("User '"+name+"' was deleted from clan '"+clan+"'"); } else { final ResultSet R=D.query("SELECT * FROM CMCHCL where CMCLAN='"+clan+"' and CMUSERID='"+name+"'"); if((R!=null) && (R.next())) { final int clanRole = BuildClanMemberRole(R); R.close(); if(clanRole == role) return; D.update("UPDATE CMCHCL SET CMCLRO="+role+" where CMCLAN='"+clan+"' and CMUSERID='"+name+"'", 0); if(CMSecurity.isDebugging(CMSecurity.DbgFlag.CLANMEMBERS)) Log.debugOut("User '"+name+"' had role in clan '"+clan+"' changed from "+clanRole+" to "+role); } else { D.update("INSERT INTO CMCHCL (CMUSERID, CMCLAN, CMCLRO, CMCLSTS) values ('"+name+"','"+clan+"',"+role+",'0;0')",0); if(CMSecurity.isDebugging(CMSecurity.DbgFlag.CLANMEMBERS)) Log.debugOut("User '"+name+"' was inserted into clan '"+clan+"' as role "+role); } } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } } public void DBUpdateClanKills(String clan, String name, int adjMobKills, int adjPlayerKills) { if(((adjMobKills==0)&&(adjPlayerKills==0)) ||(clan==null) ||(name==null)) return; DBConnection D=null; try { D=DB.DBFetch(); final ResultSet R=D.query("SELECT * FROM CMCHCL where CMCLAN='"+clan+"' and CMUSERID='"+name+"'"); MemberRecord M=null; if(R!=null) { if(R.next()) { M=BuildClanMemberRecord(R); R.close(); M.mobpvps+=adjMobKills; M.playerpvps+=adjPlayerKills; final String newStats=M.mobpvps+";"+M.playerpvps; D.update("UPDATE CMCHCL SET CMCLSTS='"+newStats+"' where CMCLAN='"+clan+"' and CMUSERID='"+name+"'", 0); } } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } } public void DBUpdate(MOB mob) { DBUpdateJustMOB(mob); final PlayerStats pStats = mob.playerStats(); if((mob.Name().length()==0)||(pStats==null)) return; DBUpdateItems(mob); DBUpdateAbilities(mob); pStats.setLastUpdated(System.currentTimeMillis()); final PlayerAccount account = pStats.getAccount(); if(account != null) { DBUpdateAccount(account); account.setLastUpdated(System.currentTimeMillis()); } } public void DBUpdatePassword(String name, String password) { name=CMStrings.capitalizeAndLower(name); DB.update("UPDATE CMCHAR SET CMPASS='"+password+"' WHERE CMUSERID='"+name.replace('\'', 'n')+"'"); } private String getPlayerStatsXML(MOB mob) { final PlayerStats pstats=mob.playerStats(); if(pstats==null) return ""; final StringBuilder pfxml=new StringBuilder(pstats.getXML()); if(mob.tattoos().hasMoreElements()) { pfxml.append("<TATTS>"); for(final Enumeration<Tattoo> e=mob.tattoos();e.hasMoreElements();) pfxml.append(e.nextElement().toString()+";"); pfxml.append("</TATTS>"); } if(mob.expertises().hasMoreElements()) { pfxml.append("<EDUS>"); for(final Enumeration<String> x=mob.expertises();x.hasMoreElements();) pfxml.append(x.nextElement()).append(';'); pfxml.append("</EDUS>"); } pfxml.append(CMLib.xml().convertXMLtoTag("IMG",mob.rawImage())); return pfxml.toString(); } public void DBUpdateJustPlayerStats(MOB mob) { if(mob.Name().length()==0) { DBCreateCharacter(mob); return; } final PlayerStats pstats=mob.playerStats(); if(pstats==null) return; final String pfxml=getPlayerStatsXML(mob); DB.updateWithClobs("UPDATE CMCHAR SET CMPFIL=? WHERE CMUSERID='"+mob.Name()+"'", pfxml.toString()); } public void DBUpdateJustMOB(MOB mob) { if(mob.Name().length()==0) { DBCreateCharacter(mob); return; } final PlayerStats pstats=mob.playerStats(); if(pstats==null) return; final String strStartRoomID=(mob.getStartRoom()!=null)?CMLib.map().getExtendedRoomID(mob.getStartRoom()):""; String strOtherRoomID=(mob.location()!=null)?CMLib.map().getExtendedRoomID(mob.location()):""; if((mob.location()!=null) &&(mob.location().getArea()!=null) &&(CMath.bset(mob.location().getArea().flags(),Area.FLAG_INSTANCE_PARENT) ||CMath.bset(mob.location().getArea().flags(),Area.FLAG_INSTANCE_CHILD))) strOtherRoomID=strStartRoomID; final String playerStatsXML=getPlayerStatsXML(mob); final String factionDataXML=CMLib.coffeeMaker().getFactionXML(mob).toString(); DB.updateWithClobs( "UPDATE CMCHAR SET CMPASS='"+pstats.getPasswordStr()+"'" +", CMCHID='"+mob.ID()+"'" +", CMCLAS='"+mob.baseCharStats().getMyClassesStr()+"'" +", CMSTRE="+mob.baseCharStats().getStat(CharStats.STAT_STRENGTH) +", CMRACE='"+mob.baseCharStats().getMyRace().ID()+"'" +", CMDEXT="+mob.baseCharStats().getStat(CharStats.STAT_DEXTERITY) +", CMCONS="+mob.baseCharStats().getStat(CharStats.STAT_CONSTITUTION) +", CMGEND='"+((char)mob.baseCharStats().getStat(CharStats.STAT_GENDER))+"'" +", CMWISD="+mob.baseCharStats().getStat(CharStats.STAT_WISDOM) +", CMINTE="+mob.baseCharStats().getStat(CharStats.STAT_INTELLIGENCE) +", CMCHAR="+mob.baseCharStats().getStat(CharStats.STAT_CHARISMA) +", CMHITP="+mob.baseState().getHitPoints() +", CMLEVL='"+mob.baseCharStats().getMyLevelsStr()+"'" +", CMMANA="+mob.baseState().getMana() +", CMMOVE="+mob.baseState().getMovement() +", CMALIG=-1" +", CMEXPE="+mob.getExperience() +", CMEXLV="+mob.getExpNextLevel() +", CMWORS='"+mob.getWorshipCharID()+"'" +", CMPRAC="+mob.getPractices() +", CMTRAI="+mob.getTrains() +", CMAGEH="+mob.getAgeMinutes() +", CMGOLD="+mob.getMoney() +", CMWIMP="+mob.getWimpHitPoint() +", CMQUES="+mob.getQuestPoint() +", CMROID='"+strStartRoomID+"||"+strOtherRoomID+"'" +", CMDATE='"+pstats.getLastDateTime()+"'" +", CMCHAN="+pstats.getChannelMask() +", CMATTA="+mob.basePhyStats().attackAdjustment() +", CMAMOR="+mob.basePhyStats().armor() +", CMDAMG="+mob.basePhyStats().damage() +", CMBTMP="+mob.getAttributesBitmap() +", CMLEIG='"+mob.getLiegeID()+"'" +", CMHEIT="+mob.basePhyStats().height() +", CMWEIT="+mob.basePhyStats().weight() +", CMPRPT=?" +", CMCOLR=?" +", CMLSIP='"+pstats.getLastIP()+"'" +", CMEMAL=?" +", CMPFIL=?" +", CMSAVE=?" +", CMMXML=?" +", CMDESC=?" +" WHERE CMUSERID='"+mob.Name()+"'" ,new String[][]{{ pstats.getPrompt(), pstats.getColorStr(), pstats.getEmail(), playerStatsXML, mob.baseCharStats().getNonBaseStatsAsString(), factionDataXML, mob.description()+" " }} ); final List<String> clanStatements=new LinkedList<String>(); DBConnection D=null; try { D=DB.DBFetch(); final ResultSet R=D.query("SELECT * FROM CMCHCL WHERE CMUSERID='"+mob.Name()+"'"); final Set<String> savedClans=new HashSet<String>(); if(R!=null) { while(R.next()) { final String clanID=DB.getRes(R,"CMCLAN"); final Pair<Clan,Integer> role=mob.getClanRole(clanID); if(role==null) { clanStatements.add("DELETE FROM CMCHCL WHERE CMUSERID='"+mob.Name()+"' AND CMCLAN='"+clanID+"'"); if(CMSecurity.isDebugging(CMSecurity.DbgFlag.CLANMEMBERS)) Log.debugOut("User '"+mob.Name()+"' was deleted from clan '"+clanID+"'"); } else { final MemberRecord M=BuildClanMemberRecord(R); if(role.second.intValue()!=M.role) { clanStatements.add("UPDATE CMCHCL SET CMCLRO="+role+" where CMCLAN='"+clanID+"' and CMUSERID='"+mob.Name()+"'"); if(CMSecurity.isDebugging(CMSecurity.DbgFlag.CLANMEMBERS)) Log.debugOut("User '"+mob.Name()+"' had role in clan '"+clanID+"' changed from "+M.role+" to role "+role.second.intValue()); } } savedClans.add(clanID.toUpperCase()); } R.close(); } for(final Pair<Clan,Integer> p : mob.clans()) if(!savedClans.contains(p.first.clanID().toUpperCase())) { clanStatements.add("INSERT INTO CMCHCL (CMUSERID, CMCLAN, CMCLRO, CMCLSTS) values ('"+mob.Name()+"','"+p.first.clanID()+"',"+p.second.intValue()+",'0;0')"); if(CMSecurity.isDebugging(CMSecurity.DbgFlag.CLANMEMBERS)) Log.debugOut("User '"+mob.Name()+"' was added to clan '"+p.first.clanID()+"' as role "+p.second.intValue()); } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } if(clanStatements.size()>0) DB.update(clanStatements.toArray(new String[0])); } protected String getDBItemUpdateString(final MOB mob, final Item thisItem) { CMLib.catalog().updateCatalogIntegrity(thisItem); final String container=((thisItem.container()!=null)?(""+thisItem.container()):""); return "INSERT INTO CMCHIT (CMUSERID, CMITNM, CMITID, CMITTX, CMITLO, CMITWO, " +"CMITUR, CMITLV, CMITAB, CMHEIT" +") values ('"+mob.Name()+"','"+(thisItem)+"','"+thisItem.ID()+"',?,'"+container+"',"+thisItem.rawWornCode()+"," +thisItem.usesRemaining()+","+thisItem.basePhyStats().level()+","+thisItem.basePhyStats().ability()+"," +thisItem.basePhyStats().height()+")"; } private List<DBPreparedBatchEntry> getDBItemUpdateStrings(MOB mob) { final HashSet<String> done=new HashSet<String>(); final List<DBPreparedBatchEntry> strings=new LinkedList<DBPreparedBatchEntry>(); for(int i=0;i<mob.numItems();i++) { final Item thisItem=mob.getItem(i); if((thisItem!=null)&&(!done.contains(""+thisItem))&&(thisItem.isSavable())) { CMLib.catalog().updateCatalogIntegrity(thisItem); final String sql=getDBItemUpdateString(mob,thisItem); strings.add(new DBPreparedBatchEntry(sql,thisItem.text()+" ")); done.add(""+thisItem); } } final PlayerStats pStats=mob.playerStats(); if(pStats !=null) { final ItemCollection coll=pStats.getExtItems(); final List<Item> finalCollection=new LinkedList<Item>(); final List<Item> extraItems=new LinkedList<Item>(); for(int i=coll.numItems()-1;i>=0;i--) { final Item thisItem=coll.getItem(i); if((thisItem!=null)&&(!thisItem.amDestroyed())) { final Item cont=thisItem.ultimateContainer(null); if(cont.owner() instanceof Room) finalCollection.add(thisItem); } } for(final Item thisItem : finalCollection) { if(thisItem instanceof Container) { final List<Item> contents=((Container)thisItem).getDeepContents(); for(final Item I : contents) if(!finalCollection.contains(I)) extraItems.add(I); } } finalCollection.addAll(extraItems); for(final Item thisItem : finalCollection) { if(!done.contains(""+thisItem)) { CMLib.catalog().updateCatalogIntegrity(thisItem); final Item cont=thisItem.ultimateContainer(null); final String sql=getDBItemUpdateString(mob,thisItem); final String roomID=((cont.owner()==null)&&(thisItem instanceof SpaceObject)&&(CMLib.map().isObjectInSpace((SpaceObject)thisItem)))? ("SPACE."+CMParms.toListString(((SpaceObject)thisItem).coordinates())):CMLib.map().getExtendedRoomID((Room)cont.owner()); final String text="<ROOM ID=\""+roomID+"\" EXPIRE="+thisItem.expirationDate()+" />"+thisItem.text(); strings.add(new DBPreparedBatchEntry(sql,text)); done.add(""+thisItem); } } } return strings; } public void DBUpdateItems(MOB mob) { if(mob.Name().length()==0) return; final List<DBPreparedBatchEntry> statements=new LinkedList<DBPreparedBatchEntry>(); statements.add(new DBPreparedBatchEntry("DELETE FROM CMCHIT WHERE CMUSERID='"+mob.Name()+"'")); statements.addAll(getDBItemUpdateStrings(mob)); DB.updateWithClobs(statements); } protected List<Pair<String,Integer>>[][] DBFindPrideWinners(int topThisMany, short scanCPUPercent, boolean players) { @SuppressWarnings("unchecked") final List<Pair<String,Integer>>[][] top=new Vector[TimeClock.TimePeriod.values().length][AccountStats.PrideStat.values().length]; for(int x=0;x<top.length;x++) { for(int y=0;y<top[x].length;y++) top[x][y]=new Vector<Pair<String,Integer>>(topThisMany+1); } DBConnection D=null; final long msWait=Math.round(1000.0 * CMath.div(scanCPUPercent, 100)); final long sleepAmount=1000 - msWait; try { long nextWaitAfter=System.currentTimeMillis() + msWait; final long now=System.currentTimeMillis(); D=DB.DBFetch(); ResultSet R; if(players) R=D.query("SELECT CMUSERID,CMPFIL FROM CMCHAR"); else R=D.query("SELECT CMANAM,CMAXML FROM CMACCT"); while((R!=null)&&(R.next())) { final String userID=DB.getRes(R, players?"CMUSERID":"CMANAM"); String pxml; final MOB M=CMLib.players().getPlayer(userID); if((M!=null)&&(M.playerStats()!=null)&&(players)) pxml=M.playerStats().getXML(); else if((M!=null)&&(M.playerStats()!=null)&&(!players)&&(M.playerStats().getAccount()!=null)) pxml=M.playerStats().getAccount().getXML(); else if(players) pxml=DB.getRes(R, "CMPFIL"); else pxml=DB.getRes(R, "CMAXML"); final String[] pridePeriods=CMLib.xml().returnXMLValue(pxml, "NEXTPRIDEPERIODS").split(","); final String[] prideStats=CMLib.xml().returnXMLValue(pxml, "PRIDESTATS").split(";"); final Pair<Long,int[]>[] allData = CMLib.players().parsePrideStats(pridePeriods, prideStats); for(final TimeClock.TimePeriod period : TimeClock.TimePeriod.values()) { if(allData.length > period.ordinal()) { final Pair<Long,int[]> p=allData[period.ordinal()]; final List<Pair<String,Integer>>[] topPeriods=top[period.ordinal()]; if((period==TimeClock.TimePeriod.ALLTIME)||(now < p.first.longValue())) { for(final AccountStats.PrideStat pride : AccountStats.PrideStat.values()) { if((p.second.length>pride.ordinal())&&(p.second[pride.ordinal()]>0)) { final int val=p.second[pride.ordinal()]; final List<Pair<String,Integer>> topPrides=topPeriods[pride.ordinal()]; final int oldSize=topPrides.size(); for(int i=0;i<topPrides.size();i++) { if(val >= topPrides.get(i).second.intValue()) { topPrides.add(i, new Pair<String,Integer>(userID,Integer.valueOf(val))); while(topPrides.size()>topThisMany) topPrides.remove(topPrides.size()-1); break; } } if((oldSize==topPrides.size())&&(topPrides.size()<topThisMany)) topPrides.add(new Pair<String,Integer>(userID,Integer.valueOf(val))); } } } } } if((sleepAmount>0)&&(System.currentTimeMillis() > nextWaitAfter)) { CMLib.s_sleep(sleepAmount); nextWaitAfter=System.currentTimeMillis() + msWait; } } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } return top; } public List<Pair<String,Integer>>[][] DBScanPridePlayerWinners(int topThisMany, short scanCPUPercent) { return DBFindPrideWinners(topThisMany,scanCPUPercent,true); } public List<Pair<String,Integer>>[][] DBScanPrideAccountWinners(int topThisMany, short scanCPUPercent) { return DBFindPrideWinners(topThisMany,scanCPUPercent,false); } // this method is unused, but is a good idea of how to collect riders, followers, carts, etc. protected void addFollowerDependent(PhysicalAgent P, DVector list, String parent) { if(P==null) return; if(list.contains(P)) return; if((P instanceof MOB) &&((!((MOB)P).isMonster())||(((MOB)P).isPossessing()))) return; CMLib.catalog().updateCatalogIntegrity(P); final String myCode=""+(list.size()-1); list.addElement(P,CMClass.classID(P)+"#"+myCode+parent); if(P instanceof Rideable) { final Rideable R=(Rideable)P; for(int r=0;r<R.numRiders();r++) addFollowerDependent(R.fetchRider(r),list,"@"+myCode+"R"); } if(P instanceof Container) { final Container C=(Container)P; final List<Item> contents=C.getDeepContents(); for(int c=0;c<contents.size();c++) addFollowerDependent(contents.get(c),list,"@"+myCode+"C"); } } public void DBUpdateFollowers(MOB mob) { if((mob==null)||(mob.Name().length()==0)) return; final List<DBPreparedBatchEntry> statements=new LinkedList<DBPreparedBatchEntry>(); statements.add(new DBPreparedBatchEntry("DELETE FROM CMCHFO WHERE CMUSERID='"+mob.Name()+"'")); for(int f=0;f<mob.numFollowers();f++) { final MOB thisMOB=mob.fetchFollower(f); if((thisMOB!=null)&&(thisMOB.isMonster())&&(!thisMOB.isPossessing())&&(CMLib.flags().isSavable(thisMOB))) { CMLib.catalog().updateCatalogIntegrity(thisMOB); final String sql="INSERT INTO CMCHFO (CMUSERID, CMFONM, CMFOID, CMFOTX, CMFOLV, CMFOAB" +") values ('"+mob.Name()+"',"+f+",'"+CMClass.classID(thisMOB)+"',?," +thisMOB.basePhyStats().level()+","+thisMOB.basePhyStats().ability()+")"; statements.add(new DBPreparedBatchEntry(sql,thisMOB.text()+" ")); } } DB.updateWithClobs(statements); } public void DBNameChange(String oldName, String newName) { if((oldName==null) ||(oldName.trim().length()==0) ||(oldName.indexOf('\'')>=0) ||(newName==null) ||(newName.trim().length()==0) ||(newName.indexOf('\'')>=0)) return; DB.update("UPDATE CMCHAB SET CMUSERID='"+newName+"' WHERE CMUSERID='"+oldName+"'"); DB.update("UPDATE CMCHAR SET CMUSERID='"+newName+"' WHERE CMUSERID='"+oldName+"'"); DB.update("UPDATE CMCHAR SET CMWORS='"+newName+"' WHERE CMWORS='"+oldName+"'"); DB.update("UPDATE CMCHAR SET CMLEIG='"+newName+"' WHERE CMLEIG='"+oldName+"'"); DB.update("UPDATE CMCHCL SET CMUSERID='"+newName+"' WHERE CMUSERID='"+oldName+"'"); DB.update("UPDATE CMCHFO SET CMUSERID='"+newName+"' WHERE CMUSERID='"+oldName+"'"); DB.update("UPDATE CMCHIT SET CMUSERID='"+newName+"' WHERE CMUSERID='"+oldName+"'"); DB.update("UPDATE CMJRNL SET CMFROM='"+newName+"' WHERE CMFROM='"+oldName+"'"); DB.update("UPDATE CMJRNL SET CMTONM='"+newName+"' WHERE CMTONM='"+oldName+"'"); DB.update("UPDATE CMPDAT SET CMPLID='"+newName+"' WHERE CMPLID='"+oldName+"'"); } public void DBDelete(MOB mob, boolean deleteAssets) { if(mob.Name().length()==0) return; final List<String> channels=CMLib.channels().getFlaggedChannelNames(ChannelsLibrary.ChannelFlag.PLAYERPURGES); for(int i=0;i<channels.size();i++) CMLib.commands().postChannel(channels.get(i),mob.clans(),CMLib.lang().fullSessionTranslation("@x1 has just been deleted.",mob.Name()),true); CMLib.coffeeTables().bump(mob,CoffeeTableRow.STAT_PURGES); DB.update("DELETE FROM CMCHAR WHERE CMUSERID='"+mob.Name()+"'"); DB.update("DELETE FROM CMCHCL WHERE CMUSERID='"+mob.Name()+"'"); mob.delAllItems(false); for(int i=0;i<mob.numItems();i++) { final Item I=mob.getItem(i); if(I!=null) I.setContainer(null); } mob.delAllItems(false); DBUpdateItems(mob); while(mob.numFollowers()>0) { final MOB follower=mob.fetchFollower(0); if(follower!=null) follower.setFollowing(null); } if(deleteAssets) { DBUpdateFollowers(mob); } mob.delAllAbilities(); DBUpdateAbilities(mob); if(deleteAssets) { CMLib.database().DBDeletePlayerJournals(mob.Name()); CMLib.database().DBDeletePlayerData(mob.Name()); } final PlayerStats pstats = mob.playerStats(); if(pstats!=null) { final PlayerAccount account = pstats.getAccount(); if(account != null) { account.delPlayer(mob); DBUpdateAccount(account); account.setLastUpdated(System.currentTimeMillis()); } } if(deleteAssets) { for(int q=0;q<CMLib.quests().numQuests();q++) { final Quest Q=CMLib.quests().fetchQuest(q); if(Q.wasWinner(mob.Name())) Q.declareWinner("-"+mob.Name()); } } } public void DBUpdateAbilities(MOB mob) { if(mob.Name().length()==0) return; final List<DBPreparedBatchEntry> statements=new LinkedList<DBPreparedBatchEntry>(); statements.add(new DBPreparedBatchEntry("DELETE FROM CMCHAB WHERE CMUSERID='"+mob.Name()+"'")); final HashSet<String> H=new HashSet<String>(); for(int a=0;a<mob.numAbilities();a++) { final Ability thisAbility=mob.fetchAbility(a); if((thisAbility!=null)&&(thisAbility.isSavable())) { int proficiency=thisAbility.proficiency(); final Ability effectA=mob.fetchEffect(thisAbility.ID()); if(effectA!=null) { if((effectA.isSavable())&&(!effectA.canBeUninvoked())&&(!effectA.isAutoInvoked())) proficiency=proficiency-200; } H.add(thisAbility.ID()); final String sql="INSERT INTO CMCHAB (CMUSERID, CMABID, CMABPF,CMABTX" +") values ('"+mob.Name()+"','"+thisAbility.ID()+"',"+proficiency+",?)"; statements.add(new DBPreparedBatchEntry(sql,thisAbility.text())); } } for(final Enumeration<Ability> a=mob.personalEffects();a.hasMoreElements();) { final Ability A=a.nextElement(); if((A!=null)&&(!H.contains(A.ID()))&&(A.isSavable())&&(!A.canBeUninvoked())) { final String sql="INSERT INTO CMCHAB (CMUSERID, CMABID, CMABPF,CMABTX" +") values ('"+mob.Name()+"','"+A.ID()+"',"+Integer.MAX_VALUE+",?)"; statements.add(new DBPreparedBatchEntry(sql,A.text())); } } for(final Enumeration<Behavior> e=mob.behaviors();e.hasMoreElements();) { final Behavior B=e.nextElement(); if((B!=null)&&(B.isSavable())) { final String sql="INSERT INTO CMCHAB (CMUSERID, CMABID, CMABPF,CMABTX" +") values ('"+mob.Name()+"','"+B.ID()+"',"+(Integer.MIN_VALUE+1)+",?" +")"; statements.add(new DBPreparedBatchEntry(sql,B.getParms())); } } final String scriptStuff = CMLib.coffeeMaker().getGenScripts(mob,true); if(scriptStuff.length()>0) { final String sql="INSERT INTO CMCHAB (CMUSERID, CMABID, CMABPF,CMABTX" +") values ('"+mob.Name()+"','ScriptingEngine',"+(Integer.MIN_VALUE+1)+",?" +")"; statements.add(new DBPreparedBatchEntry(sql,scriptStuff)); } DB.updateWithClobs(statements); } public void DBCreateCharacter(MOB mob) { if(mob.Name().length()==0) return; final PlayerStats pstats=mob.playerStats(); if(pstats==null) return; DB.update("INSERT INTO CMCHAR (CMCHID, CMUSERID, CMPASS, CMCLAS, CMRACE, CMGEND " +") VALUES ('"+mob.ID()+"','"+mob.Name()+"','"+pstats.getPasswordStr()+"','"+mob.baseCharStats().getMyClassesStr() +"','"+mob.baseCharStats().getMyRace().ID()+"','"+((char)mob.baseCharStats().getStat(CharStats.STAT_GENDER)) +"')"); final PlayerAccount account = pstats.getAccount(); if(account != null) { account.addNewPlayer(mob); DBUpdateAccount(account); account.setLastUpdated(System.currentTimeMillis()); } } public void DBUpdateAccount(PlayerAccount account) { if(account == null) return; final String characters = CMParms.toSemicolonListString(account.getPlayers()); DB.updateWithClobs("UPDATE CMACCT SET CMPASS='"+account.getPasswordStr()+"', CMCHRS=?, CMAXML=? WHERE CMANAM='"+account.getAccountName()+"'", new String[][]{{characters,account.getXML()}}); } public void DBDeleteAccount(PlayerAccount account) { if(account == null) return; DB.update("DELETE FROM CMACCT WHERE CMANAM='"+account.getAccountName()+"'"); } public void DBCreateAccount(PlayerAccount account) { if(account == null) return; account.setAccountName(CMStrings.capitalizeAndLower(account.getAccountName())); final String characters = CMParms.toSemicolonListString(account.getPlayers()); DB.updateWithClobs("INSERT INTO CMACCT (CMANAM, CMPASS, CMCHRS, CMAXML) " +"VALUES ('"+account.getAccountName()+"','"+account.getPasswordStr()+"',?,?)",new String[][]{{characters,account.getXML()}}); } public PlayerAccount MakeAccount(String username, ResultSet R) throws SQLException { PlayerAccount account = null; account = (PlayerAccount)CMClass.getCommon("DefaultPlayerAccount"); final String password=DB.getRes(R,"CMPASS"); final String chrs=DB.getRes(R,"CMCHRS"); final String xml=DB.getRes(R,"CMAXML"); final Vector<String> names = new Vector<String>(); if(chrs!=null) names.addAll(CMParms.parseSemicolons(chrs,true)); account.setAccountName(CMStrings.capitalizeAndLower(username)); account.setPassword(password); account.setPlayerNames(names); account.setXML(xml); return account; } public PlayerAccount DBReadAccount(String Login) { DBConnection D=null; PlayerAccount account = null; try { // why in the hell is this a memory scan? // case insensitivity from databases configured almost // certainly by amateurs is the answer. That, and fakedb // doesn't understand 'LIKE' D=DB.DBFetch(); final ResultSet R=D.query("SELECT * FROM CMACCT WHERE CMANAM='"+CMStrings.replaceAll(CMStrings.capitalizeAndLower(Login),"\'", "n")+"'"); if(R!=null) while(R.next()) { final String username=DB.getRes(R,"CMANAM"); if(Login.equalsIgnoreCase(username)) account = MakeAccount(username,R); } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } return account; } public List<PlayerAccount> DBListAccounts(String mask) { DBConnection D=null; PlayerAccount account = null; final Vector<PlayerAccount> accounts = new Vector<PlayerAccount>(); if(mask!=null) mask=mask.toLowerCase(); try { // why in the hell is this a memory scan? // case insensitivity from databases configured almost // certainly by amateurs is the answer. That, and fakedb // doesn't understand 'LIKE' D=DB.DBFetch(); final ResultSet R=D.query("SELECT * FROM CMACCT"); if(R!=null) while(R.next()) { final String username=DB.getRes(R,"CMANAM"); if((mask==null)||(mask.length()==0)||(username.toLowerCase().indexOf(mask)>=0)) { account = MakeAccount(username,R); accounts.add(account); } } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } return accounts; } public List<String> DBExpiredCharNameSearch(Set<String> skipNames) { DBConnection D=null; String buf=null; final List<String> expiredPlayers = new ArrayList<String>(); final long now=System.currentTimeMillis(); try { D=DB.DBFetch(); final ResultSet R=D.query("SELECT * FROM CMCHAR"); if(R!=null) while(R.next()) { final String username=DB.getRes(R,"CMUSERID"); if((skipNames!=null)&&(skipNames.contains(username))) continue; buf=DBConnections.getRes(R,"CMPFIL"); final String secGrps=CMLib.xml().restoreAngleBrackets(CMLib.xml().returnXMLValue(buf,"SECGRPS")); final SecGroup g=CMSecurity.instance().createGroup("", CMParms.parseSemicolons(secGrps,true)); if(g.contains(SecFlag.NOEXPIRE, false)) continue; long expiration; if(CMLib.xml().returnXMLValue(buf,"ACCTEXP").length()>0) expiration=CMath.s_long(CMLib.xml().returnXMLValue(buf,"ACCTEXP")); else { final Calendar C=Calendar.getInstance(); C.add(Calendar.DATE,CMProps.getIntVar(CMProps.Int.TRIALDAYS)); expiration=C.getTimeInMillis(); } if(now>=expiration) expiredPlayers.add(username); } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } return expiredPlayers; } public PlayerLibrary.ThinnerPlayer DBUserSearch(String Login) { DBConnection D=null; String buf=null; PlayerLibrary.ThinnerPlayer thinPlayer = null; try { // why in the hell is this a memory scan? // case insensitivity from databases configured almost // certainly by amateurs is the answer. That, and fakedb // doesn't understand 'LIKE' D=DB.DBFetch(); final ResultSet R=D.query("SELECT * FROM CMCHAR WHERE CMUSERID='"+CMStrings.capitalizeAndLower(Login).replace('\'', 'n')+"'"); if(R!=null) while(R.next()) { final String username=DB.getRes(R,"CMUSERID"); thinPlayer = new PlayerLibrary.ThinnerPlayer(); final String password=DB.getRes(R,"CMPASS"); final String email=DB.getRes(R,"CMEMAL"); thinPlayer.name=username; thinPlayer.password=password; thinPlayer.email=email; // Acct Exp Code buf=DBConnections.getRes(R,"CMPFIL"); } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } if((buf!=null)&&(thinPlayer!=null)) { PlayerAccount acct = null; thinPlayer.accountName = CMLib.xml().returnXMLValue(buf,"ACCOUNT"); if((thinPlayer.accountName!=null)&&(thinPlayer.accountName.length()>0)) acct = CMLib.players().getLoadAccount(thinPlayer.accountName); if((acct != null)&&(CMProps.isUsingAccountSystem())) thinPlayer.expiration=acct.getAccountExpiration(); else if(CMLib.xml().returnXMLValue(buf,"ACCTEXP").length()>0) thinPlayer.expiration=CMath.s_long(CMLib.xml().returnXMLValue(buf,"ACCTEXP")); else { final Calendar C=Calendar.getInstance(); C.add(Calendar.DATE,CMProps.getIntVar(CMProps.Int.TRIALDAYS)); thinPlayer.expiration=C.getTimeInMillis(); } } return thinPlayer; } public String[] DBFetchEmailData(String name) { final String[] data=new String[2]; for(final Enumeration<MOB> e=CMLib.players().players();e.hasMoreElements();) { final MOB M=e.nextElement(); if((M.Name().equalsIgnoreCase(name))&&(M.playerStats()!=null)) { data[0]=M.playerStats().getEmail(); data[1]=""+M.isAttributeSet(MOB.Attrib.AUTOFORWARD); return data; } } DBConnection D=null; try { D=DB.DBFetch(); final ResultSet R=D.query("SELECT * FROM CMCHAR WHERE CMUSERID='"+name.replace('\'', 'n')+"'"); if(R!=null) while(R.next()) { // String username=DB.getRes(R,"CMUSERID"); final int btmp=CMath.s_int(DB.getRes(R,"CMBTMP")); final String temail=DB.getRes(R,"CMEMAL"); data[0]=temail; data[1]=""+((btmp&MOB.Attrib.AUTOFORWARD.getBitCode())!=0); return data; } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } return null; } public String DBPlayerEmailSearch(String email) { DBConnection D=null; for(final Enumeration<MOB> e=CMLib.players().players();e.hasMoreElements();) { final MOB M=e.nextElement(); if((M.playerStats()!=null)&&(M.playerStats().getEmail().equalsIgnoreCase(email))) return M.Name(); } try { D=DB.DBFetch(); email=DB.injectionClean(email.trim()); ResultSet R=D.query("SELECT * FROM CMCHAR WHERE CMEMAL='"+email+"'"); if(((R==null)||(!R.next()))&&(!CMStrings.isLowerCase(email))) R=D.query("SELECT * FROM CMCHAR WHERE CMEMAL='"+email.toLowerCase()+"'"); if((R==null)||(!R.next())) R=D.query("SELECT * FROM CMCHAR WHERE CMEMAL LIKE '"+email+"'"); if((R==null)||(!R.next())) R=D.query("SELECT * FROM CMCHAR"); if(R!=null) while(R.next()) { final String username=DB.getRes(R,"CMUSERID"); final String temail=DB.getRes(R,"CMEMAL"); if(temail.equalsIgnoreCase(email)) { return username; } } } catch(final Exception sqle) { Log.errOut("MOB",sqle); } finally { DB.DBDone(D); } return null; } }