Improve config handling

- Rewrote ConfigOption to take advantage of generics.
- Simplified config option management by getting rid of some code
duplication.
- No longer using Strings to get configuration values. This is both much
faster and less error-prone (when using any IDE worth its salt).
This commit is contained in:
Pim van der Loos 2019-04-30 20:41:12 +02:00
parent ecd0340cd6
commit 45486a7eea
No known key found for this signature in database
GPG Key ID: C16F020ADAE6D5A8
7 changed files with 216 additions and 222 deletions

View File

@ -31,21 +31,19 @@ public class ArmoredElytra extends JavaPlugin implements Listener
private String leatherName, ironName, goldName, chainName, diamondName;
private String elytraReceivedMessage;
private String usageDeniedMessage;
private boolean uninstallMode;
private String elytraLore;
private boolean upToDate;
private String locale;
private boolean is1_9;
@Override
public void onEnable()
{
readConfigValues();
config = new ConfigLoader(this);
messages = new Messages(this);
readMessages();
// Check if the user allows checking for updates.
if (config.getBool("checkForUpdates"))
if (config.checkForUpdates())
{
// Check for updates in a new thread, so the server won't hang when it cannot contact the update servers.
final Thread thread = new Thread(() ->
@ -81,7 +79,7 @@ public class ArmoredElytra extends JavaPlugin implements Listener
else
myLogger(Level.INFO, "Plugin update checking not enabled! You will not receive any messages about new updates for this plugin. Please consider turning this on in the config.");
if (config.getBool("allowStats"))
if (config.allowStats())
{
myLogger(Level.INFO, "Enabling stats! Thanks, it really helps!");
@SuppressWarnings("unused")
@ -106,10 +104,10 @@ public class ArmoredElytra extends JavaPlugin implements Listener
}
// Load the plugin normally if not in uninstall mode.
if (!uninstallMode)
if (!config.uninstallMode())
{
// Check if the user wants to disable durability penalty for flying with an armored elytra.
if (config.getBool("noFlightDurability"))
if (config.noFlightDurability())
{
Bukkit.getPluginManager().registerEvents(new FlyDurabilityHandler(nbtEditor), this);
myLogger(Level.INFO, "Durability penalty for flying disabled!");
@ -119,7 +117,7 @@ public class ArmoredElytra extends JavaPlugin implements Listener
// Log all allowed enchantments.
myLogger(Level.INFO, ("Allowed enchantments:"));
for (final String s : config.getStringList("allowedEnchantments"))
for (final String s : config.allowedEnchantments())
myLogger(Level.INFO, " - " + s);
}
else
@ -129,17 +127,6 @@ public class ArmoredElytra extends JavaPlugin implements Listener
}
}
public void readConfigValues()
{
// Load the settings from the config file.
config = new ConfigLoader(this);
// Check if the plugin should go into uninstall mode.
uninstallMode = config.getBool("uninstallMode");
locale = config.getString("languageFile");
}
public Messages getMyMessages()
{
return messages;
@ -220,15 +207,6 @@ public class ArmoredElytra extends JavaPlugin implements Listener
return string.replace("%ARMOR_TIER%", ChatColor.stripColor(getArmoredElytrName(armorTier)));
}
public String getLocale()
{
if (locale == null)
System.out.println("locale is null!");
else
System.out.println("Locale is " + locale);
return locale == null ? "en_US" : locale;
}
// Print a string to the log.
public void myLogger(Level level, String str)
{
@ -238,7 +216,7 @@ public class ArmoredElytra extends JavaPlugin implements Listener
// Log message that only gets printed when debugging is enabled in the config file.
public void debugMsg(Level level, String str)
{
if (config.getBool("enableDebug"))
if (config.enableDebug())
myLogger(level, str);
}
@ -291,9 +269,4 @@ public class ArmoredElytra extends JavaPlugin implements Listener
{
this.upToDate = upToDate;
}
public boolean getUninstallMode()
{
return uninstallMode;
}
}

View File

@ -35,7 +35,7 @@ public class CommandHandler implements CommandExecutor
{
player = (Player) sender;
if (plugin.getUninstallMode())
if (plugin.getConfigLoader().uninstallMode())
{
plugin.messagePlayer(player, plugin.getMyMessages().getString("MESSAGES.UninstallMode"));
return true;
@ -77,7 +77,7 @@ public class CommandHandler implements CommandExecutor
if (allowed)
{
plugin.elytraReceivedMessage(receiver, armorTier);
newElytra = nbtEditor.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier, plugin.getConfigLoader().getBool("unbreakable"));
newElytra = nbtEditor.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier, plugin.getConfigLoader().unbreakable());
plugin.giveArmoredElytraToPlayer(receiver, newElytra);
}
else
@ -87,7 +87,7 @@ public class CommandHandler implements CommandExecutor
}
else
{
if (plugin.getUninstallMode())
if (plugin.getConfigLoader().uninstallMode())
{
plugin.myLogger(Level.INFO, "Plugin in uninstall mode! New Armored Elytras are not allowed!");
return true;
@ -106,7 +106,7 @@ public class CommandHandler implements CommandExecutor
return false;
plugin.elytraReceivedMessage(player, armorTier);
newElytra = nbtEditor.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier, plugin.getConfigLoader().getBool("unbreakable"));
newElytra = nbtEditor.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier, plugin.getConfigLoader().unbreakable());
plugin.giveArmoredElytraToPlayer(player, newElytra);
plugin.myLogger(Level.INFO, ("Giving an armored elytra of the " + ArmorTier.getArmor(armorTier) + " armor tier to player " + player.getName()));
return true;

View File

@ -1,7 +1,6 @@
package nl.pim16aap2.armoredElytra.handlers;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.logging.Level;
@ -32,13 +31,8 @@ import nl.pim16aap2.armoredElytra.util.Util;
public class EventHandlers implements Listener
{
private final int DIAMONDS_TO_FULL;
private final int LEATHER_TO_FULL;
private final int GOLD_TO_FULL;
private final int IRON_TO_FULL;
private final NBTEditor nbtEditor;
private final ArmoredElytra plugin;
private final List<String> allowedEnchantments;
private final boolean is1_9;
public EventHandlers(ArmoredElytra plugin, NBTEditor nbtEditor, boolean is1_9)
@ -46,13 +40,6 @@ public class EventHandlers implements Listener
this.plugin = plugin;
this.nbtEditor = nbtEditor;
this.is1_9 = is1_9;
// Get the values of the config options.
allowedEnchantments = plugin.getConfigLoader().getStringList("allowedEnchantments");
LEATHER_TO_FULL = plugin.getConfigLoader().getInt("leatherRepair");
GOLD_TO_FULL = plugin.getConfigLoader().getInt("goldRepair");
IRON_TO_FULL = plugin.getConfigLoader().getInt("ironRepair");
DIAMONDS_TO_FULL = plugin.getConfigLoader().getInt("diamondsRepair");
}
// Remove item from player's chestplate slot and puts it in their normal inventory.
@ -89,7 +76,7 @@ public class EventHandlers implements Listener
// Check if the enchantment is allowed on elytras.
private boolean isAllowedEnchantment(Enchantment enchant)
{
for (String s : allowedEnchantments)
for (String s : plugin.getConfigLoader().allowedEnchantments())
if (Enchantment.getByName(s) != null)
if (Enchantment.getByName(s).equals(enchant))
return true;
@ -164,16 +151,16 @@ public class EventHandlers implements Listener
// Get the multiplier for the repair items.
double mult = 0.01;
if ( repairItem.getType() == Material.LEATHER)
mult *= (100 / LEATHER_TO_FULL);
mult *= (100.0f / plugin.getConfigLoader().LEATHER_TO_FULL());
else if (repairItem.getType() == Material.GOLD_INGOT)
mult *= (100 / GOLD_TO_FULL);
mult *= (100.0f / plugin.getConfigLoader().GOLD_TO_FULL());
else if (repairItem.getType() == Material.IRON_INGOT)
mult *= (100 / IRON_TO_FULL);
mult *= (100.0f / plugin.getConfigLoader().IRON_TO_FULL());
else if (repairItem.getType() == Material.DIAMOND)
mult *= (100 / DIAMONDS_TO_FULL);
mult *= (100.0f / plugin.getConfigLoader().DIAMONDS_TO_FULL());
int maxDurability = Material.ELYTRA.getMaxDurability();
int newDurability = (int) (curDur - (maxDurability * mult));
@ -330,7 +317,7 @@ public class EventHandlers implements Listener
result.addUnsafeEnchantments(enchantments);
result.setDurability(durability);
result = nbtEditor.addArmorNBTTags(result, newTier, plugin.getConfigLoader().getBool("unbreakable"));
result = nbtEditor.addArmorNBTTags(result, newTier, plugin.getConfigLoader().unbreakable());
event.setResult(result);
}
}
@ -379,7 +366,7 @@ public class EventHandlers implements Listener
{
// Create a new armored elytra and give that one to the player instead of the result.
// This is done because after putting item0 in AFTER item1, the first letter of the color code shows up, this gets rid of that problem.
ItemStack result = nbtEditor.addArmorNBTTags(anvilInventory.getItem(2), armortier, plugin.getConfigLoader().getBool("unbreakable"));
ItemStack result = nbtEditor.addArmorNBTTags(anvilInventory.getItem(2), armortier, plugin.getConfigLoader().unbreakable());
// Give the result to the player and clear the anvil's inventory.
if (e.isShiftClick())
{

View File

@ -5,6 +5,7 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
@ -15,6 +16,7 @@ import nl.pim16aap2.armoredElytra.ArmoredElytra;
public class ConfigLoader
{
private final String header;
private boolean allowStats;
private boolean unbreakable;
private boolean enableDebug;
@ -28,18 +30,19 @@ public class ConfigLoader
private boolean noFlightDurability;
private List<String> allowedEnchantments;
private ArrayList<ConfigOption> configOptionsList;
private ArrayList<ConfigOption<?>> configOptionsList;
private ArmoredElytra plugin;
public ConfigLoader(ArmoredElytra plugin)
{
this.plugin = plugin;
configOptionsList = new ArrayList<>();
header = "Config file for ArmoredElytra. Don't forget to make a backup before making changes!";
makeConfig();
}
// Read the current config, the make a new one based on the old one or default values, whichever is applicable.
public void makeConfig()
private void makeConfig()
{
// All the comments for the various config options.
String[] unbreakableComment =
@ -91,45 +94,38 @@ public class ConfigLoader
"Specify a language file to be used. Note that en_US.txt will get regenerated!"
};
// Set default list of allowed enchantments.
allowedEnchantments = new ArrayList<>(Arrays.asList("DURABILITY", "PROTECTION_FIRE", "PROTECTION_EXPLOSIONS",
"PROTECTION_PROJECTILE", "PROTECTION_ENVIRONMENTAL", "THORNS",
"BINDING_CURSE", "VANISHING_CURSE"));
FileConfiguration config = plugin.getConfig();
// Read all the options from the config, then put them in a configOption with their name, value and comment.
// THen put all configOptions into an ArrayList.
unbreakable = config.getBoolean ("unbreakable" , false);
configOptionsList.add(new ConfigOption ("unbreakable" , unbreakable , unbreakableComment ));
noFlightDurability = config.getBoolean ("noFlightDurability", false);
configOptionsList.add(new ConfigOption ("noFlightDurability", noFlightDurability, flyDurabilityComment));
LEATHER_TO_FULL = config.getInt ("leatherRepair" , 6);
configOptionsList.add(new ConfigOption ("leatherRepair" , LEATHER_TO_FULL, repairComment));
GOLD_TO_FULL = config.getInt ("goldRepair" , 5);
configOptionsList.add(new ConfigOption ("goldRepair" , GOLD_TO_FULL));
IRON_TO_FULL = config.getInt ("ironRepair" , 4);
configOptionsList.add(new ConfigOption ("ironRepair" , IRON_TO_FULL));
DIAMONDS_TO_FULL = config.getInt ("diamondsRepair", 3);
configOptionsList.add(new ConfigOption ("diamondsRepair", DIAMONDS_TO_FULL));
allowedEnchantments = config.getStringList("allowedEnchantments");
configOptionsList.add(new ConfigOption ("allowedEnchantments", allowedEnchantments, enchantmentsComment));
checkForUpdates = config.getBoolean ("checkForUpdates", true );
configOptionsList.add(new ConfigOption ("checkForUpdates", checkForUpdates, updateComment));
allowStats = config.getBoolean ("allowStats" , true );
configOptionsList.add(new ConfigOption ("allowStats" , allowStats, bStatsComment));
enableDebug = config.getBoolean ("enableDebug" , false);
configOptionsList.add(new ConfigOption ("enableDebug" , enableDebug, debugComment));
uninstallMode = config.getBoolean ("uninstallMode" , false);
configOptionsList.add(new ConfigOption ("uninstallMode" , uninstallMode, uninstallComment));
languageFile = config.getString ("languageFile" , "en_US");
configOptionsList.add(new ConfigOption ("languageFile" , languageFile, languageFileComment));
unbreakable = addNewConfigOption(config, "unbreakable", false, unbreakableComment);
noFlightDurability = addNewConfigOption(config, "noFlightDurability", false, flyDurabilityComment);
LEATHER_TO_FULL = addNewConfigOption(config, "leatherRepair", 6, repairComment);
GOLD_TO_FULL = addNewConfigOption(config, "goldRepair", 5, null);
IRON_TO_FULL = addNewConfigOption(config, "ironRepair", 4, null);
DIAMONDS_TO_FULL = addNewConfigOption(config, "diamondsRepair", 3, null);
allowedEnchantments = addNewConfigOption(config, "allowedEnchantments", allowedEnchantments, enchantmentsComment);
checkForUpdates = addNewConfigOption(config, "checkForUpdates", true, updateComment);
allowStats = addNewConfigOption(config, "allowStats", true, bStatsComment);
enableDebug = addNewConfigOption(config, "enableDebug", false, debugComment);
uninstallMode = addNewConfigOption(config, "uninstallMode", false, uninstallComment);
languageFile = addNewConfigOption(config, "languageFile", "en_US", languageFileComment);
writeConfig();
}
private <T> T addNewConfigOption(FileConfiguration config, String optionName, T defaultValue, String[] comment)
{
ConfigOption<T> option = new ConfigOption<>(plugin, config, optionName, defaultValue, comment);
configOptionsList.add(option);
return option.getValue();
}
// Write new config file.
public void writeConfig()
private void writeConfig()
{
// Write all the config options to the config.yml.
try
@ -149,8 +145,14 @@ public class ConfigLoader
FileWriter fw = new FileWriter(saveTo, true);
PrintWriter pw = new PrintWriter(fw);
for (ConfigOption configOption : configOptionsList)
pw.println(configOption.toString());
if (header != null)
pw.println("# " + header + "\n");
for (int idx = 0; idx < configOptionsList.size(); ++idx)
pw.println(configOptionsList.get(idx).toString() +
// Only print an additional newLine if the next config option has a comment.
(idx < configOptionsList.size() - 1 && configOptionsList.get(idx + 1).getComment() == null ? ""
: "\n"));
pw.flush();
pw.close();
@ -162,35 +164,64 @@ public class ConfigLoader
}
}
public Integer getInt(String path)
public boolean allowStats()
{
for (ConfigOption configOption : configOptionsList)
if (configOption.getName().equals(path))
return configOption.getInt();
return null;
return allowStats;
}
public Boolean getBool(String path)
public boolean unbreakable()
{
for (ConfigOption configOption : configOptionsList)
if (configOption.getName().equals(path))
return configOption.getBool();
return null;
return unbreakable;
}
public String getString(String path)
public boolean enableDebug()
{
for (ConfigOption configOption : configOptionsList)
if (configOption.getName().equals(path))
return configOption.getString();
return null;
return enableDebug;
}
public List<String> getStringList(String path)
public String languageFile()
{
for (ConfigOption configOption : configOptionsList)
if (configOption.getName().equals(path))
return configOption.getStringList();
return null;
return languageFile;
}
public int LEATHER_TO_FULL()
{
return LEATHER_TO_FULL;
}
public int GOLD_TO_FULL()
{
return GOLD_TO_FULL;
}
public int IRON_TO_FULL()
{
return IRON_TO_FULL;
}
public int DIAMONDS_TO_FULL()
{
return DIAMONDS_TO_FULL;
}
public boolean uninstallMode()
{
return uninstallMode;
}
public boolean checkForUpdates()
{
return checkForUpdates;
}
public boolean noFlightDurability()
{
return noFlightDurability;
}
public List<String> allowedEnchantments()
{
return allowedEnchantments;
}
}

View File

@ -2,104 +2,86 @@ package nl.pim16aap2.armoredElytra.util;
import java.util.List;
public class ConfigOption
{
private String optionName;
List<String> listVal = null;
private Integer intVal = null;
private Boolean boolVal = null;
private String stringVal = null;
private String[] comment;
import org.bukkit.configuration.file.FileConfiguration;
public ConfigOption(String optionName, int value, String[] comment)
import nl.pim16aap2.armoredElytra.ArmoredElytra;
/* This class represent a configuration option.
* The general format is: the comment followed by
* "<optionName>: <value>" on a new line for most options.
* For Lists, every option appears on a new line after a '-'.
*/
public class ConfigOption<V>
{
private final ArmoredElytra plugin;
private final FileConfiguration config;
private final String optionName;
private V value;
private final V defaultValue;
private final String[] comment;
public ConfigOption(ArmoredElytra plugin, FileConfiguration config, String optionName, V defaultValue, String[] comment)
{
this.plugin = plugin;
this.config = config;
this.optionName = optionName;
this.intVal = value;
this.defaultValue = defaultValue;
this.comment = comment;
setValue();
}
public ConfigOption(String optionName, int value)
@SuppressWarnings("unchecked")
private void setValue()
{
this.optionName = optionName;
this.intVal = value;
this.comment = null;
}
public ConfigOption(String optionName, boolean value, String[] comment)
try
{
this.optionName = optionName;
this.boolVal = value;
this.comment = comment;
value = (V) config.get(optionName, defaultValue);
}
public ConfigOption(String optionName, boolean value)
catch (Exception e)
{
this.optionName = optionName;
this.boolVal = value;
this.comment = null;
plugin.myLogger(java.util.logging.Level.WARNING, "Failed to read config value of: \"" + optionName + "\"! Using default value instead!");
plugin.myLogger(java.util.logging.Level.WARNING, Util.exceptionToString(e));
value = defaultValue;
}
}
public ConfigOption(String optionName, String value, String[] comment)
public V getValue()
{
this.optionName = optionName;
this.stringVal = value;
this.comment = comment;
return value;
}
public ConfigOption(String optionName, String value)
public String[] getComment()
{
this.optionName = optionName;
this.stringVal = value;
this.comment = null;
return comment;
}
public ConfigOption(String optionName, List<String> value, String[] comment)
{
this.optionName = optionName;
this.listVal = value;
this.comment = comment;
}
public ConfigOption(String optionName, List<String> value)
{
this.optionName = optionName;
this.listVal = value;
this.comment = null;
}
public String stringListToString()
{
String string = "";
for (String s : listVal)
string += " - " + s + "\n";
return string;
}
public String getName() { return optionName; }
public List<String> getStringList() { return listVal ; }
public int getInt() { return intVal ; }
public boolean getBool() { return boolVal ; }
public String getString() { return stringVal ; }
@Override
public String toString()
{
String string = "";
// Print the comments, if there are any.
if (comment != null)
{
string += "\n";
for (String comLine : comment)
// Prefix every line by a comment-sign (#).
string += "# " + comLine + "\n";
}
// Then add the name of the option followed by its value (if it is an int/bool/String/String[]).
string += optionName + ": " +
(intVal != null ? intVal :
boolVal != null ? boolVal :
stringVal != null ? "\'" + stringVal + "\'" :
listVal != null ? "\n" + stringListToString() : null);
string += optionName + ": ";
if (value.getClass().isAssignableFrom(String.class))
string += "\'" + value.toString() + "\'";
else if (value instanceof List<?>)
{
StringBuilder builder = new StringBuilder();
builder.append("\n");
int listSize = ((List<?>) value).size();
for (int index = 0; index < listSize; ++index)
builder.append(" - " + ((List<?>) value).get(index) + (index == listSize - 1 ? "" : "\n")); // Don't print newline at the end
string += builder.toString();
}
else
string += value.toString();
return string;
}
}

View File

@ -20,7 +20,12 @@ public class Messages
public Messages(ArmoredElytra plugin)
{
this.plugin = plugin;
textFile = new File(plugin.getDataFolder(), plugin.getLocale() + ".txt");
textFile = new File(plugin.getDataFolder(), plugin.getConfigLoader().languageFile() + ".txt");
if (!textFile.exists())
{
plugin.myLogger(Level.WARNING, "Failed to load language file: \"" + textFile + "\": File not found! Using default file instead!");
textFile = new File(plugin.getDataFolder(), "en_US.txt");
}
readFile();
}

View File

@ -1,5 +1,7 @@
package nl.pim16aap2.armoredElytra.util;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;
import org.bukkit.Material;
@ -9,6 +11,20 @@ import org.bukkit.inventory.ItemStack;
public class Util
{
public static String errorToString(Error e)
{
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
return sw.toString();
}
public static String exceptionToString(Exception e)
{
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
return sw.toString();
}
// Check if an item is broken or not.
public static boolean isBroken(ItemStack item)
{