public void players(MOB mob, List<String> commands)
		throws IOException
	{
		if(commands.size()<3)
		{
			mob.tell(L("You have failed to specify the proper fields.\n\rThe format is MODIFY USER [PLAYER NAME] ([STAT],?) (VALUE)\n\r"));
			mob.location().showOthers(mob,null,CMMsg.MSG_OK_ACTION,L("<S-NAME> flub(s) a powerful spell."));
			return;
		}

		final String mobID=commands.get(2);
		MOB M=CMLib.players().getLoadPlayer(mobID);
		if(M!=null)
		{
			if(M.playerStats()!=null)
				M.playerStats().setLastUpdated(M.playerStats().getLastDateTime());
			M.recoverPhyStats();
			M.recoverCharStats();
		}
		else
		{
			mob.tell(L("There is no such player as '@x1'!",mobID));
			mob.location().showOthers(mob,null,CMMsg.MSG_OK_ACTION,L("<S-NAME> flub(s) a powerful spell."));
			return;
		}
		mob.location().showOthers(mob,M,CMMsg.MSG_OK_ACTION,L("<S-NAME> wave(s) <S-HIS-HER> hands around <T-NAMESELF>."));
		final MOB copyMOB=(MOB)M.copyOf();
		M.basePhyStats().copyInto(copyMOB.basePhyStats());
		M.phyStats().copyInto(copyMOB.phyStats());
		mob.location().delInhabitant(copyMOB); //necc because location is cleared later, before destroy is called.
		if(commands.size()<4)
		{
			CMLib.genEd().modifyPlayer(mob,M,-1);
			if(!copyMOB.sameAs(M))
				Log.sysOut("Mobs",mob.Name()+" modified player "+M.Name()+".");
		}
		else
		{
			final String command=commands.get(3).toUpperCase();
			final String restStr=CMParms.combine(commands,4);
			if(command.equalsIgnoreCase("PROFICIENCIES")||command.equalsIgnoreCase("PROFICIENCY"))
			{
				final int prof=CMath.s_int(restStr);
				for(int a=0;a<M.numAbilities();a++)
					M.fetchAbility(a).setProficiency(prof);
				for(int a=0;a<M.numEffects();a++)
				{
					final Ability A=M.fetchEffect(a);
					if((A!=null)&&(A.isNowAnAutoEffect()))
						A.setProficiency(prof);
				}
				mob.tell(L("All of @x1's skill proficiencies set to @x2",M.Name(),""+prof));
				Log.sysOut("Mobs",mob.Name()+" modified player "+M.Name()+" skill proficiencies.");
			}
			else
			if(command.toUpperCase().startsWith("PROFICIENCY(")&&command.endsWith(")"))
			{
				final int prof=CMath.s_int(restStr);
				final String ableName=command.substring(12,command.length()-1).trim();
				final Ability A=M.findAbility(ableName);
				if(A==null)
				{
					mob.tell(L("...but failed to specify an valid ability name.  Try one of: @x1",CMParms.toCMObjectListString(M.abilities())));
					mob.location().showOthers(mob,null,CMMsg.MSG_OK_ACTION,L("<S-NAME> flub(s) a spell.."));
					return;
				}
				A.setProficiency(prof);
				final Ability eA=M.fetchEffect(A.ID());
				if((eA!=null)&&(eA.isNowAnAutoEffect()))
					eA.setProficiency(prof);
				mob.tell(L("@x1's skill proficiency in @x2 set to @x3",M.Name(),A.ID(),""+prof));
				Log.sysOut("Mobs",mob.Name()+" modified player "+M.Name()+" skill proficiency in "+A.ID()+".");
			}
			else
			if(CMLib.coffeeMaker().isAnyGenStat(M, command))
			{
				CMLib.coffeeMaker().setAnyGenStat(M,command, restStr);
				M.recoverPhyStats();
				M.recoverCharStats();
				M.recoverMaxState();
				if(!copyMOB.sameAs(M))
					Log.sysOut("Mobs",mob.Name()+" modified player "+M.Name()+".");
			}
			else
			{
				final STreeSet<String> set=new STreeSet<String>();
				set.addAll(CMLib.coffeeMaker().getAllGenStats(M));
				set.add("PROFICIENCIES");
				set.add("PROFICIENCY(ABILITY_ID)");
				mob.tell(L("...but failed to specify an aspect.  Try one of: @x1",CMParms.toListString(set)));
				mob.location().showOthers(mob,null,CMMsg.MSG_OK_ACTION,L("<S-NAME> flub(s) a spell.."));
			}
			CMLib.database().DBUpdatePlayer(M);
			if(CMLib.flags().isInTheGame(M,true))
				CMLib.database().DBUpdateFollowers(M);
		}
		copyMOB.setSession(null); // prevents logoffs.
		copyMOB.setLocation(null);
		copyMOB.destroy();
	}