Add aliases to some config nodes, optionally read lists as actual YAML lists

This commit is contained in:
filoghost 2020-05-29 23:30:58 +02:00
parent 0ef4b0b2cc
commit 9752899f9a
6 changed files with 257 additions and 136 deletions

View File

@ -0,0 +1,92 @@
/*
* This program 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.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.gmail.filoghost.chestcommands.config;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import org.bukkit.configuration.ConfigurationSection;
import com.gmail.filoghost.chestcommands.util.Utils;
public class ConfigUtil {
public static String getAnyString(ConfigurationSection config, String... paths) {
for (String path : paths) {
String value = config.getString(path);
if (value != null) {
return value;
}
}
return null;
}
public static Integer getAnyInt(ConfigurationSection config, String... paths) {
for (String path : paths) {
if (config.isSet(path)) {
return config.getInt(path);
}
}
return null;
}
public static List<String> getStringListOrInlineList(ConfigurationSection config, String separator, String... paths) {
for (String path : paths) {
if (config.isSet(path)) {
if (config.isList(path)) {
return config.getStringList(path);
} else {
return getSeparatedValues(config.getString(path), separator);
}
}
}
return null;
}
public static List<String> getStringListOrSingle(ConfigurationSection config, String... paths) {
for (String path : paths) {
if (config.isSet(path)) {
if (config.isList(path)) {
return config.getStringList(path);
} else {
return Collections.singletonList(config.getString(path));
}
}
}
return null;
}
public static List<String> getSeparatedValues(String input, String separator) {
if (separator == null || separator.length() == 0) {
separator = ";";
}
String[] splitValues = input.split(Pattern.quote(separator));
List<String> values = Utils.newArrayList();
for (String value : splitValues) {
String trimmedValue = value.trim();
if (!trimmedValue.isEmpty()) {
values.add(trimmedValue);
}
}
return values;
}
}

View File

@ -14,13 +14,11 @@
*/
package com.gmail.filoghost.chestcommands.serializer;
import com.gmail.filoghost.chestcommands.ChestCommands;
import com.gmail.filoghost.chestcommands.internal.icon.IconCommand;
import com.gmail.filoghost.chestcommands.internal.icon.command.*;
import com.gmail.filoghost.chestcommands.util.ErrorLogger;
import com.gmail.filoghost.chestcommands.util.Utils;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
@ -58,26 +56,7 @@ public class CommandSerializer {
}
}
}
public static List<IconCommand> readCommands(String input) {
String separator = ChestCommands.getSettings().multiple_commands_separator;
if (separator == null || separator.length() == 0) {
separator = ";";
}
String[] split = input.split(Pattern.quote(separator));
List<IconCommand> iconCommands = Utils.newArrayList();
for (String command : split) {
String trim = command.trim();
if (trim.length() > 0) {
iconCommands.add(matchCommand(trim));
}
}
return iconCommands;
}
public static IconCommand matchCommand(String input) {

View File

@ -63,38 +63,29 @@ public class EnchantmentSerializer {
return StringUtils.stripChars(string, " _-").toLowerCase();
}
public static Map<Enchantment, Integer> loadEnchantments(String input, String iconName, String menuFileName, ErrorLogger errorLogger) {
Map<Enchantment, Integer> output = new HashMap<Enchantment, Integer>();
public static EnchantmentDetails parseEnchantment(String input, String iconName, String menuFileName, ErrorLogger errorLogger) {
int level = 1;
if (input == null || input.isEmpty()) {
return output;
if (input.contains(",")) {
String[] levelSplit = input.split(",");
try {
level = Integer.parseInt(levelSplit[1].trim());
} catch (NumberFormatException ex) {
errorLogger.addError("The icon \"" + iconName + "\" in the menu \"" + menuFileName + "\" has an invalid enchantment level: " + levelSplit[1]);
}
input = levelSplit[0];
}
for (String singleEnchant : input.split(";")) {
Enchantment ench = matchEnchantment(input);
int level = 1;
if (singleEnchant.contains(",")) {
String[] levelSplit = singleEnchant.split(",");
try {
level = Integer.parseInt(levelSplit[1].trim());
} catch (NumberFormatException ex) {
errorLogger.addError("The icon \"" + iconName + "\" in the menu \"" + menuFileName + "\" has an invalid enchantment level: " + levelSplit[1]);
}
singleEnchant = levelSplit[0];
}
Enchantment ench = matchEnchantment(singleEnchant);
if (ench == null) {
errorLogger.addError("The icon \"" + iconName + "\" in the menu \"" + menuFileName + "\" has an invalid enchantment: " + singleEnchant);
} else {
output.put(ench, level);
}
if (ench == null) {
errorLogger.addError("The icon \"" + iconName + "\" in the menu \"" + menuFileName + "\" has an invalid enchantment: " + input);
} else {
return new EnchantmentDetails(ench, level);
}
return output;
return null;
}
public static Enchantment matchEnchantment(String input) {
@ -104,5 +95,26 @@ public class EnchantmentSerializer {
return enchantmentsMap.get(formatLowercase(input));
}
public static class EnchantmentDetails {
private final Enchantment enchantment;
private final int level;
public EnchantmentDetails(Enchantment enchantment, int level) {
this.enchantment = enchantment;
this.level = level;
}
public Enchantment getEnchantment() {
return enchantment;
}
public int getLevel() {
return level;
}
}
}

View File

@ -14,49 +14,56 @@
*/
package com.gmail.filoghost.chestcommands.serializer;
import java.util.List;
import java.util.Map;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.enchantments.Enchantment;
import com.gmail.filoghost.chestcommands.ChestCommands;
import com.gmail.filoghost.chestcommands.api.Icon;
import com.gmail.filoghost.chestcommands.config.AsciiPlaceholders;
import com.gmail.filoghost.chestcommands.config.ConfigUtil;
import com.gmail.filoghost.chestcommands.exception.FormatException;
import com.gmail.filoghost.chestcommands.internal.CommandsClickHandler;
import com.gmail.filoghost.chestcommands.internal.RequiredItem;
import com.gmail.filoghost.chestcommands.internal.icon.ExtendedIcon;
import com.gmail.filoghost.chestcommands.internal.icon.IconCommand;
import com.gmail.filoghost.chestcommands.util.*;
import com.gmail.filoghost.chestcommands.serializer.EnchantmentSerializer.EnchantmentDetails;
import com.gmail.filoghost.chestcommands.util.ErrorLogger;
import com.gmail.filoghost.chestcommands.util.FormatUtils;
import com.gmail.filoghost.chestcommands.util.ItemStackReader;
import com.gmail.filoghost.chestcommands.util.ItemUtils;
import com.gmail.filoghost.chestcommands.util.Utils;
import com.gmail.filoghost.chestcommands.util.Validate;
import com.gmail.filoghost.chestcommands.util.nbt.parser.MojangsonParseException;
import com.gmail.filoghost.chestcommands.util.nbt.parser.MojangsonParser;
import org.bukkit.configuration.ConfigurationSection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class IconSerializer {
private static class Nodes {
public static final String
ID = "ID",
AMOUNT = "AMOUNT",
DATA_VALUE = "DATA-VALUE",
DURABILITY = "DURABILITY",
NBT_DATA = "NBT-DATA",
NAME = "NAME",
LORE = "LORE",
ENCHANT = "ENCHANTMENT",
COLOR = "COLOR",
SKULL_OWNER = "SKULL-OWNER",
BANNER_COLOR = "BANNER-COLOUR",
BANNER_PATTERNS = "BANNER-PATTERNS",
COMMAND = "COMMAND",
PRICE = "PRICE",
EXP_LEVELS = "LEVELS",
REQUIRED_ITEM = "REQUIRED-ITEM",
PERMISSION = "PERMISSION",
PERMISSION_MESSAGE = "PERMISSION-MESSAGE",
VIEW_PERMISSION = "VIEW-PERMISSION",
KEEP_OPEN = "KEEP-OPEN",
POSITION_X = "POSITION-X",
POSITION_Y = "POSITION-Y";
public static final String[] MATERIAL = {"MATERIAL", "ID"};
public static final String AMOUNT = "AMOUNT";
public static final String[] DURABILITY = {"DURABILITY", "DATA-VALUE"};
public static final String[] NBT_DATA = {"NBT-DATA", "NBT"};
public static final String NAME = "NAME";
public static final String LORE = "LORE";
public static final String[] ENCHANTMENTS = {"ENCHANTMENTS", "ENCHANTMENT"};
public static final String COLOR = "COLOR";
public static final String SKULL_OWNER = "SKULL-OWNER";
public static final String BANNER_COLOR = "BANNER-COLOR";
public static final String BANNER_PATTERNS = "BANNER-PATTERNS";
public static final String[] ACTIONS = {"ACTIONS", "COMMAND"};
public static final String PRICE = "PRICE";
public static final String EXP_LEVELS = "LEVELS";
public static final String[] REQUIRED_ITEMS = {"REQUIRED-ITEMS", "REQUIRED-ITEM"};
public static final String PERMISSION = "PERMISSION";
public static final String PERMISSION_MESSAGE = "PERMISSION-MESSAGE";
public static final String VIEW_PERMISSION = "VIEW-PERMISSION";
public static final String KEEP_OPEN = "KEEP-OPEN";
public static final String POSITION_X = "POSITION-X";
public static final String POSITION_Y = "POSITION-Y";
}
public static class Coords {
@ -92,9 +99,10 @@ public class IconSerializer {
// The icon is valid even without a Material
ExtendedIcon icon = new ExtendedIcon();
if (section.isSet(Nodes.ID)) {
String material = ConfigUtil.getAnyString(section, Nodes.MATERIAL);
if (material != null) {
try {
ItemStackReader itemReader = new ItemStackReader(section.getString(Nodes.ID), true);
ItemStackReader itemReader = new ItemStackReader(material, true);
icon.setMaterial(itemReader.getMaterial());
icon.setDataValue(itemReader.getDataValue());
icon.setAmount(itemReader.getAmount());
@ -106,15 +114,14 @@ public class IconSerializer {
if (section.isSet(Nodes.AMOUNT)) {
icon.setAmount(section.getInt(Nodes.AMOUNT));
}
if (section.isSet(Nodes.DURABILITY)) {
icon.setDataValue((short) section.getInt(Nodes.DURABILITY));
} else if (section.isSet(Nodes.DATA_VALUE)) { // Alias
icon.setDataValue((short) section.getInt(Nodes.DATA_VALUE));
Integer durability = ConfigUtil.getAnyInt(section, Nodes.DURABILITY);
if (durability != null) {
icon.setDataValue(durability.shortValue());
}
if (section.isSet(Nodes.NBT_DATA)) {
String nbtData = section.getString(Nodes.NBT_DATA);
String nbtData = ConfigUtil.getAnyString(section, Nodes.NBT_DATA);
if (nbtData != null) {
try {
// Check that NBT has valid syntax before applying it to the icon
MojangsonParser.parse(nbtData);
@ -127,8 +134,23 @@ public class IconSerializer {
icon.setName(AsciiPlaceholders.placeholdersToSymbols(FormatUtils.colorizeName(section.getString(Nodes.NAME))));
icon.setLore(AsciiPlaceholders.placeholdersToSymbols(FormatUtils.colorizeLore(section.getStringList(Nodes.LORE))));
if (section.isSet(Nodes.ENCHANT)) {
icon.setEnchantments(EnchantmentSerializer.loadEnchantments(section.getString(Nodes.ENCHANT), iconName, menuFileName, errorLogger));
List<String> serializedEnchantments = ConfigUtil.getStringListOrInlineList(section, ";", Nodes.ENCHANTMENTS);
if (serializedEnchantments != null && !serializedEnchantments.isEmpty()) {
Map<Enchantment, Integer> enchantments = Utils.newHashMap();
for (String serializedEnchantment : serializedEnchantments) {
if (serializedEnchantment != null && !serializedEnchantment.isEmpty()) {
EnchantmentDetails enchantment = EnchantmentSerializer.parseEnchantment(serializedEnchantment, iconName, menuFileName, errorLogger);
if (enchantment != null) {
enchantments.put(enchantment.getEnchantment(), enchantment.getLevel());
}
}
}
if (!enchantments.isEmpty()) {
icon.setEnchantments(enchantments);
}
}
if (section.isSet(Nodes.COLOR)) {
@ -141,11 +163,12 @@ public class IconSerializer {
icon.setSkullOwner(section.getString(Nodes.SKULL_OWNER));
if (section.isSet(Nodes.BANNER_COLOR)) {
String bannerColor = ConfigUtil.getAnyString(section, Nodes.BANNER_COLOR);
if (bannerColor != null) {
try {
icon.setBannerColor(ItemUtils.parseDyeColor(section.getString(Nodes.BANNER_COLOR)));
icon.setBannerColor(ItemUtils.parseDyeColor(bannerColor));
} catch (FormatException e) {
errorLogger.addError("The icon \"" + iconName + "\" in the menu \"" + menuFileName + "\" has an invalid BASE-COLOUR: " + e.getMessage());
errorLogger.addError("The icon \"" + iconName + "\" in the menu \"" + menuFileName + "\" has an invalid BANNER-COLOR: " + e.getMessage());
}
}
@ -153,7 +176,7 @@ public class IconSerializer {
try {
icon.setBannerPatterns(ItemUtils.parseBannerPatternList(section.getStringList(Nodes.BANNER_PATTERNS)));
} catch (FormatException e) {
errorLogger.addError("The icon \"" + iconName + "\" in the menu \"" + menuFileName + "\" has an invalid PATTERN-LIST: " + e.getMessage());
errorLogger.addError("The icon \"" + iconName + "\" in the menu \"" + menuFileName + "\" has an invalid BANNER-PATTERNS: " + e.getMessage());
}
}
@ -164,25 +187,20 @@ public class IconSerializer {
boolean closeOnClick = !section.getBoolean(Nodes.KEEP_OPEN);
icon.setCloseOnClick(closeOnClick);
if (section.isSet(Nodes.COMMAND)) {
List<IconCommand> commands;
if (section.isList(Nodes.COMMAND)) {
commands = Utils.newArrayList();
for (String commandString : section.getStringList(Nodes.COMMAND)) {
if (commandString.isEmpty()) {
continue;
}
commands.add(CommandSerializer.matchCommand(commandString));
List<String> serializedCommands = ConfigUtil.getStringListOrInlineList(section, ChestCommands.getSettings().multiple_commands_separator, Nodes.ACTIONS);
if (serializedCommands != null && !serializedCommands.isEmpty()) {
List<IconCommand> commands = Utils.newArrayList();
for (String serializedCommand : serializedCommands) {
if (serializedCommand != null && !serializedCommand.isEmpty()) {
commands.add(CommandSerializer.matchCommand(serializedCommand));
}
} else {
commands = CommandSerializer.readCommands(section.getString(Nodes.COMMAND));
}
icon.setClickHandler(new CommandsClickHandler(commands, closeOnClick));
if (!commands.isEmpty()) {
icon.setClickHandler(new CommandsClickHandler(commands, closeOnClick));
}
}
double price = section.getDouble(Nodes.PRICE);
@ -199,28 +217,27 @@ public class IconSerializer {
errorLogger.addError("The icon \"" + iconName + "\" in the menu \"" + menuFileName + "\" has negative LEVELS: " + levels);
}
if (section.isSet(Nodes.REQUIRED_ITEM)) {
List<String> requiredItemsStrings;
if (section.isList(Nodes.REQUIRED_ITEM)) {
requiredItemsStrings = section.getStringList(Nodes.REQUIRED_ITEM);
} else {
requiredItemsStrings = Collections.singletonList(section.getString(Nodes.REQUIRED_ITEM));
}
List<RequiredItem> requiredItems = new ArrayList<RequiredItem>();
for (String requiredItemText : requiredItemsStrings) {
List<String> serializedRequiredItems = ConfigUtil.getStringListOrSingle(section, Nodes.REQUIRED_ITEMS);
if (serializedRequiredItems != null && !serializedRequiredItems.isEmpty()) {
List<RequiredItem> requiredItems = Utils.newArrayList();
for (String serializedItem : serializedRequiredItems) {
try {
ItemStackReader itemReader = new ItemStackReader(requiredItemText, true);
ItemStackReader itemReader = new ItemStackReader(serializedItem, true);
RequiredItem requiredItem = new RequiredItem(itemReader.getMaterial(), itemReader.getAmount());
if (itemReader.hasExplicitDataValue()) {
requiredItem.setRestrictiveDataValue(itemReader.getDataValue());
}
requiredItems.add(requiredItem);
} catch (FormatException e) {
errorLogger.addError("The icon \"" + iconName + "\" in the menu \"" + menuFileName + "\" has an invalid REQUIRED-ITEM: " + e.getMessage());
errorLogger.addError("The icon \"" + iconName + "\" in the menu \"" + menuFileName + "\" has invalid REQUIRED-ITEMS: " + e.getMessage());
}
}
icon.setRequiredItems(requiredItems);
if (!requiredItems.isEmpty()) {
icon.setRequiredItems(requiredItems);
}
}
return icon;

View File

@ -14,18 +14,25 @@
*/
package com.gmail.filoghost.chestcommands.serializer;
import java.util.List;
import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
import com.gmail.filoghost.chestcommands.ChestCommands;
import com.gmail.filoghost.chestcommands.api.Icon;
import com.gmail.filoghost.chestcommands.config.ConfigUtil;
import com.gmail.filoghost.chestcommands.config.yaml.PluginConfig;
import com.gmail.filoghost.chestcommands.exception.FormatException;
import com.gmail.filoghost.chestcommands.internal.ExtendedIconMenu;
import com.gmail.filoghost.chestcommands.internal.MenuData;
import com.gmail.filoghost.chestcommands.internal.icon.IconCommand;
import com.gmail.filoghost.chestcommands.serializer.IconSerializer.Coords;
import com.gmail.filoghost.chestcommands.util.ClickType;
import com.gmail.filoghost.chestcommands.util.ErrorLogger;
import com.gmail.filoghost.chestcommands.util.FormatUtils;
import com.gmail.filoghost.chestcommands.util.ItemStackReader;
import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
import com.gmail.filoghost.chestcommands.util.Utils;
public class MenuSerializer {
@ -33,11 +40,11 @@ public class MenuSerializer {
public static final String MENU_NAME = "menu-settings.name";
public static final String MENU_ROWS = "menu-settings.rows";
public static final String MENU_COMMAND = "menu-settings.command";
public static final String[] MENU_COMMANDS = {"menu-settings.command", "menu-settings.commands"};
public static final String OPEN_ACTION = "menu-settings.open-action";
public static final String[] OPEN_ACTIONS = {"menu-settings.open-actions", "menu-settings.open-action"};
public static final String OPEN_ITEM_MATERIAL = "menu-settings.open-with-item.id";
public static final String[] OPEN_ITEM_MATERIAL = {"menu-settings.open-with-item.id", "menu-settings.open-with-item.material"};
public static final String OPEN_ITEM_LEFT_CLICK = "menu-settings.open-with-item.left-click";
public static final String OPEN_ITEM_RIGHT_CLICK = "menu-settings.open-with-item.right-click";
@ -103,25 +110,39 @@ public class MenuSerializer {
}
MenuData menuData = new MenuData(title, rows);
if (config.isSet(Nodes.MENU_COMMAND)) {
menuData.setCommands(config.getString(Nodes.MENU_COMMAND).replace(" ", "").split(";"));
List<String> triggeringCommands = ConfigUtil.getStringListOrInlineList(config, ";", Nodes.MENU_COMMANDS);
if (triggeringCommands != null) {
menuData.setCommands(triggeringCommands.toArray(new String[0]));
}
if (config.isSet(Nodes.OPEN_ACTION)) {
menuData.setOpenActions(CommandSerializer.readCommands(config.getString(Nodes.OPEN_ACTION)));
List<String> serializedOpenCommands = ConfigUtil.getStringListOrInlineList(config, ChestCommands.getSettings().multiple_commands_separator, Nodes.OPEN_ACTIONS);
if (serializedOpenCommands != null && !serializedOpenCommands.isEmpty()) {
List<IconCommand> openCommands = Utils.newArrayList();
for (String serializedCommand : serializedOpenCommands) {
if (serializedCommand != null && !serializedCommand.isEmpty()) {
openCommands.add(CommandSerializer.matchCommand(serializedCommand));
}
}
if (!openCommands.isEmpty()) {
menuData.setOpenActions(openCommands);
}
}
if (config.isSet(Nodes.OPEN_ITEM_MATERIAL)) {
String openItemMaterial = ConfigUtil.getAnyString(config, Nodes.OPEN_ITEM_MATERIAL);
if (openItemMaterial != null) {
try {
ItemStackReader itemReader = new ItemStackReader(config.getString(Nodes.OPEN_ITEM_MATERIAL), false);
ItemStackReader itemReader = new ItemStackReader(openItemMaterial, false);
menuData.setBoundMaterial(itemReader.getMaterial());
if (itemReader.hasExplicitDataValue()) {
menuData.setBoundDataValue(itemReader.getDataValue());
}
} catch (FormatException e) {
errorLogger.addError("The item \"" + config.getString(Nodes.OPEN_ITEM_MATERIAL) + "\" used to open the menu \"" + config.getFileName() + "\" is invalid: " + e.getMessage());
errorLogger.addError("The item \"" + openItemMaterial + "\" used to open the menu \"" + config.getFileName() + "\" is invalid: " + e.getMessage());
}
boolean leftClick = config.getBoolean(Nodes.OPEN_ITEM_LEFT_CLICK);

View File

@ -156,7 +156,7 @@ public final class ItemUtils {
try {
color = DyeColor.valueOf(input.toUpperCase());
} catch (IllegalArgumentException e) {
throw new FormatException("it must be a valid colour.");
throw new FormatException("it must be a valid color.");
}
return color;
}
@ -166,7 +166,7 @@ public final class ItemUtils {
for (String str : input) {
String[] split = str.split(":");
if (split.length != 2) {
throw new FormatException("it must be in the format \"pattern:colour\".");
throw new FormatException("it must be in the format \"pattern:color\".");
}
try {
patterns.add(new Pattern(parseDyeColor(split[1]), PatternType.valueOf(split[0].toUpperCase())));