Package ch.njol.skript.aliases

Source Code of ch.njol.skript.aliases.Aliases$Variations

/*
*   This file is part of Skript.
*
*  Skript is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  Skript is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with Skript.  If not, see <http://www.gnu.org/licenses/>.
*
*
* Copyright 2011-2014 Peter Güttinger
*
*/

package ch.njol.skript.aliases;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.eclipse.jdt.annotation.Nullable;

import ch.njol.skript.ScriptLoader;
import ch.njol.skript.Skript;
import ch.njol.skript.config.Config;
import ch.njol.skript.config.EntryNode;
import ch.njol.skript.config.Node;
import ch.njol.skript.config.SectionNode;
import ch.njol.skript.config.validate.SectionValidator;
import ch.njol.skript.localization.ArgsMessage;
import ch.njol.skript.localization.Language;
import ch.njol.skript.localization.Message;
import ch.njol.skript.localization.Noun;
import ch.njol.skript.localization.RegexMessage;
import ch.njol.skript.log.BlockingLogHandler;
import ch.njol.skript.log.SkriptLogger;
import ch.njol.skript.util.EnchantmentType;
import ch.njol.skript.util.Utils;
import ch.njol.util.NonNullPair;
import ch.njol.util.Setter;

/**
* @author Peter Güttinger
*/
@SuppressWarnings("deprecation")
public abstract class Aliases {
 
  /**
   * Note to self: never use this, use {@link #getAlias_i(String)} instead.
   */
  private final static HashMap<String, ItemType> aliases_english = new HashMap<String, ItemType>(10000);
  private final static HashMap<String, ItemType> aliases_localised = new HashMap<String, ItemType>(1000);
 
  private final static HashMap<String, ItemType> getAliases() {
    return Language.isUsingLocal() ? aliases_localised : aliases_english;
  }
 
  @Nullable
  private final static ItemType getAlias_i(final String s) {
    final ItemType t = ScriptLoader.getScriptAliases().get(s);
    if (t != null)
      return t;
    return getAliases().get(s);
  }
 
  private final static HashMap<Integer, MaterialName> materialNames_english = new HashMap<Integer, MaterialName>(Material.values().length);
  private final static HashMap<Integer, MaterialName> materialNames_localised = new HashMap<Integer, MaterialName>(Material.values().length);
 
  private final static HashMap<Integer, MaterialName> getMaterialNames() {
    return Language.isUsingLocal() ? materialNames_localised : materialNames_english;
  }
 
  static String itemSingular = "item";
  static String itemPlural = "items";
  @Nullable
  static String itemGender = null;
  static String blockSingular = "block";
  static String blockPlural = "blocks";
  @Nullable
  static String blockGender = null;
 
  // this is not an alias!
  private final static ItemType everything = new ItemType();
  static {
    everything.setAll(true);
    everything.add(new ItemData());
  }
 
  private final static Message m_brackets_error = new Message("aliases.brackets error");
  private final static ArgsMessage m_invalid_brackets = new ArgsMessage("aliases.invalid brackets");
  private final static ArgsMessage m_empty_alias = new ArgsMessage("aliases.empty alias");
  private final static ArgsMessage m_unknown_variation = new ArgsMessage("aliases.unknown variation");
  private final static Message m_starting_with_number = new Message("aliases.starting with number");
  private final static Message m_missing_aliases = new Message("aliases.missing aliases");
  private final static Message m_empty_string = new Message("aliases.empty string");
  private final static ArgsMessage m_invalid_item_data = new ArgsMessage("aliases.invalid item data");
  private final static ArgsMessage m_invalid_id = new ArgsMessage("aliases.invalid id");
  private final static Message m_invalid_block_data = new Message("aliases.invalid block data");
  private final static ArgsMessage m_invalid_item_type = new ArgsMessage("aliases.invalid item type");
  private final static ArgsMessage m_out_of_data_range = new ArgsMessage("aliases.out of data range");
  private final static Message m_invalid_range = new Message("aliases.invalid range");
  private final static ArgsMessage m_invalid_section = new ArgsMessage("aliases.invalid section");
  private final static ArgsMessage m_section_not_found = new ArgsMessage("aliases.section not found");
  private final static ArgsMessage m_not_a_section = new ArgsMessage("aliases.not a section");
  private final static Message m_unexpected_non_variation_section = new Message("aliases.unexpected non-variation section");
  private final static Message m_unexpected_section = new Message("aliases.unexpected section");
  private final static ArgsMessage m_loaded_x_aliases_from = new ArgsMessage("aliases.loaded x aliases from");
  private final static ArgsMessage m_loaded_x_aliases = new ArgsMessage("aliases.loaded x aliases");
 
  final static class Variations extends HashMap<String, HashMap<String, ItemType>> {
    private final static long serialVersionUID = -139481665727386819L;
  }
 
  private static int nextBracket(final String s, final char closingBracket, final char openingBracket, final int start) {
    int n = 0;
    assert s.charAt(start) == openingBracket;
    for (int i = start + 1; i < s.length(); i++) {
      if (s.charAt(i) == '\\') {
        i++;
        continue;
      } else if (s.charAt(i) == closingBracket) {
        if (n == 0)
          return i;
        n--;
      } else if (s.charAt(i) == openingBracket) {
        n++;
      }
    }
    Skript.error(m_invalid_brackets.toString(openingBracket + "" + closingBracket));
    return -1;
  }
 
  /**
   * Concatenates parts of an alias's name. This currently 'lowercases' the first character of any part if there's no space in front of it. It also replaces double spaces with a
   * single one and trims the resulting string.
   *
   * @param parts
   */
  private final static String concatenate(final String... parts) {
    assert parts.length >= 2;
    final StringBuilder b = new StringBuilder();
    for (int i = 0; i < parts.length; i++) {
      if (parts[i].isEmpty())
        continue;
      if (b.length() == 0) {
        b.append(parts[i]);
        continue;
      }
      final char c = parts[i].charAt(0);
      if (Character.isUpperCase(c) && b.charAt(b.length() - 1) != ' ') {
        b.append(Character.toLowerCase(c) + parts[i].substring(1));
      } else {
        b.append(parts[i]);
      }
    }
    return "" + b.toString().replace("  ", " ").trim();
  }
 
  /**
   * @param name Mixedcase string with no whitespace besides spaces and no double spaces.
   * @param value The alias's value, used for {variations}
   * @param variations
   * @return A map containing all parsed aliases
   */
  static LinkedHashMap<String, ItemType> getAliases(final String name, final ItemType value, final Variations variations) {
    final LinkedHashMap<String, ItemType> r = new LinkedHashMap<String, ItemType>(); // LinkedHashMap to preserve order for item names
    for (int i = 0; i < name.length(); i++) {
      final char c = name.charAt(i);
      if ("[({".indexOf(c) != -1) {
        final int end = nextBracket(name, "])}".charAt("[({".indexOf(c)), c, i);
        if (end == -1)
          return r;
        if (c == '[') {
          r.putAll(getAliases(concatenate(name.substring(0, i), name.substring(i + 1, end), name.substring(end + 1)), value, variations));
          r.putAll(getAliases(concatenate(name.substring(0, i), name.substring(end + 1)), value, variations));
        } else if (c == '(') {
          int n = 0;
          int last = i;
          boolean hasParts = false;
          for (int j = i + 1; j < end; j++) {
            final char x = name.charAt(j);
            if (x == '(') {
              n++;
            } else if (x == ')') {
              n--;
            } else if (x == '|') {
              if (n > 0)
                continue;
              hasParts = true;
              r.putAll(getAliases(concatenate(name.substring(0, i), name.substring(last + 1, j), name.substring(end + 1)), value, variations));
              last = j;
            }
          }
          if (!hasParts) {
            Skript.error(m_brackets_error.toString());
            return r;
          }
          r.putAll(getAliases(concatenate(name.substring(0, i), name.substring(last + 1, end), name.substring(end + 1)), value, variations));
        } else {
          assert c == '{';
          continue;
        }
        return r;
      }
    }
   
    // variations and <any>/<block>/etc. are replaced last because they replace genders
   
    int i = name.indexOf('{');
    if (i != -1) {
      final int end = name.indexOf('}', i + 1);
      if (end == -1) {// checked above
        assert false;
        return r;
      }
      final String var = name.substring(i + 1, end);
      if (variations.containsKey(var)) {
        boolean hasDefault = false;
        for (final Entry<String, ItemType> v : variations.get(var).entrySet()) {
          final String n;
          if (v.getKey().equalsIgnoreCase("{default}")) {
            hasDefault = true;
            if (v.getValue() == null)
              continue;
            n = concatenate(name.substring(0, i), name.substring(end + 1));
          } else {
            final int g = v.getKey().lastIndexOf('@');
            if (g == -1) {
              n = concatenate(name.substring(0, i), v.getKey(), name.substring(end + 1));
            } else {
              final String n0 = concatenate(name.substring(0, i), v.getKey().substring(0, g), name.substring(end + 1));
              final int c0 = n0.lastIndexOf('@');
              n = (c0 == -1 ? n0 : n0.substring(0, c0).trim() + v.getKey().substring(g));
            }
          }
          final ItemType t = v.getValue().intersection(value);
          if (t != null)
            r.putAll(getAliases(n, t, variations));
          else
            Skript.warning(m_empty_alias.toString(n));
        }
        if (!hasDefault)
          r.putAll(getAliases(concatenate(name.substring(0, i), name.substring(end + 1)), value, variations));
      } else {
        Skript.error(m_unknown_variation.toString(var));
      }
      return r;
    }
   
    i = name.indexOf('<');
    if (i != -1) {
      final int end = name.indexOf('>', i + 1);
      if (end != -1) {
        final String x = name.substring(i + 1, end);
        if (x.equalsIgnoreCase("any")) {
          String s = name.substring(0, i) + m_any.toString() + name.substring(end + 1);
          final int g = s.lastIndexOf('@');
          if (g != -1)
            s = s.substring(0, g + 1) + "-";
          r.putAll(getAliases(s, value, variations));
          return r;
        } else {
          final String[][] os = {
              {"item", itemSingular, itemPlural, itemGender},
              {"block", blockSingular, blockPlural, blockGender},
              {"item/block", itemSingular, itemPlural, itemGender, blockSingular, blockPlural, blockGender},
              {"block/item", blockSingular, blockPlural, blockGender, itemSingular, itemPlural, itemGender},
          };
          for (final String[] o : os) {
            if (x.equalsIgnoreCase(o[0])) {
              for (int j = 1; j < o.length; j += 3) {
                String s = name.substring(0, i) + "¦" + o[j] + "¦" + o[j + 1] + "¦" + name.substring(end + 1);
                if (o[j + 2] != null) {
                  final NonNullPair<String, Integer> p = Noun.stripGender(s, s);
                  s = p.getFirst() + "@" + o[j + 2];
                }
                r.put(s, value);
              }
              return r;
            }
          }
        }
      }
    }
   
    r.put(name, value);
    r.remove("");
    return r;
  }
 
  @SuppressWarnings("null")
  private final static Pattern numberWordPattern = Pattern.compile("\\d+\\s+.+");
 
  /**
   * Parses & adds new aliases
   *
   * @param name mixedcase string
   * @param value
   * @param variations
   * @return amount of added aliases
   */
  static int addAliases(final String name, final String value, final Variations variations) {
    final ItemType t = parseAlias(value);
    if (t == null) {
      return 0;
    }
    final HashMap<String, ItemType> aliases = getAliases();
    final HashMap<String, ItemType> as = getAliases("" + name.replaceAll("\\s+", " "), t, variations);
    boolean printedStartingWithNumberError = false;
//    boolean printedSyntaxError = false;
    for (final Entry<String, ItemType> e : as.entrySet()) {
      final String s = "" + e.getKey().trim().replaceAll("\\s+", " ");
      final NonNullPair<String, Integer> g = Noun.stripGender(s, "" + e.getKey());
      final NonNullPair<String, String> p = Noun.getPlural(g.getFirst());
      final String lcs = p.getFirst().toLowerCase();
      final String lcp = p.getSecond().toLowerCase();
      if (numberWordPattern.matcher(lcs).matches() || numberWordPattern.matcher(lcp).matches()) {
        if (!printedStartingWithNumberError) {
          Skript.error(m_starting_with_number.toString());
          printedStartingWithNumberError = true;
        }
        continue;
      }
//      if (lc.contains(",") || lc.contains(" and ") || lc.contains(" or ")) {
//        if (!printedSyntaxError) {
//          Skript.error("aliases must not contain syntax elements (comma, 'and', 'or')");
//          printedSyntaxError = true;
//        }
//        continue;
//      }
      boolean b;
      final ItemType alias;
      if ((b = lcs.endsWith(itemSingular)) || lcp.endsWith(itemPlural)) {
        String m = b ? lcs.substring(0, lcs.length() - itemSingular.length()) : lcp.substring(0, lcp.length() - itemPlural.length());
        if (m.endsWith(" ") || m.endsWith("-"))
          m = m.substring(0, m.length() - 1);
        final ItemType si = aliases.get(m);
        if (si != null)
          si.setItem(e.getValue());
        alias = e.getValue();
      } else if ((b = lcs.endsWith(blockSingular)) || lcp.endsWith(blockPlural)) {
        String m = b ? lcs.substring(0, lcs.length() - blockSingular.length()) : lcp.substring(0, lcp.length() - blockPlural.length());
        if (m.endsWith(" ") || m.endsWith("-"))
          m = m.substring(0, m.length() - 1);
        final ItemType si = aliases.get(m);
        if (si != null)
          si.setBlock(e.getValue());
        alias = e.getValue();
      } else {
        final ItemType[] ib = new ItemType[2];
        final String[] ibs = {itemSingular, blockSingular};
        final String[] seps = {" ", "", "-"};
        for (int i = 0; i < ib.length; i++) {
          for (final String sep : seps) {
            ib[i] = aliases.get(lcs + sep + ibs[i]);
            if (ib[i] != null)
              break;
          }
        }
        if (ib[0] == null && ib[1] == null) {
          alias = e.getValue();
        } else {
          alias = e.getValue().clone();
          alias.setItem(ib[0]);
          alias.setBlock(ib[1]);
        }
      }
      aliases.put(lcs, alias);
      aliases.put(lcp, alias);
     
      //if (logSpam()) // over 10k aliases in the default aliases.sk as of MC 1.5
      //  info("added alias " + s + " for " + e.getValue());
     
      final HashMap<Integer, MaterialName> materialNames = getMaterialNames();
     
      if (alias.getTypes().size() == 1) {
        final ItemData d = alias.getTypes().get(0);
        MaterialName n = materialNames.get(Integer.valueOf(d.getId()));
        if (d.dataMin == -1 && d.dataMax == -1) {
          if (n != null) {
            if (n.singular.equals("" + d.getId()) && n.singular.equals(n.plural)) {
              n.singular = p.getFirst();
              n.plural = p.getSecond();
            }
          } else {
            materialNames.put(Integer.valueOf(d.getId()), new MaterialName(d.getId(), p.getFirst(), p.getSecond(), g.getSecond()));
          }
        } else {
          if (n == null)
            materialNames.put(Integer.valueOf(d.getId()), n = new MaterialName(d.getId(), "" + d.getId(), "" + d.getId(), g.getSecond()));
          @SuppressWarnings("null")
          final NonNullPair<Short, Short> data = new NonNullPair<Short, Short>(Short.valueOf(d.dataMin), Short.valueOf(d.dataMax));
          n.names.put(data, p);
        }
      }
    }
    return as.size();
  }
 
  /**
   * Gets the custom name of of a material, or the default if none is set.
   *
   * @param id
   * @param data
   * @return The material's name
   */
  public final static String getMaterialName(final int id, final short data, final boolean plural) {
    return getMaterialName(id, data, data, plural);
  }
 
  public final static String getDebugMaterialName(final int id, final short data, final boolean plural) {
    return getDebugMaterialName(id, data, data, plural);
  }
 
  public final static String getMaterialName(final int id, final short dataMin, final short dataMax, final boolean plural) {
    final MaterialName n = getMaterialNames().get(Integer.valueOf(id));
    if (n == null) {
      return "" + id;
    }
    return n.toString(dataMin, dataMax, plural);
  }
 
  public final static String getDebugMaterialName(final int id, final short dataMin, final short dataMax, final boolean plural) {
    final MaterialName n = getMaterialNames().get(Integer.valueOf(id));
    if (n == null) {
      return "" + id + ":" + dataMin + (dataMax == dataMin ? "" : "-" + dataMax);
    }
    return n.getDebugName(dataMin, dataMax, plural);
  }
 
  /**
   * @return The ietm's gender or -1 if no name is found
   */
  public final static int getGender(final int id, final short dataMin, final short dataMax) {
    final MaterialName n = getMaterialNames().get(Integer.valueOf(id));
    if (n != null)
      return n.gender;
    return -1;
  }
 
  /**
   * @return how many ids are missing an alias, including the 'any id' (-1)
   */
  final static int addMissingMaterialNames() {
    final HashMap<Integer, MaterialName> materialNames = getMaterialNames();
    int r = 0;
    final StringBuilder missing = new StringBuilder(m_missing_aliases + " ");
    for (final Material m : Material.values()) {
      if (materialNames.get(Integer.valueOf(m.getId())) == null) {
        materialNames.put(Integer.valueOf(m.getId()), new MaterialName(m.getId(), "" + m.toString().toLowerCase().replace('_', ' '), "" + m.toString().toLowerCase().replace('_', ' '), 0));
        missing.append(m.getId() + ", ");
        r++;
      }
    }
    final MaterialName m = materialNames.get(Integer.valueOf(-1));
    if (m == null) {
      materialNames.put(Integer.valueOf(-1), new MaterialName(-1, Language.get("aliases.anything"), Language.get("aliases.anything"), 0));
      missing.append("<any>, ");
      r++;
    }
    if (r > 0)
      Skript.warning("" + missing.substring(0, missing.length() - 2));
    return r;
  }
 
  /**
   * Parses an ItemType to be used as an alias, i.e. it doesn't parse 'all'/'every' and the amount.
   *
   * @param s mixed case string
   * @return A new ItemType representing the given value
   */
  @Nullable
  public static ItemType parseAlias(final String s) {
    if (s.isEmpty()) {
      Skript.error(m_empty_string.toString());
      return null;
    }
    if (s.equals("*"))
      return everything;
   
    final ItemType t = new ItemType();
   
    final String[] types = s.split("\\s*,\\s*");
    for (final String type : types) {
      if (type == null || parseType(type, t, true) == null)
        return null;
    }
   
    return t;
  }
 
  private final static RegexMessage p_any = new RegexMessage("aliases.any", "", " (.+)", Pattern.CASE_INSENSITIVE);
  private final static Message m_any = new Message("aliases.any-skp");
  private final static RegexMessage p_every = new RegexMessage("aliases.every", "", " (.+)", Pattern.CASE_INSENSITIVE);
  private final static RegexMessage p_of_every = new RegexMessage("aliases.of every", "(\\d+) ", " (.+)", Pattern.CASE_INSENSITIVE);
  private final static RegexMessage p_of = new RegexMessage("aliases.of", "(\\d+) (?:", " )?(.+)", Pattern.CASE_INSENSITIVE);
 
  /**
   * Parses an ItemType.
   * <p>
   * Prints errors.
   *
   * @param s
   * @return The parsed ItemType or null if the input is invalid.
   */
  @Nullable
  public static ItemType parseItemType(String s) {
    if (s.isEmpty())
      return null;
    s = "" + s.trim();
   
    final ItemType t = new ItemType();
   
    Matcher m;
    if ((m = p_of_every.matcher(s)).matches()) {
      t.setAmount(Utils.parseInt("" + m.group(1)));
      t.setAll(true);
      s = "" + m.group(m.groupCount());
    } else if ((m = p_of.matcher(s)).matches()) {
      t.setAmount(Utils.parseInt("" + m.group(1)));
      s = "" + m.group(m.groupCount());
    } else if ((m = p_every.matcher(s)).matches()) {
      t.setAll(true);
      s = "" + m.group(m.groupCount());
    } else {
      final int l = s.length();
      s = Noun.stripIndefiniteArticle(s);
      if (s.length() != l) // had indefinite article
        t.setAmount(1);
    }
   
    final String lc = s.toLowerCase();
    final String of = Language.getSpaced("enchantments.of").toLowerCase();
    int c = -1;
    outer: while ((c = lc.indexOf(of, c + 1)) != -1) {
      final ItemType t2 = t.clone();
      final BlockingLogHandler log = SkriptLogger.startLogHandler(new BlockingLogHandler());
      try {
        if (parseType("" + s.substring(0, c), t2, false) == null)
          continue;
      } finally {
        log.stop();
      }
      if (t2.numTypes() == 0)
        continue;
      final Map<Enchantment, Integer> enchantments = new HashMap<Enchantment, Integer>();
      final String[] enchs = lc.substring(c + of.length(), lc.length()).split("\\s*(,|" + Pattern.quote(Language.get("and")) + ")\\s*");
      for (final String ench : enchs) {
        final EnchantmentType e = EnchantmentType.parse("" + ench);
        if (e == null)
          continue outer;
        enchantments.put(e.getType(), e.getLevel());
      }
      t2.addEnchantments(enchantments);
      return t2;
    }
   
    if (parseType(s, t, false) == null)
      return null;
   
    if (t.numTypes() == 0)
      return null;
   
    return t;
  }
 
  /**
   * Prints errors.
   *
   * @param s The string holding the type, can be either a number or an alias, plus an optional data part. Case does not matter.
   * @param t The ItemType to add the parsed ItemData(s) to (i.e. this ItemType will be modified)
   * @param isAlias Whether this type is parsed for an alias.
   * @return The given item type or null if the input couldn't be parsed.
   */
  @Nullable
  private final static ItemType parseType(final String s, final ItemType t, final boolean isAlias) {
    ItemType i;
    int c = s.indexOf(':');
    if (c == -1)
      c = s.length();
    final String type = s.substring(0, c);
    ItemData data = null;
    if (c != s.length()) {
      data = parseData("" + s.substring(c + 1));
      if (data == null) {
        Skript.error(m_invalid_item_data.toString(s.substring(c)));
        return null;
      }
    }
    if (type.isEmpty()) {
      t.add(data == null ? new ItemData() : data);
      return t;
    } else if (type.matches("\\d+")) {
      ItemData d = new ItemData(Utils.parseInt(type));
      if (Material.getMaterial(d.getId()) == null) {
        Skript.error(m_invalid_id.toString(d.getId()));
        return null;
      }
      if (data != null) {
        if (d.getId() <= Skript.MAXBLOCKID && (data.dataMax > 15 || data.dataMin > 15)) {
          Skript.error(m_invalid_block_data.toString());
          return null;
        }
        d = d.intersection(data);
      }
      if (!isAlias && d != null) {
        Skript.warning("Using an ID instead of an alias is discouraged and will likely not be supported in future versions of Skript anymore. " +
            (d.toString().equals(type) ?
                "Please crate an alias for '" + type + (type.equals(s) ? "" : " or '" + s + "'") + "' (" + Material.getMaterial(d.getId()).name() + ") in aliases-english.sk or the script's aliases section and use that instead." :
                "Please replace '" + s + "' with e.g. '" + d.toString(true, false) + "'."));
      }
      t.add(d);
      return t;
    } else if ((i = getAlias(type)) != null) {
      for (ItemData d : i) {
        if (data != null) {
          if (d.getId() <= Skript.MAXBLOCKID && (data.dataMax > 15 || data.dataMin > 15)) {
            Skript.error(m_invalid_block_data.toString());
            return null;
          }
          d = d.intersection(data);
        } else {
          d = d.clone();
        }
        t.add(d);
      }
      if (data == null) {
        if (i.getItem() != i)
          t.setItem(i.getItem().clone());
        if (i.getBlock() != i)
          t.setBlock(i.getBlock().clone());
      }
      return t;
    }
    if (isAlias)
      Skript.error(m_invalid_item_type.toString(s));
    return null;
  }
 
  /**
   * Gets an alias from the aliases defined in the config.
   *
   * @param s The alias to get, case does not matter
   * @return A copy of the ItemType represented by the given alias or null if no such alias exists.
   */
  @Nullable
  private final static ItemType getAlias(final String s) {
    ItemType i;
    String lc = "" + s.toLowerCase();
    final Matcher m = p_any.matcher(lc);
    if (m.matches()) {
      lc = "" + m.group(m.groupCount());
    }
    if ((i = getAlias_i(lc)) != null)
      return i.clone();
    boolean b;
    if ((b = lc.endsWith(" " + blockSingular)) || lc.endsWith(" " + blockPlural)) {
      if ((i = getAlias_i("" + s.substring(0, s.length() - (b ? blockSingular.length() : blockPlural.length()) - 1))) != null) {
        i = i.clone();
        for (int j = 0; j < i.numTypes(); j++) {
          final ItemData d = i.getTypes().get(j);
          if (d.getId() > Skript.MAXBLOCKID) {
            i.remove(d);
            j--;
          }
        }
        if (i.getTypes().isEmpty())
          return null;
        return i;
      }
    } else if ((b = lc.endsWith(" " + itemSingular)) || lc.endsWith(" " + itemPlural)) {
      if ((i = getAlias_i("" + s.substring(0, s.length() - (b ? itemSingular.length() : itemPlural.length()) - 1))) != null) {
        for (int j = 0; j < i.numTypes(); j++) {
          final ItemData d = i.getTypes().get(j);
          if (d.getId() != -1 && d.getId() <= Skript.MAXBLOCKID) {
            i.remove(d);
            j--;
          }
        }
        if (i.getTypes().isEmpty())
          return null;
        return i;
      }
    }
    return null;
  }
 
  /**
   * Gets the data part of an item data
   *
   * @param s Everything after ':'
   * @return ItemData with only the dataMin and dataMax set
   */
  @Nullable
  private final static ItemData parseData(final String s) {
    if (s.isEmpty())
      return new ItemData();
    if (!s.matches("\\d+(-\\d+)?"))
      return null;
    final ItemData t = new ItemData();
    int i = s.indexOf('-');
    if (i == -1)
      i = s.length();
    try {
      t.dataMin = Short.parseShort(s.substring(0, i));
      t.dataMax = (i == s.length() ? t.dataMin : Short.parseShort(s.substring(i + 1, s.length())));
    } catch (final NumberFormatException e) { // overflow
      Skript.error(m_out_of_data_range.toString(Short.MAX_VALUE));
      return null;
    }
    if (t.dataMin > t.dataMax) {
      Skript.error(m_invalid_range.toString());
      return null;
    }
    return t;
  }
 
  public static void clear() {
    aliases_english.clear();
    aliases_localised.clear();
    materialNames_english.clear();
    materialNames_localised.clear();
  }
 
  public static void load() {
   
    final boolean wasLocal = Language.isUsingLocal();
    try {
      for (int l = 0; l < 2; l++) {
        Language.setUseLocal(l == 1);
        if (l == 1 && !Language.isUsingLocal())
          break;
       
        final Config aliasConfig;
        try {
          final File file = new File(Skript.getInstance().getDataFolder(), "aliases-" + Language.getName() + ".sk");
          if (!file.exists()) {
            Skript.error("Could not find the " + Language.getName() + " aliases file " + file.getName());
          }
          aliasConfig = new Config(file, false, true, "=");
        } catch (final IOException e) {
          Skript.error("Could not load the " + Language.getName() + " aliases config: " + e.getLocalizedMessage());
          return;
        }
       
        final ArrayList<String> aliasNodes = new ArrayList<String>();
       
        aliasConfig.validate(
            new SectionValidator()
                .addEntry("aliases", new Setter<String>() {
                  @Override
                  public void set(final String s) {
                    for (final String n : s.split(","))
                      aliasNodes.add(n.trim());
                  }
                }, false)
                .addEntry("item", new Setter<String>() {
                  @Override
                  public void set(final String s) {
                    final NonNullPair<String, Integer> g = Noun.stripGender(s, "item");
                    itemGender = Noun.getGenderID(g.getSecond());
                    final NonNullPair<String, String> p = Noun.getPlural(g.getFirst());
                    itemSingular = "" + p.getFirst().toLowerCase();
                    itemPlural = "" + p.getSecond().toLowerCase();
                  }
                }, false)
                .addEntry("block", new Setter<String>() {
                  @Override
                  public void set(final String s) {
                    final NonNullPair<String, Integer> g = Noun.stripGender(s, "block");
                    blockGender = Noun.getGenderID(g.getSecond());
                    final NonNullPair<String, String> p = Noun.getPlural(g.getFirst());
                    blockSingular = "" + p.getFirst().toLowerCase();
                    blockPlural = "" + p.getSecond().toLowerCase();
                  }
                }, false)
                .setAllowUndefinedSections(true));
       
        for (final Node node : aliasConfig.getMainNode()) {
          if (node instanceof SectionNode) {
            if (!aliasNodes.contains(node.getKey())) {
              Skript.error(m_invalid_section.toString(node.getKey()));
            }
          }
        }
       
        final Variations variations = new Variations();
        int num = 0;
        for (final String an : aliasNodes) {
          final Node node = aliasConfig.getMainNode().get(an);
          SkriptLogger.setNode(node);
          if (node == null) {
            Skript.error(m_section_not_found.toString(an));
            continue;
          }
          if (!(node instanceof SectionNode)) {
            Skript.error(m_not_a_section.toString(an));
            continue;
          }
          int i = 0;
          for (final Node n : (SectionNode) node) {
            if (n instanceof EntryNode) {
              i += addAliases(((EntryNode) n).getKey(), ((EntryNode) n).getValue(), variations);
            } else if (n instanceof SectionNode) {
              final String key = n.getKey();
              if (key == null) {
                assert false;
                continue;
              }
              if (!(key.startsWith("{") && key.endsWith("}"))) {
                Skript.error(m_unexpected_non_variation_section.toString());
                continue;
              }
              final HashMap<String, ItemType> vs = new HashMap<String, ItemType>();
              for (final Node a : (SectionNode) n) {
                if (a instanceof SectionNode) {
                  Skript.error(m_unexpected_section.toString());
                  continue;
                } else if (!(a instanceof EntryNode)) {
                  continue;
                }
                final boolean noDefault = ((EntryNode) a).getValue().isEmpty() && ((EntryNode) a).getKey().equalsIgnoreCase("{default}");
                final ItemType t = noDefault ? null : parseAlias(((EntryNode) a).getValue());
                if (t != null || noDefault)
                  vs.put(Noun.normalizePluralMarkers(((EntryNode) a).getKey()), t);
              }
              variations.put(key.substring(1, key.length() - 1), vs);
            }
          }
          if (Skript.logVeryHigh())
            Skript.info(m_loaded_x_aliases_from.toString(i, node.getKey()));
          num += i;
        }
        SkriptLogger.setNode(null);
       
        if (Skript.logNormal())
          Skript.info(m_loaded_x_aliases.toString(num));
       
        addMissingMaterialNames();
       
//      if (!SkriptConfig.keepConfigsLoaded.value())
//        aliasConfig = null;
       
      }
    } finally {
      Language.setUseLocal(wasLocal);
    }
   
  }
 
}
TOP

Related Classes of ch.njol.skript.aliases.Aliases$Variations

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.