@Override
  protected boolean autoGenInvoke(
      final MOB mob,
      List<String> commands,
      Physical givenTarget,
      final boolean auto,
      final int asLevel,
      int autoGenerate,
      boolean forceLevels,
      List<Item> crafted) {
    if (super.checkStop(mob, commands)) return true;

    if (super.checkInfo(mob, commands)) return true;

    final PairVector<EnhancedExpertise, Integer> enhancedTypes = enhancedTypes(mob, commands);
    randomRecipeFix(mob, addRecipes(mob, loadRecipes()), commands, autoGenerate);
    if (commands.size() == 0) {
      commonTell(
          mob,
          L(
              "Make what? Enter \"mleatherwork list\" for a list, \"mleatherworkd info <item>\", \"mleatherwork refit <item>\" to resize,"
                  + " \"mleatherwork learn <item>\", \"mleatherwork scan\", \"mleatherwork mend <item>\", or \"mleatherwork stop\" to cancel."));
      return false;
    }
    if ((!auto) && (commands.size() > 0) && ((commands.get(0)).equalsIgnoreCase("bundle"))) {
      bundling = true;
      if (super.invoke(mob, commands, givenTarget, auto, asLevel))
        return super.bundle(mob, commands);
      return false;
    }
    final List<List<String>> recipes = addRecipes(mob, loadRecipes());
    final String str = commands.get(0);
    playSound = "scissor.wav";
    String startStr = null;
    bundling = false;
    int multiplier = 4;
    int duration = 4;
    if (str.equalsIgnoreCase("list")) {
      String mask = CMParms.combine(commands, 1);
      boolean allFlag = false;
      if (mask.equalsIgnoreCase("all")) {
        allFlag = true;
        mask = "";
      }
      final StringBuffer buf = new StringBuffer("");
      int toggler = 1;
      final int toggleTop = 2;
      final int[] cols = {
        CMLib.lister().fixColWidth(30, mob.session()),
        CMLib.lister().fixColWidth(3, mob.session()),
        CMLib.lister().fixColWidth(3, mob.session())
      };
      for (int r = 0; r < toggleTop; r++)
        buf.append(
            (r > 0 ? " " : "")
                + CMStrings.padRight(L("Item"), cols[0])
                + " "
                + CMStrings.padRight(L("Lvl"), cols[1])
                + " "
                + CMStrings.padRight(L("Amt"), cols[2]));
      buf.append("\n\r");
      for (int r = 0; r < recipes.size(); r++) {
        final List<String> V = recipes.get(r);
        if (V.size() > 0) {
          final String item = replacePercent(V.get(RCP_FINALNAME), "");
          final int level = CMath.s_int(V.get(RCP_LEVEL));
          final String wood = getComponentDescription(mob, V, RCP_WOOD);
          if (wood.length() > 5) {
            if (toggler > 1) buf.append("\n\r");
            toggler = toggleTop;
          }
          if (((level <= xlevel(mob)) || allFlag)
              && ((mask.length() == 0)
                  || mask.equalsIgnoreCase("all")
                  || CMLib.english().containsString(item, mask))) {
            buf.append(
                CMStrings.padRight(item, cols[0])
                    + " "
                    + CMStrings.padRight("" + (level), cols[1])
                    + " "
                    + CMStrings.padRightPreserve("" + wood, cols[2])
                    + ((toggler != toggleTop) ? " " : "\n\r"));
            if (++toggler > toggleTop) toggler = 1;
          }
        }
      }
      if (toggler != 1) buf.append("\n\r");
      commonTell(mob, buf.toString());
      enhanceList(mob);
      return true;
    } else if (((commands.get(0))).equalsIgnoreCase("learn")) {
      return doLearnRecipe(mob, commands, givenTarget, auto, asLevel);
    } else if (str.equalsIgnoreCase("scan")) return publicScan(mob, commands);
    else if (str.equalsIgnoreCase("mend")) {
      buildingI = null;
      activity = CraftingActivity.CRAFTING;
      messedUp = false;
      final Vector<String> newCommands = CMParms.parse(CMParms.combine(commands, 1));
      buildingI =
          getTarget(mob, mob.location(), givenTarget, newCommands, Wearable.FILTER_UNWORNONLY);
      if (!canMend(mob, buildingI, false)) return false;
      activity = CraftingActivity.MENDING;
      if (!super.invoke(mob, commands, givenTarget, auto, asLevel)) return false;
      startStr = L("<S-NAME> start(s) mending @x1.", buildingI.name());
      displayText = L("You are mending @x1", buildingI.name());
      verb = L("mending @x1", buildingI.name());
    } else if (str.equalsIgnoreCase("refit")) {
      buildingI = null;
      activity = CraftingActivity.CRAFTING;
      messedUp = false;
      final Vector<String> newCommands = CMParms.parse(CMParms.combine(commands, 1));
      buildingI =
          getTarget(mob, mob.location(), givenTarget, newCommands, Wearable.FILTER_UNWORNONLY);
      if (buildingI == null) return false;
      if ((buildingI.material() & RawMaterial.MATERIAL_MASK) != RawMaterial.MATERIAL_LEATHER) {
        commonTell(mob, L("That's not made of leather.  That can't be refitted."));
        return false;
      }
      if (!(buildingI instanceof Armor)) {
        commonTell(mob, L("You don't know how to refit that sort of thing."));
        return false;
      }
      if (buildingI.phyStats().height() == 0) {
        commonTell(mob, L("@x1 is already the right size.", buildingI.name(mob)));
        return false;
      }
      activity = CraftingActivity.REFITTING;
      if (!super.invoke(mob, commands, givenTarget, auto, asLevel)) return false;
      startStr = L("<S-NAME> start(s) refitting @x1.", buildingI.name());
      displayText = L("You are refitting @x1", buildingI.name());
      verb = L("refitting @x1", buildingI.name());
    } else {
      buildingI = null;
      activity = CraftingActivity.CRAFTING;
      messedUp = false;
      aborted = false;
      int amount = -1;
      if ((commands.size() > 1) && (CMath.isNumber(commands.get(commands.size() - 1)))) {
        amount = CMath.s_int(commands.get(commands.size() - 1));
        commands.remove(commands.size() - 1);
      }
      final String recipeName = CMParms.combine(commands, 0);
      List<String> foundRecipe = null;
      final List<List<String>> matches = matchingRecipeNames(recipes, recipeName, true);
      for (int r = 0; r < matches.size(); r++) {
        final List<String> V = matches.get(r);
        if (V.size() > 0) {
          final String name = V.get(RCP_FINALNAME);
          final int level = CMath.s_int(V.get(RCP_LEVEL));
          if (level <= xlevel(mob)) {
            final int x = name.indexOf(' ');
            final Stage stage = Stage.valueOf(name.substring(0, x));
            multiplier = stage.multiplier;
            foundRecipe = V;
            break;
          }
        }
      }
      if (foundRecipe == null) {
        commonTell(
            mob,
            L(
                "You don't know how to make a '@x1'.  Try \"mleatherwork list\" for a list.",
                recipeName));
        return false;
      }

      final String woodRequiredStr = foundRecipe.get(RCP_WOOD);
      final int[] compData = new int[CF_TOTAL];
      final List<Object> componentsFoundList =
          getAbilityComponents(
              mob,
              woodRequiredStr,
              "make " + CMLib.english().startWithAorAn(recipeName),
              autoGenerate,
              compData);
      if (componentsFoundList == null) return false;
      int woodRequired = CMath.s_int(woodRequiredStr);
      woodRequired = adjustWoodRequired(woodRequired, mob);

      if (amount > woodRequired) woodRequired = amount;
      final int[] pm = {RawMaterial.MATERIAL_LEATHER};
      final int[] pm1 = {RawMaterial.MATERIAL_METAL, RawMaterial.MATERIAL_MITHRIL};
      final String misctype = foundRecipe.get(RCP_MISCTYPE);
      bundling = misctype.equalsIgnoreCase("BUNDLE");
      final int[][] data =
          fetchFoundResourceData(
              mob,
              woodRequired,
              "leather",
              pm,
              (multiplier == 6) ? 1 : 0,
              (multiplier == 6) ? "metal" : null,
              (multiplier == 6) ? pm1 : null,
              bundling,
              autoGenerate,
              enhancedTypes);
      if (data == null) return false;
      fixDataForComponents(data, componentsFoundList);
      woodRequired = data[0][FOUND_AMT];
      if (!super.invoke(mob, commands, givenTarget, auto, asLevel)) return false;
      final int lostValue =
          autoGenerate > 0
              ? 0
              : CMLib.materials()
                      .destroyResourcesValue(
                          mob.location(),
                          woodRequired,
                          data[0][FOUND_CODE],
                          data[1][FOUND_CODE],
                          null)
                  + CMLib.ableComponents().destroyAbilityComponents(componentsFoundList);
      buildingI = CMClass.getItem(foundRecipe.get(RCP_CLASSTYPE));
      if (buildingI == null) {
        commonTell(mob, L("There's no such thing as a @x1!!!", foundRecipe.get(RCP_CLASSTYPE)));
        return false;
      }
      duration = getDuration(multiplier * CMath.s_int(foundRecipe.get(RCP_TICKS)), mob, 30, 4);
      buildingI.setMaterial(super.getBuildingMaterial(woodRequired, data, compData));
      String itemName =
          (replacePercent(
                  foundRecipe.get(RCP_FINALNAME), RawMaterial.CODES.NAME(data[0][FOUND_CODE])))
              .toLowerCase();
      if (bundling) itemName = "a " + woodRequired + "# " + itemName;
      else if (itemName.endsWith("s")) itemName = "some " + itemName;
      else itemName = CMLib.english().startWithAorAn(itemName);
      buildingI.setName(itemName);
      startStr = L("<S-NAME> start(s) making @x1.", buildingI.name());
      displayText = L("You are making @x1", buildingI.name());
      verb = L("making @x1", buildingI.name());
      buildingI.setDisplayText(L("@x1 lies here", itemName));
      buildingI.setDescription(itemName + ". ");
      buildingI
          .basePhyStats()
          .setWeight(getStandardWeight(woodRequired + compData[CF_AMOUNT], bundling));
      buildingI.setBaseValue(CMath.s_int(foundRecipe.get(RCP_VALUE)) * multiplier);
      buildingI.setSecretIdentity(getBrand(mob));
      final int hardness = RawMaterial.CODES.HARDNESS(buildingI.material()) - 2;
      buildingI.basePhyStats().setLevel(CMath.s_int(foundRecipe.get(RCP_LEVEL)) + hardness);
      final int capacity = CMath.s_int(foundRecipe.get(RCP_CAPACITY));
      final long canContain = getContainerType(foundRecipe.get(RCP_CONTAINMASK));
      int armordmg = CMath.s_int(foundRecipe.get(RCP_ARMORDMG));
      if (armordmg != 0) armordmg = armordmg + (multiplier - 1);
      if (bundling) buildingI.setBaseValue(lostValue);
      final String spell =
          (foundRecipe.size() > RCP_SPELL) ? foundRecipe.get(RCP_SPELL).trim() : "";
      addSpells(buildingI, spell);
      if (buildingI instanceof Weapon) {
        ((Weapon) buildingI)
            .basePhyStats()
            .setAttackAdjustment(baseYield() + abilityCode() + (hardness * 5) - 1);
        ((Weapon) buildingI).setWeaponClassification(Weapon.CLASS_FLAILED);
        setWeaponTypeClass((Weapon) buildingI, misctype, Weapon.TYPE_SLASHING);
        buildingI.basePhyStats().setDamage(armordmg + hardness);
        ((Weapon) buildingI).setRawProperLocationBitmap(Wearable.WORN_WIELD | Wearable.WORN_HELD);
        ((Weapon) buildingI).setRawLogicalAnd((capacity > 1));
      }
      if ((buildingI instanceof Armor) && (!(buildingI instanceof FalseLimb))) {
        if ((capacity > 0) && (buildingI instanceof Container)) {
          ((Container) buildingI).setCapacity(capacity + woodRequired);
          ((Container) buildingI).setContainTypes(canContain);
        }
        ((Armor) buildingI).basePhyStats().setArmor(0);
        if (armordmg != 0)
          ((Armor) buildingI)
              .basePhyStats()
              .setArmor(armordmg + (baseYield() + abilityCode() - 1) + hardness);
        setWearLocation(buildingI, misctype, 0);
      }
      if (buildingI instanceof Drink) {
        if (CMLib.flags().isGettable(buildingI)) {
          ((Drink) buildingI).setLiquidRemaining(0);
          ((Drink) buildingI).setLiquidHeld(capacity * 50);
          ((Drink) buildingI).setThirstQuenched(250);
          if ((capacity * 50) < 250) ((Drink) buildingI).setThirstQuenched(capacity * 50);
        }
      }
      buildingI.recoverPhyStats();
      buildingI.text();
      buildingI.recoverPhyStats();
    }

    messedUp = !proficiencyCheck(mob, 0, auto);

    if (bundling) {
      messedUp = false;
      duration = 1;
      verb = L("bundling @x1", RawMaterial.CODES.NAME(buildingI.material()).toLowerCase());
      startStr = L("<S-NAME> start(s) @x1.", verb);
      displayText = L("You are @x1", verb);
    }

    if (autoGenerate > 0) {
      crafted.add(buildingI);
      return true;
    }

    final CMMsg msg = CMClass.getMsg(mob, buildingI, this, getActivityMessageType(), startStr);
    if (mob.location().okMessage(mob, msg)) {
      mob.location().send(mob, msg);
      buildingI = (Item) msg.target();
      beneficialAffect(mob, mob, asLevel, duration);
      enhanceItem(mob, buildingI, enhancedTypes);
    } else if (bundling) {
      messedUp = false;
      aborted = false;
      unInvoke();
    }
    return true;
  }