/*
* 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);
}
}
}