package net.knarcraft.blacksmith.config; import net.citizensnpcs.api.util.DataKey; import net.citizensnpcs.api.util.YamlStorage; import net.knarcraft.blacksmith.BlacksmithPlugin; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.enchantments.Enchantment; import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; /** * A class which keeps track of all default NPC settings and all global settings */ public class GlobalSettings { private final Map materialBasePrices = new HashMap<>(); private final Map materialPricePerDurabilityPoints = new HashMap<>(); private final Map enchantmentModifiers = new HashMap<>(); private final Map defaultNPCSettings = new HashMap<>(); private final Map globalSettings = new HashMap<>(); private final YamlStorage defaultConfig; /** * Instantiates a new "Settings" * * @param plugin

A reference to the blacksmith plugin

*/ public GlobalSettings(BlacksmithPlugin plugin) { defaultConfig = new YamlStorage(new File(plugin.getDataFolder() + File.separator + "config.yml"), "Blacksmith Configuration\nWarning: The values under defaults are the values set for a blacksmith" + "upon creation. To change any values for existing NPCs, edit the citizens NPC file."); } /** * Loads all configuration values from the config file */ public void load() { //Load the config from disk defaultConfig.load(); DataKey root = defaultConfig.getKey(""); //Just in case, clear existing values defaultNPCSettings.clear(); globalSettings.clear(); materialBasePrices.clear(); materialPricePerDurabilityPoints.clear(); enchantmentModifiers.clear(); //Load/Save NPC default settings loadDefaultNPCSettings(root); //Load/Save global settings loadGlobalSettings(root); //Save any modified values to disk defaultConfig.save(); } /** * Gets the current value of the default NPC settings * * @return

The current value of the default NPC settings

*/ public Map getDefaultNPCSettings() { return new HashMap<>(this.defaultNPCSettings); } /** * Gets whether to use natural cost for cost calculation * *

Natural cost makes it more costly the more damage is dealt to an item. The alternative is the legacy behavior * where the amount of durability points remaining increases the cost.

* * @return

Whether to use natural cost

*/ public boolean getUseNaturalCost() { return asBoolean(GlobalSetting.NATURAL_COST); } /** * Gets the base price for the given material * * @param material

The material to get the base price for

* @return

The base price for the material

*/ public double getBasePrice(Material material) { if (materialBasePrices.containsKey(material) && materialBasePrices.get(material) != null) { return materialBasePrices.get(material); } else { return asDouble(GlobalSetting.BASE_PRICE); } } /** * Gets the price per durability point for the given material * * @param material

The material to get the durability point price for

* @return

The durability point price for the material

*/ public double getPricePerDurabilityPoint(Material material) { if (materialPricePerDurabilityPoints.containsKey(material) && materialPricePerDurabilityPoints.get(material) != null) { return materialPricePerDurabilityPoints.get(material); } else { return asDouble(GlobalSetting.PRICE_PER_DURABILITY_POINT); } } /** * Gets the cost to be added for each level of the given enchantment * * @param enchantment

The enchantment to get the cost for

* @return

The cost of each enchantment level

*/ public double getEnchantmentModifier(Enchantment enchantment) { if (enchantmentModifiers.containsKey(enchantment) && enchantmentModifiers.get(enchantment) != null) { return enchantmentModifiers.get(enchantment); } else { return asDouble(GlobalSetting.ENCHANTMENT_MODIFIER); } } /** * Gets the given value as a boolean * *

This will throw an exception if used for a non-boolean value

* * @param setting

The setting to get the value of

* @return

The value of the given setting as a boolean

*/ public boolean asBoolean(GlobalSetting setting) { Object value = getValue(setting); if (value instanceof String) { return Boolean.parseBoolean((String) value); } else { return (Boolean) value; } } /** * Gets the given value as a double * *

This will throw an exception if used for a non-double setting

* * @param setting

The setting to get the value of

* @return

The value of the given setting as a double

*/ public double asDouble(GlobalSetting setting) { Object value = getValue(setting); if (value instanceof String) { return Double.parseDouble((String) value); } else if (value instanceof Integer) { return (Integer) value; } else { return (Double) value; } } /** * Gets the value of a setting, using the default if not set * * @param setting

The setting to get the value of

* @return

The current value

*/ private Object getValue(GlobalSetting setting) { Object value = globalSettings.get(setting); //If not set in config.yml, use the default value from the enum if (value == null) { value = setting.getDefaultValue(); } return value; } /** * Loads all global settings * * @param root

The root node of all global settings

*/ private void loadGlobalSettings(DataKey root) { for (GlobalSetting globalSetting : GlobalSetting.values()) { if (!root.keyExists(globalSetting.getPath())) { //If the setting does not exist in the config file, add it root.setRaw(globalSetting.getPath(), globalSetting.getDefaultValue()); } else { //Set the setting to the value found in the path globalSettings.put(globalSetting, root.getRaw(globalSetting.getPath())); } } //Load all base prices DataKey basePriceNode = root.getRelative(GlobalSetting.BASE_PRICE.getParent()); Map relevantKeys = getRelevantKeys(basePriceNode); for (String key : relevantKeys.keySet()) { String materialName = relevantKeys.get(key); Material material = Material.matchMaterial(materialName); if (material != null) { materialBasePrices.put(material, basePriceNode.getDouble(key)); } else { BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING, "Unable to find a material matching " + materialName); } } //Load all per-durability-point prices DataKey basePerDurabilityPriceNode = root.getRelative(GlobalSetting.PRICE_PER_DURABILITY_POINT.getParent()); relevantKeys = getRelevantKeys(basePerDurabilityPriceNode); for (String key : relevantKeys.keySet()) { String materialName = relevantKeys.get(key); Material material = Material.matchMaterial(materialName); if (material != null) { materialPricePerDurabilityPoints.put(material, basePerDurabilityPriceNode.getDouble(key)); } else { BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING, "Unable to find a material matching " + materialName); } } //Load all enchantment prices DataKey enchantmentModifiersNode = root.getRelative(GlobalSetting.ENCHANTMENT_MODIFIER.getParent()); relevantKeys = getRelevantKeys(basePerDurabilityPriceNode); for (String key : relevantKeys.keySet()) { String enchantmentName = relevantKeys.get(key); Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(enchantmentName)); if (enchantment != null) { enchantmentModifiers.put(enchantment, enchantmentModifiersNode.getDouble(key)); } else { BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING, "Unable to find an enchantment matching " + enchantmentName); } } } /** * Gets a map between relevant keys and their normalized name * * @param rootKey

The root data key containing sub-keys

* @return

Any sub-keys found that aren't the default

*/ private Map getRelevantKeys(DataKey rootKey) { Map relevant = new HashMap<>(); for (DataKey dataKey : rootKey.getSubKeys()) { String keyName = dataKey.name(); //Skip the default value if (keyName.equals("default")) { continue; } String normalizedName = keyName.toUpperCase().replace("-", "_"); relevant.put(keyName, normalizedName); } return relevant; } /** * Loads all default NPC settings * * @param root

The root node of all default NPC settings

*/ private void loadDefaultNPCSettings(DataKey root) { for (NPCSetting setting : NPCSetting.values()) { if (!root.keyExists(setting.getPath())) { //If the setting does not exist in the config file, add it root.setRaw(setting.getPath(), setting.getDefaultValue()); } else { //Set the setting to the value found in the path defaultNPCSettings.put(setting, root.getRaw(setting.getPath())); } } } }