@Override
  public boolean invoke(MOB mob, Vector commands, Physical givenTarget, boolean auto, int asLevel) {
    if (CMParms.combine(commands, 0).equalsIgnoreCase("auto")) {
      DATA.clear();
      IPS.clear();
      final Hashtable<String, List<MOB>> ipes = new Hashtable<String, List<MOB>>();
      for (final Session S : CMLib.sessions().localOnlineIterable()) {
        if ((S.getAddress().length() > 0) && (S.mob() != null)) {
          List V = ipes.get(S.getAddress());
          if (V == null) {
            V = new Vector();
            ipes.put(S.getAddress(), V);
          }
          if (!V.contains(S.mob())) V.add(S.mob());
        }
      }
      final StringBuffer rpt = new StringBuffer("");
      for (final Enumeration e = ipes.keys(); e.hasMoreElements(); ) {
        final String addr = (String) e.nextElement();
        final List<MOB> names = ipes.get(addr);
        if (names.size() > 1) {
          IPS.put(addr, names);
          rpt.append("Watch #" + (IPS.size()) + " added: ");
          for (int n = 0; n < names.size(); n++) {
            final MOB MN = names.get(n);
            if (MN.fetchEffect(ID()) == null) {
              final Ability A = (Ability) copyOf();
              MN.addNonUninvokableEffect(A);
              A.setSavable(false);
            }
            rpt.append(MN.Name() + " ");
          }
          rpt.append("\n\r");
        }
      }
      if (rpt.length() == 0)
        rpt.append("No users with duplicate IDs found.  Try MULTIWATCH ADD name1 name2 ... ");
      mob.tell(rpt.toString());
      return true;
    } else if (CMParms.combine(commands, 0).equalsIgnoreCase("stop")) {
      boolean foundLegacy = false;
      for (final Session S : CMLib.sessions().localOnlineIterable()) {
        if ((S != null) && (S.mob() != null) && (S.mob().fetchEffect(ID()) != null)) {
          foundLegacy = true;
          break;
        }
      }
      if ((DATA.size() == 0) && (IPS.size() == 0) && (!foundLegacy)) {
        mob.tell(L("Multiwatch is already off."));
        return false;
      }
      for (final Enumeration<List<MOB>> e = IPS.elements(); e.hasMoreElements(); ) {
        final List<MOB> V = e.nextElement();
        for (int v = 0; v < V.size(); v++) {
          final MOB M = V.get(v);
          final Ability A = M.fetchEffect(ID());
          if (A != null) M.delEffect(A);
        }
      }
      for (final Session S : CMLib.sessions().localOnlineIterable()) {
        if ((S != null) && (S.mob() != null)) {
          final MOB M = S.mob();
          final Ability A = M.fetchEffect(ID());
          if (A != null) M.delEffect(A);
        }
      }
      mob.tell(L("Multiplay watcher is now turned off."));
      DATA.clear();
      IPS.clear();
      return true;
    } else if ((commands.size() > 1)
        && ((String) commands.firstElement()).equalsIgnoreCase("add")) {
      final Vector V = new Vector();
      for (int i = 1; i < commands.size(); i++) {
        final String name = (String) commands.elementAt(i);
        final MOB M = CMLib.players().getPlayer(name);
        if ((M.session() != null) && (CMLib.flags().isInTheGame(M, true))) V.addElement(M);
        else mob.tell(L("'@x1' is not online.", name));
      }
      if (V.size() > 1) {
        for (int n = 0; n < V.size(); n++) {
          final MOB MN = (MOB) V.elementAt(n);
          if (MN.fetchEffect(ID()) == null) {
            final Ability A = (Ability) copyOf();
            MN.addNonUninvokableEffect(A);
            A.setSavable(false);
          }
        }
        IPS.put("MANUAL" + (IPS.size() + 1), V);
        mob.tell(L("Manual Watch #@x1 added.", "" + IPS.size()));
      }
      return true;
    } else if ((commands.size() == 0) && (DATA.size() > 0) && (IPS.size() > 0)) {
      final StringBuffer report = new StringBuffer("");
      for (final Enumeration<String> e = IPS.keys(); e.hasMoreElements(); ) {
        final String key = e.nextElement();
        int sync = 0;
        final List<MOB> V = IPS.get(key);
        for (int v = 0; v < V.size(); v++) {
          final MOB M = V.get(v);
          final int data[] = DATA.get(M);
          if (data != null) sync += data[DATA_SYNCHROFOUND];
        }
        report.append("^x" + key + "^?^., Syncs: " + sync + "\n\r");
        report.append(
            CMStrings.padRight(L("Name"), 25)
                + CMStrings.padRight(L("Speech"), 15)
                + CMStrings.padRight(L("Socials"), 15)
                + CMStrings.padRight(L("CMD"), 10)
                + CMStrings.padRight(L("ORDERS"), 10)
                + "\n\r");
        for (int v = 0; v < V.size(); v++) {
          final MOB M = V.get(v);
          int data[] = DATA.get(M);
          if (data == null) data = new int[DATA_TOTAL];
          report.append(CMStrings.padRight(M.Name(), 25));
          report.append(
              CMStrings.padRight(
                  data[DATA_GOODSPEECH] + "/" + data[DATA_DIRSPEECH] + "/" + data[DATA_ANYSPEECH],
                  15));
          report.append(
              CMStrings.padRight(
                  data[DATA_GOODSOCIAL] + "/" + data[DATA_DIRSOCIAL] + "/" + data[DATA_ANYSOCIAL],
                  15));
          report.append(CMStrings.padRight(data[DATA_TYPEDCOMMAND] + "", 10));
          report.append(CMStrings.padRight(data[DATA_ORDER] + "", 10));
          report.append("\n\r");
        }
        report.append("\n\r");
      }

      mob.tell(report.toString());
      return true;
    } else {
      mob.tell(L("Try MULTIWATCH AUTO, MULTIWATCH STOP, or MULTIWATCH ADD name1 name2.."));
      return false;
    }
  }