@SideOnly(Side.CLIENT)
  private static Pair<String, KnowledgeObject<?>> getObject(char type, String identifier) {
    KnowledgeObject<?> obj = null;
    String text = null;

    boolean isHEE = identifier.charAt(0) == '~' && identifier.length() > 1;
    if (isHEE) identifier = identifier.substring(1);

    switch (type) {
      case 'b':
      case 'i':
        int metaIndex = identifier.indexOf('/'), meta = 0;

        if (metaIndex != -1 && metaIndex + 1 < identifier.length()) {
          meta = DragonUtil.tryParse(identifier.substring(metaIndex + 1), 0);
          identifier = identifier.substring(0, metaIndex);
        }

        Item item =
            GameRegistry.findItem(isHEE ? "HardcoreEnderExpansion" : "minecraft", identifier);

        if (item != null) {
          text =
              StatCollector.translateToLocal(
                  item.getUnlocalizedName(new ItemStack(item, 1, meta)) + ".name");
          obj =
              KnowledgeObject.fromObject(
                  type == 'b'
                      ? (item instanceof ItemBlock
                          ? new BlockInfo(((ItemBlock) item).field_150939_a, meta)
                          : null)
                      : item);
        }

        break;

      case 'e':
        if (isHEE)
          text =
              ItemSpawnEggs.getMobName(
                  (Class<?>)
                      EntityList.stringToClassMapping.get(
                          identifier = ("HardcoreEnderExpansion." + identifier)));
        else text = StatCollector.translateToLocal("entity." + identifier + ".name");

        Class<?> cls = (Class<?>) EntityList.stringToClassMapping.get(identifier);
        if (cls != null) obj = KnowledgeObject.fromObject(cls);
        break;

      case 'd':
        obj = KnowledgeObject.fromObject(identifier);
        if (obj != null) text = obj.getTranslatedTooltip();
        break;
    }

    if (text == null || obj == null) {
      Log.warn("Invalid object type or identifier: $0:$1", type, identifier);
      return Pair.<String, KnowledgeObject<?>>of(text == null ? identifier : text, obj);
    } else return Pair.<String, KnowledgeObject<?>>of(text, obj);
  }
 @Override
 public boolean onItemUse(
     ItemStack is,
     EntityPlayer player,
     World world,
     int x,
     int y,
     int z,
     int side,
     float hitX,
     float hitY,
     float hitZ) {
   if (!world.isRemote && Log.isDebugEnabled())
     doDebugAction(is, NBT.item(is, false), player, Pos.at(x, y, z));
   return true;
 }
  @SideOnly(Side.CLIENT)
  private String convertString(String str) {
    if (parsed != null) return parsed;

    if (str.indexOf('$') == -1) return parsed = str;

    int index = 0, lastIndex = 0;
    char type = 0, tmp;
    StringBuilder build = new StringBuilder(str.length()), tmpBuild = new StringBuilder(16);

    while (true) {
      if ((index = str.indexOf('$', lastIndex)) == -1) break;
      build.append(str.substring(lastIndex, index));

      if (index >= str.length() - 2) {
        Log.warn("Invalid text formatting, incorrect link start location: $0", str);
        break;
      }

      type = str.charAt(++index);

      if (str.charAt(++index) != ':') {
        Log.warn("Invalid text formatting, expected a colon: $0", str);
        break;
      }

      tmpBuild.setLength(0);

      while (index < str.length() - 1) {
        tmp = Character.toLowerCase(str.charAt(++index));

        if ((tmp >= 'a' && tmp <= 'z')
            || (tmp >= '0' && tmp <= '9')
            || tmp == '_'
            || tmp == '/'
            || tmp == '~') tmpBuild.append(str.charAt(index));
        else break;
      }

      build.append(linkColor);

      if (str.charAt(index) == ':') {
        lastIndex = ++index;
        index = str.indexOf('$', lastIndex);

        if (index == -1) {
          Log.warn("Invalid text formatting, display text not terminated: $0", str);
          break;
        }

        parsedObjects.add(getObject(type, tmpBuild.toString()).getRight());
        build.append(str.substring(lastIndex, index++));
      } else if (tmpBuild.length() > 0) {
        Pair<String, KnowledgeObject<?>> pair = getObject(type, tmpBuild.toString());
        parsedObjects.add(pair.getRight());
        build.append(pair.getLeft());
      } else {
        Log.warn("Invalid text formatting, identifier empty: $0", str);
        break;
      }

      lastIndex = index;
      build.append(EnumChatFormatting.BLACK);
    }

    if (parsedObjects.contains(null))
      Log.warn("Invalid text formatting, unknown object found: $0 $1", str, parsedObjects);

    return parsed = build.append(str.substring(lastIndex)).toString();
  }
 @Override
 public ItemStack onItemRightClick(ItemStack is, World world, EntityPlayer player) {
   if (!world.isRemote && Log.isDebugEnabled())
     doDebugAction(is, NBT.item(is, false), player, null);
   return is;
 }