Majorly changes most plugin code
Changes the entire settings structure Splits settings into NPC settings and global settings Adds some command classes in preparation for a new command system Moves a lot of code away from BlacksmithPlugin Adds a new EconomyManager class which takes care of everything economy and pricing Removes HyperConomy softdepend Changes the reload command to /blacksmith reload Adds a proper configuration file to make possible to change stuff without a bloody wiki
This commit is contained in:
		@@ -1,33 +1,20 @@
 | 
			
		||||
package net.knarcraft.blacksmith;
 | 
			
		||||
 | 
			
		||||
import net.citizensnpcs.api.CitizensAPI;
 | 
			
		||||
import net.citizensnpcs.api.util.DataKey;
 | 
			
		||||
import net.knarcraft.blacksmith.config.Setting;
 | 
			
		||||
import net.knarcraft.blacksmith.config.Settings;
 | 
			
		||||
import net.milkbowl.vault.economy.Economy;
 | 
			
		||||
import org.bukkit.ChatColor;
 | 
			
		||||
import org.bukkit.command.Command;
 | 
			
		||||
import org.bukkit.command.CommandSender;
 | 
			
		||||
import org.bukkit.enchantments.Enchantment;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
import org.bukkit.inventory.ItemStack;
 | 
			
		||||
import org.bukkit.inventory.meta.Damageable;
 | 
			
		||||
import org.bukkit.plugin.RegisteredServiceProvider;
 | 
			
		||||
import net.knarcraft.blacksmith.command.BlackSmithCommand;
 | 
			
		||||
import net.knarcraft.blacksmith.config.GlobalSettings;
 | 
			
		||||
import org.bukkit.command.PluginCommand;
 | 
			
		||||
import org.bukkit.plugin.java.JavaPlugin;
 | 
			
		||||
import org.jetbrains.annotations.NotNull;
 | 
			
		||||
 | 
			
		||||
import java.util.logging.Level;
 | 
			
		||||
 | 
			
		||||
import static net.knarcraft.blacksmith.util.Sanitizer.sanitizeItemName;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Blacksmith's main class
 | 
			
		||||
 */
 | 
			
		||||
public class BlacksmithPlugin extends JavaPlugin {
 | 
			
		||||
 | 
			
		||||
    private static BlacksmithPlugin instance;
 | 
			
		||||
    private Settings config;
 | 
			
		||||
    private Economy economy;
 | 
			
		||||
    private GlobalSettings config;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets an instance of the Blacksmith plugin
 | 
			
		||||
@@ -43,14 +30,19 @@ public class BlacksmithPlugin extends JavaPlugin {
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>Settings for the blacksmith plugin</p>
 | 
			
		||||
     */
 | 
			
		||||
    public Settings getSettings() {
 | 
			
		||||
    public GlobalSettings getSettings() {
 | 
			
		||||
        return config;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Reloads the configuration file from disk
 | 
			
		||||
     */
 | 
			
		||||
    public void reload() {
 | 
			
		||||
        config.load();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onDisable() {
 | 
			
		||||
        //	config.save();
 | 
			
		||||
 | 
			
		||||
        getLogger().log(Level.INFO, " v" + getDescription().getVersion() + " disabled.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -59,11 +51,11 @@ public class BlacksmithPlugin extends JavaPlugin {
 | 
			
		||||
        instance = this;
 | 
			
		||||
 | 
			
		||||
        //Load settings
 | 
			
		||||
        config = new Settings(this);
 | 
			
		||||
        config = new GlobalSettings(this);
 | 
			
		||||
        config.load();
 | 
			
		||||
 | 
			
		||||
        getLogger().log(Level.INFO, "Setting Up Vault now....");
 | 
			
		||||
        boolean canLoad = setupVault();
 | 
			
		||||
        boolean canLoad = EconomyManager.setUp(getServer().getServicesManager(), getLogger());
 | 
			
		||||
        if (!canLoad) {
 | 
			
		||||
            getLogger().log(Level.SEVERE, "Vault Integration Failed....");
 | 
			
		||||
            getServer().getPluginManager().disablePlugin(this);
 | 
			
		||||
@@ -73,200 +65,13 @@ public class BlacksmithPlugin extends JavaPlugin {
 | 
			
		||||
        CitizensAPI.getTraitFactory().registerTrait(
 | 
			
		||||
                net.citizensnpcs.api.trait.TraitInfo.create(BlacksmithTrait.class).withName("blacksmith"));
 | 
			
		||||
 | 
			
		||||
        //Register the blacksmith main-command
 | 
			
		||||
        PluginCommand blacksmithCommand = this.getCommand("blacksmith");
 | 
			
		||||
        if (blacksmithCommand != null) {
 | 
			
		||||
            blacksmithCommand.setExecutor(new BlackSmithCommand());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getLogger().log(Level.INFO, " v" + getDescription().getVersion() + " enabled.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets up Vault for economy
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>True if Vault was successfully set up</p>
 | 
			
		||||
     */
 | 
			
		||||
    private boolean setupVault() {
 | 
			
		||||
        // Setup Vault
 | 
			
		||||
        RegisteredServiceProvider<Economy> economyProvider = getServer().getServicesManager().getRegistration(
 | 
			
		||||
                Economy.class);
 | 
			
		||||
        if (economyProvider != null) {
 | 
			
		||||
            economy = economyProvider.getProvider();
 | 
			
		||||
            return true;
 | 
			
		||||
        } else {
 | 
			
		||||
            // Disable if no economy plugin was found
 | 
			
		||||
            getServer().getLogger().log(Level.SEVERE, "Failed to load an economy plugin. Disabling...");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean onCommand(final CommandSender sender, final @NotNull Command command, final @NotNull String label,
 | 
			
		||||
                             final String[] args) {
 | 
			
		||||
        //Handle the reload command
 | 
			
		||||
        config.load();
 | 
			
		||||
        sender.sendMessage(ChatColor.GREEN + "Blacksmith config reloaded!");
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets whether the given item is a type of tool
 | 
			
		||||
     *
 | 
			
		||||
     * @param item <p>The item to check if is tool or not</p>
 | 
			
		||||
     * @return <p>True if the given item is a type of tool</p>
 | 
			
		||||
     */
 | 
			
		||||
    public boolean isTool(ItemStack item) {
 | 
			
		||||
        return switch (item.getType()) {
 | 
			
		||||
            case WOODEN_PICKAXE, WOODEN_SHOVEL, WOODEN_HOE, WOODEN_SWORD, WOODEN_AXE, STONE_PICKAXE, STONE_SHOVEL,
 | 
			
		||||
                    STONE_HOE, STONE_SWORD, STONE_AXE, GOLDEN_PICKAXE, GOLDEN_SHOVEL, GOLDEN_HOE, GOLDEN_SWORD,
 | 
			
		||||
                    GOLDEN_AXE, IRON_PICKAXE, IRON_SHOVEL, IRON_HOE, IRON_SWORD, IRON_AXE, DIAMOND_PICKAXE,
 | 
			
		||||
                    DIAMOND_SHOVEL, DIAMOND_HOE, DIAMOND_SWORD, DIAMOND_AXE, NETHERITE_SWORD, NETHERITE_SHOVEL,
 | 
			
		||||
                    NETHERITE_PICKAXE, NETHERITE_AXE, NETHERITE_HOE, BOW, CROSSBOW, FLINT_AND_STEEL, FISHING_ROD,
 | 
			
		||||
                    SHEARS, TRIDENT, SHIELD -> true;
 | 
			
		||||
            default -> false;
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets whether the given item is a type of armor
 | 
			
		||||
     *
 | 
			
		||||
     * @param item <p>The item to check if is armor or not</p>
 | 
			
		||||
     * @return <p>True if the given item is a type of armor</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean isArmor(ItemStack item) {
 | 
			
		||||
        return switch (item.getType()) {
 | 
			
		||||
            case LEATHER_HELMET, LEATHER_CHESTPLATE, LEATHER_LEGGINGS, LEATHER_BOOTS, CHAINMAIL_HELMET,
 | 
			
		||||
                    CHAINMAIL_CHESTPLATE, CHAINMAIL_LEGGINGS, CHAINMAIL_BOOTS, GOLDEN_HELMET, GOLDEN_CHESTPLATE,
 | 
			
		||||
                    GOLDEN_LEGGINGS, GOLDEN_BOOTS, IRON_HELMET, IRON_CHESTPLATE, IRON_LEGGINGS, IRON_BOOTS,
 | 
			
		||||
                    DIAMOND_HELMET, DIAMOND_CHESTPLATE, DIAMOND_LEGGINGS, DIAMOND_BOOTS, TURTLE_HELMET, ELYTRA,
 | 
			
		||||
                    NETHERITE_HELMET, NETHERITE_CHESTPLATE, NETHERITE_LEGGINGS, NETHERITE_BOOTS -> true;
 | 
			
		||||
            default -> false;
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets whether the given player can pay for re-forging their held item
 | 
			
		||||
     *
 | 
			
		||||
     * @param player <p>The player holding an item</p>
 | 
			
		||||
     * @return <p>Whether the player can pay for the re-forge</p>
 | 
			
		||||
     */
 | 
			
		||||
    public boolean canPay(Player player) {
 | 
			
		||||
        return economy.getBalance(player) - getHeldItemCost(player) >= 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the human-readable cost of the given player's held item
 | 
			
		||||
     *
 | 
			
		||||
     * @param player <p>The player holding an item</p>
 | 
			
		||||
     * @return <p>The formatted cost</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String formatCost(Player player) {
 | 
			
		||||
        double cost = getHeldItemCost(player);
 | 
			
		||||
        return economy.format(cost);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Withdraws the re-forge cost from the given player
 | 
			
		||||
     *
 | 
			
		||||
     * <p>The cost is automatically calculated from the item in the player's main hand.</p>
 | 
			
		||||
     *
 | 
			
		||||
     * @param player <p>The player to withdraw from</p>
 | 
			
		||||
     */
 | 
			
		||||
    public void withdraw(Player player) {
 | 
			
		||||
        economy.withdrawPlayer(player, getHeldItemCost(player));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the current durability of the given item
 | 
			
		||||
     *
 | 
			
		||||
     * @param itemStack <p>The item to get the durability of</p>
 | 
			
		||||
     * @return <p>The durability of the item</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static short getDurability(ItemStack itemStack) {
 | 
			
		||||
        Damageable damageable = (Damageable) itemStack.getItemMeta();
 | 
			
		||||
        int maxDurability = itemStack.getType().getMaxDurability();
 | 
			
		||||
        if (damageable != null) {
 | 
			
		||||
            return (short) (maxDurability - damageable.getDamage());
 | 
			
		||||
        } else {
 | 
			
		||||
            return (short) maxDurability;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the damage done to the given item
 | 
			
		||||
     *
 | 
			
		||||
     * @param itemStack <p>The damage done to the item</p>
 | 
			
		||||
     * @return <p>The damage done to the item</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static short getDamage(ItemStack itemStack) {
 | 
			
		||||
        Damageable damageable = (Damageable) itemStack.getItemMeta();
 | 
			
		||||
        if (damageable != null) {
 | 
			
		||||
            return (short) damageable.getDamage();
 | 
			
		||||
        } else {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the cost of repairing the given item
 | 
			
		||||
     *
 | 
			
		||||
     * @param item <p>The item to be repaired</p>
 | 
			
		||||
     * @return <p>The cost of the repair</p>
 | 
			
		||||
     */
 | 
			
		||||
    private double getCost(ItemStack item) {
 | 
			
		||||
        DataKey root = config.getConfig().getKey("");
 | 
			
		||||
        String itemName = sanitizeItemName(item.getType().name());
 | 
			
		||||
        double price;
 | 
			
		||||
        if (root.keyExists("base-prices." + itemName)) {
 | 
			
		||||
            price = root.getDouble("base-prices." + itemName);
 | 
			
		||||
        } else {
 | 
			
		||||
            price = Setting.BASE_PRICE.asDouble();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Adjust price based on durability and enchantments
 | 
			
		||||
        double pricePerDurabilityPoint;
 | 
			
		||||
        if (root.keyExists("price-per-durability-point." + itemName)) {
 | 
			
		||||
            pricePerDurabilityPoint = root.getDouble("price-per-durability-point." + itemName);
 | 
			
		||||
        } else {
 | 
			
		||||
            pricePerDurabilityPoint = Setting.PRICE_PER_DURABILITY_POINT.asDouble();
 | 
			
		||||
        }
 | 
			
		||||
        if (config.getNaturalCost()) {
 | 
			
		||||
            //Cost increases with damage
 | 
			
		||||
            price += ((double) getDamage(item)) * pricePerDurabilityPoint;
 | 
			
		||||
        } else {
 | 
			
		||||
            //Cost decreases with damage
 | 
			
		||||
            price += ((double) getDurability(item)) * pricePerDurabilityPoint;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //Add the enchantment modifier for each enchantment on the item
 | 
			
		||||
        price += getEnchantmentCost(item, root);
 | 
			
		||||
        return price;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the cost resulting from all enchantments on the given item
 | 
			
		||||
     *
 | 
			
		||||
     * @param item <p>The item to calculate enchantment cost for</p>
 | 
			
		||||
     * @param root <p>The data key containing the enchantment-modifiers option</p>
 | 
			
		||||
     * @return <p>The resulting enchantment cost</p>
 | 
			
		||||
     */
 | 
			
		||||
    private double getEnchantmentCost(ItemStack item, DataKey root) {
 | 
			
		||||
        double enchantmentModifier = Setting.ENCHANTMENT_MODIFIER.asDouble();
 | 
			
		||||
        double price = 0;
 | 
			
		||||
        for (Enchantment enchantment : item.getEnchantments().keySet()) {
 | 
			
		||||
            String enchantmentKey = "enchantment-modifiers." + sanitizeItemName(enchantment.getKey().toString());
 | 
			
		||||
            if (root.keyExists(enchantmentKey)) {
 | 
			
		||||
                price += root.getDouble(enchantmentKey) * item.getEnchantmentLevel(enchantment);
 | 
			
		||||
            } else {
 | 
			
		||||
                price += enchantmentModifier * item.getEnchantmentLevel(enchantment);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return price;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the cost of the item in the given player's main hand
 | 
			
		||||
     *
 | 
			
		||||
     * @param player <p>The player to calculate the cost for</p>
 | 
			
		||||
     * @return <p>The calculated cost</p>
 | 
			
		||||
     */
 | 
			
		||||
    private double getHeldItemCost(Player player) {
 | 
			
		||||
        return getCost(player.getInventory().getItemInMainHand());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,10 +4,10 @@ import net.citizensnpcs.api.CitizensAPI;
 | 
			
		||||
import net.citizensnpcs.api.npc.NPC;
 | 
			
		||||
import net.citizensnpcs.api.trait.Trait;
 | 
			
		||||
import net.citizensnpcs.api.util.DataKey;
 | 
			
		||||
import net.knarcraft.blacksmith.config.Settings;
 | 
			
		||||
import net.knarcraft.blacksmith.util.Sanitizer;
 | 
			
		||||
import net.knarcraft.blacksmith.config.NPCSettings;
 | 
			
		||||
import org.bukkit.Bukkit;
 | 
			
		||||
import org.bukkit.Material;
 | 
			
		||||
import org.bukkit.enchantments.EnchantmentTarget;
 | 
			
		||||
import org.bukkit.entity.Entity;
 | 
			
		||||
import org.bukkit.entity.LivingEntity;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
@@ -17,9 +17,9 @@ import org.bukkit.event.EventPriority;
 | 
			
		||||
import org.bukkit.event.block.Action;
 | 
			
		||||
import org.bukkit.event.player.PlayerInteractEvent;
 | 
			
		||||
import org.bukkit.inventory.ItemStack;
 | 
			
		||||
import org.bukkit.inventory.meta.Damageable;
 | 
			
		||||
import org.bukkit.util.Vector;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Calendar;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
@@ -27,18 +27,14 @@ import java.util.Map;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
import static net.knarcraft.blacksmith.util.Sanitizer.sanitizedToItemName;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The class representing the Blacksmith NPC trait
 | 
			
		||||
 */
 | 
			
		||||
public class BlacksmithTrait extends Trait {
 | 
			
		||||
 | 
			
		||||
    private final BlacksmithPlugin plugin;
 | 
			
		||||
    private final List<Material> reforgeAbleItems = new ArrayList<>();
 | 
			
		||||
    private final Map<UUID, Calendar> coolDowns = new HashMap<>();
 | 
			
		||||
    private ReforgeSession session;
 | 
			
		||||
    private final Settings config;
 | 
			
		||||
    private final NPCSettings config;
 | 
			
		||||
    private long _sessionStart = System.currentTimeMillis();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -46,8 +42,9 @@ public class BlacksmithTrait extends Trait {
 | 
			
		||||
     */
 | 
			
		||||
    public BlacksmithTrait() {
 | 
			
		||||
        super("blacksmith");
 | 
			
		||||
        plugin = (BlacksmithPlugin) Bukkit.getServer().getPluginManager().getPlugin("Blacksmith");
 | 
			
		||||
        this.config = BlacksmithPlugin.getInstance().getSettings();
 | 
			
		||||
        //This should crash if the blacksmith plugin hasn't been properly registered
 | 
			
		||||
        Bukkit.getServer().getPluginManager().getPlugin("Blacksmith");
 | 
			
		||||
        this.config = new NPCSettings(BlacksmithPlugin.getInstance().getSettings());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -67,26 +64,23 @@ public class BlacksmithTrait extends Trait {
 | 
			
		||||
        this.session = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Loads all config values stored in citizens' config file for this NPC
 | 
			
		||||
     *
 | 
			
		||||
     * @param key <p>The data key used for the config root</p>
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void load(DataKey key) {
 | 
			
		||||
        for (DataKey sub : key.getRelative("reforge-able-items").getIntegerSubKeys()) {
 | 
			
		||||
            Material material = Material.getMaterial(sanitizedToItemName(sub.getString("")));
 | 
			
		||||
            if (material != null) {
 | 
			
		||||
                reforgeAbleItems.add(material);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        config.loadVariables(key);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Saves all config values for this NPC
 | 
			
		||||
     *
 | 
			
		||||
     * @param key <p>The data key used for the config root</p>
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void save(DataKey key) {
 | 
			
		||||
        //Save all items the blacksmith knows how to reforge
 | 
			
		||||
        for (int i = 0; i < reforgeAbleItems.size(); i++) {
 | 
			
		||||
            key.getRelative("reforge-able-items").setString(String.valueOf(i), Sanitizer.sanitizeItemName(
 | 
			
		||||
                    reforgeAbleItems.get(i).name()));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //Save all other config values
 | 
			
		||||
        config.saveVariables(key);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -105,7 +99,7 @@ public class BlacksmithTrait extends Trait {
 | 
			
		||||
 | 
			
		||||
        //Block armor equip if interacting with a blacksmith
 | 
			
		||||
        ItemStack usedItem = event.getPlayer().getInventory().getItem(event.getHand());
 | 
			
		||||
        if (usedItem != null && BlacksmithPlugin.isArmor(usedItem)) {
 | 
			
		||||
        if (usedItem != null && isArmor(usedItem)) {
 | 
			
		||||
            event.setUseItemInHand(Event.Result.DENY);
 | 
			
		||||
            event.getPlayer().updateInventory();
 | 
			
		||||
        }
 | 
			
		||||
@@ -199,9 +193,9 @@ public class BlacksmithTrait extends Trait {
 | 
			
		||||
     */
 | 
			
		||||
    private void startSession(Player player) {
 | 
			
		||||
        ItemStack hand = player.getInventory().getItemInMainHand();
 | 
			
		||||
        //If not a tool, not armor, and not set in reforgeAbleItems, refuse to repair
 | 
			
		||||
        if ((!plugin.isTool(hand) && !BlacksmithPlugin.isArmor(hand)) ||
 | 
			
		||||
                (!reforgeAbleItems.isEmpty() && !reforgeAbleItems.contains(hand.getType()))) {
 | 
			
		||||
        //Refuse if not repairable, or if reforge-able items is set, but doesn't include the held item
 | 
			
		||||
        List<Material> reforgeAbleItems = config.getReforgeAbleItems();
 | 
			
		||||
        if (!isRepairable(hand) || (!reforgeAbleItems.isEmpty() && !reforgeAbleItems.contains(hand.getType()))) {
 | 
			
		||||
            player.sendMessage(config.getInvalidItemMessage());
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@@ -211,7 +205,7 @@ public class BlacksmithTrait extends Trait {
 | 
			
		||||
        session = new ReforgeSession(this, player, npc, config);
 | 
			
		||||
 | 
			
		||||
        //Tell the player the cost of repairing the item
 | 
			
		||||
        String cost = plugin.formatCost(player);
 | 
			
		||||
        String cost = EconomyManager.formatCost(player);
 | 
			
		||||
        String itemName = hand.getType().name().toLowerCase().replace('_', ' ');
 | 
			
		||||
        player.sendMessage(config.getCostMessage().replace("<price>", cost).replace("<item>", itemName));
 | 
			
		||||
    }
 | 
			
		||||
@@ -224,7 +218,7 @@ public class BlacksmithTrait extends Trait {
 | 
			
		||||
     */
 | 
			
		||||
    private void reforge(NPC npc, Player player) {
 | 
			
		||||
        player.sendMessage(config.getStartReforgeMessage());
 | 
			
		||||
        plugin.withdraw(player);
 | 
			
		||||
        EconomyManager.withdraw(player);
 | 
			
		||||
        session.beginReforge();
 | 
			
		||||
        ItemStack heldItem = player.getInventory().getItemInMainHand();
 | 
			
		||||
 | 
			
		||||
@@ -266,4 +260,33 @@ public class BlacksmithTrait extends Trait {
 | 
			
		||||
        return target;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets whether the given item is repairable
 | 
			
		||||
     *
 | 
			
		||||
     * @param item <p>The item to check</p>
 | 
			
		||||
     * @return <p>True if the item is repairable</p>
 | 
			
		||||
     */
 | 
			
		||||
    private static boolean isRepairable(ItemStack item) {
 | 
			
		||||
        return item.getItemMeta() instanceof Damageable;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets whether the given item is a type of armor
 | 
			
		||||
     *
 | 
			
		||||
     * @param item <p>The item to check if is armor or not</p>
 | 
			
		||||
     * @return <p>True if the given item is a type of armor</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean isArmor(ItemStack item) {
 | 
			
		||||
        return EnchantmentTarget.WEARABLE.includes(item);
 | 
			
		||||
        //TODO: Remove this commented-out code if the above line works
 | 
			
		||||
        /*return switch (item.getType()) {
 | 
			
		||||
            case LEATHER_HELMET, LEATHER_CHESTPLATE, LEATHER_LEGGINGS, LEATHER_BOOTS, CHAINMAIL_HELMET,
 | 
			
		||||
                    CHAINMAIL_CHESTPLATE, CHAINMAIL_LEGGINGS, CHAINMAIL_BOOTS, GOLDEN_HELMET, GOLDEN_CHESTPLATE,
 | 
			
		||||
                    GOLDEN_LEGGINGS, GOLDEN_BOOTS, IRON_HELMET, IRON_CHESTPLATE, IRON_LEGGINGS, IRON_BOOTS,
 | 
			
		||||
                    DIAMOND_HELMET, DIAMOND_CHESTPLATE, DIAMOND_LEGGINGS, DIAMOND_BOOTS, TURTLE_HELMET, ELYTRA,
 | 
			
		||||
                    NETHERITE_HELMET, NETHERITE_CHESTPLATE, NETHERITE_LEGGINGS, NETHERITE_BOOTS -> true;
 | 
			
		||||
            default -> false;
 | 
			
		||||
        };*/
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										174
									
								
								src/main/java/net/knarcraft/blacksmith/EconomyManager.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								src/main/java/net/knarcraft/blacksmith/EconomyManager.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,174 @@
 | 
			
		||||
package net.knarcraft.blacksmith;
 | 
			
		||||
 | 
			
		||||
import net.knarcraft.blacksmith.config.GlobalSettings;
 | 
			
		||||
import net.milkbowl.vault.economy.Economy;
 | 
			
		||||
import org.bukkit.Material;
 | 
			
		||||
import org.bukkit.enchantments.Enchantment;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
import org.bukkit.inventory.ItemStack;
 | 
			
		||||
import org.bukkit.inventory.meta.Damageable;
 | 
			
		||||
import org.bukkit.plugin.RegisteredServiceProvider;
 | 
			
		||||
import org.bukkit.plugin.ServicesManager;
 | 
			
		||||
 | 
			
		||||
import java.util.logging.Level;
 | 
			
		||||
import java.util.logging.Logger;
 | 
			
		||||
 | 
			
		||||
public class EconomyManager {
 | 
			
		||||
 | 
			
		||||
    private static Economy economy;
 | 
			
		||||
 | 
			
		||||
    private EconomyManager() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets up Vault economy support
 | 
			
		||||
     *
 | 
			
		||||
     * @param servicesManager <p>The services manager to use for finding a Vault provider</p>
 | 
			
		||||
     * @param logger          <p>The logger to use for logging</p>
 | 
			
		||||
     * @return <p>True if Vault was successfully set up</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean setUp(ServicesManager servicesManager, Logger logger) {
 | 
			
		||||
        //If already set up, there is nothing to do
 | 
			
		||||
        if (economy != null) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return setupVault(servicesManager, logger);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets whether the given player can pay for re-forging their held item
 | 
			
		||||
     *
 | 
			
		||||
     * @param player <p>The player holding an item</p>
 | 
			
		||||
     * @return <p>Whether the player can pay for the re-forge</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean canPay(Player player) {
 | 
			
		||||
        return economy.getBalance(player) - getHeldItemCost(player) >= 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the human-readable cost of the given player's held item
 | 
			
		||||
     *
 | 
			
		||||
     * @param player <p>The player holding an item</p>
 | 
			
		||||
     * @return <p>The formatted cost</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static String formatCost(Player player) {
 | 
			
		||||
        double cost = getHeldItemCost(player);
 | 
			
		||||
        return economy.format(cost);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Withdraws the re-forge cost from the given player
 | 
			
		||||
     *
 | 
			
		||||
     * <p>The cost is automatically calculated from the item in the player's main hand.</p>
 | 
			
		||||
     *
 | 
			
		||||
     * @param player <p>The player to withdraw from</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static void withdraw(Player player) {
 | 
			
		||||
        economy.withdrawPlayer(player, getHeldItemCost(player));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the current durability of the given item
 | 
			
		||||
     *
 | 
			
		||||
     * @param itemStack <p>The item to get the durability of</p>
 | 
			
		||||
     * @return <p>The durability of the item</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static short getDurability(ItemStack itemStack) {
 | 
			
		||||
        Damageable damageable = (Damageable) itemStack.getItemMeta();
 | 
			
		||||
        int maxDurability = itemStack.getType().getMaxDurability();
 | 
			
		||||
        if (damageable != null) {
 | 
			
		||||
            return (short) (maxDurability - damageable.getDamage());
 | 
			
		||||
        } else {
 | 
			
		||||
            return (short) maxDurability;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the damage done to the given item
 | 
			
		||||
     *
 | 
			
		||||
     * @param itemStack <p>The damage done to the item</p>
 | 
			
		||||
     * @return <p>The damage done to the item</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static short getDamage(ItemStack itemStack) {
 | 
			
		||||
        Damageable damageable = (Damageable) itemStack.getItemMeta();
 | 
			
		||||
        if (damageable != null) {
 | 
			
		||||
            return (short) damageable.getDamage();
 | 
			
		||||
        } else {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the cost of the item in the given player's main hand
 | 
			
		||||
     *
 | 
			
		||||
     * @param player <p>The player to calculate the cost for</p>
 | 
			
		||||
     * @return <p>The calculated cost</p>
 | 
			
		||||
     */
 | 
			
		||||
    private static double getHeldItemCost(Player player) {
 | 
			
		||||
        return getCost(player.getInventory().getItemInMainHand());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the cost of repairing the given item
 | 
			
		||||
     *
 | 
			
		||||
     * @param item <p>The item to be repaired</p>
 | 
			
		||||
     * @return <p>The cost of the repair</p>
 | 
			
		||||
     */
 | 
			
		||||
    private static double getCost(ItemStack item) {
 | 
			
		||||
        GlobalSettings globalSettings = BlacksmithPlugin.getInstance().getSettings();
 | 
			
		||||
        Material material = item.getType();
 | 
			
		||||
        //Calculate the base price
 | 
			
		||||
        double price = globalSettings.getBasePrice(material);
 | 
			
		||||
 | 
			
		||||
        // Adjust price based on durability
 | 
			
		||||
        double pricePerDurabilityPoint = globalSettings.getPricePerDurabilityPoint(material);
 | 
			
		||||
        if (globalSettings.getUseNaturalCost()) {
 | 
			
		||||
            //Cost increases with damage
 | 
			
		||||
            price += ((double) getDamage(item)) * pricePerDurabilityPoint;
 | 
			
		||||
        } else {
 | 
			
		||||
            //Cost decreases with damage
 | 
			
		||||
            price += ((double) getDurability(item)) * pricePerDurabilityPoint;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //Increase price for any enchantments
 | 
			
		||||
        price += getEnchantmentCost(item);
 | 
			
		||||
        return price;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the cost resulting from all enchantments on the given item
 | 
			
		||||
     *
 | 
			
		||||
     * @param item <p>The item to calculate enchantment cost for</p>
 | 
			
		||||
     * @return <p>The resulting enchantment cost</p>
 | 
			
		||||
     */
 | 
			
		||||
    private static double getEnchantmentCost(ItemStack item) {
 | 
			
		||||
        GlobalSettings settings = BlacksmithPlugin.getInstance().getSettings();
 | 
			
		||||
        double price = 0;
 | 
			
		||||
        for (Enchantment enchantment : item.getEnchantments().keySet()) {
 | 
			
		||||
            price += settings.getEnchantmentModifier(enchantment) * item.getEnchantmentLevel(enchantment);
 | 
			
		||||
        }
 | 
			
		||||
        return price;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets up Vault for economy
 | 
			
		||||
     *
 | 
			
		||||
     * @param servicesManager <p>The services manager to use for finding a Vault provider</p>
 | 
			
		||||
     * @param logger          <p>The logger to use for logging</p>
 | 
			
		||||
     * @return <p>True if Vault was successfully set up</p>
 | 
			
		||||
     */
 | 
			
		||||
    private static boolean setupVault(ServicesManager servicesManager, Logger logger) {
 | 
			
		||||
        // Setup Vault
 | 
			
		||||
        RegisteredServiceProvider<Economy> economyProvider = servicesManager.getRegistration(Economy.class);
 | 
			
		||||
        if (economyProvider != null) {
 | 
			
		||||
            economy = economyProvider.getProvider();
 | 
			
		||||
            return true;
 | 
			
		||||
        } else {
 | 
			
		||||
            // Disable if no economy plugin was found
 | 
			
		||||
            logger.log(Level.SEVERE, "Failed to load an economy plugin. Disabling...");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
package net.knarcraft.blacksmith;
 | 
			
		||||
 | 
			
		||||
import net.citizensnpcs.api.npc.NPC;
 | 
			
		||||
import net.knarcraft.blacksmith.config.Settings;
 | 
			
		||||
import net.knarcraft.blacksmith.config.NPCSettings;
 | 
			
		||||
import org.bukkit.NamespacedKey;
 | 
			
		||||
import org.bukkit.enchantments.Enchantment;
 | 
			
		||||
import org.bukkit.entity.LivingEntity;
 | 
			
		||||
@@ -25,7 +25,7 @@ public class ReforgeSession implements Runnable {
 | 
			
		||||
    private final NPC npc;
 | 
			
		||||
    private final ItemStack itemToReforge;
 | 
			
		||||
    private int taskId;
 | 
			
		||||
    private final Settings config;
 | 
			
		||||
    private final NPCSettings config;
 | 
			
		||||
    private static final String[] enchantments = new String[Enchantment.values().length];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -36,7 +36,7 @@ public class ReforgeSession implements Runnable {
 | 
			
		||||
     * @param npc             <p>The Blacksmith NPC involved in the session</p>
 | 
			
		||||
     * @param config          <p>The config to use for the session</p>
 | 
			
		||||
     */
 | 
			
		||||
    ReforgeSession(BlacksmithTrait blacksmithTrait, Player player, NPC npc, Settings config) {
 | 
			
		||||
    ReforgeSession(BlacksmithTrait blacksmithTrait, Player player, NPC npc, NPCSettings config) {
 | 
			
		||||
        this.blacksmithTrait = blacksmithTrait;
 | 
			
		||||
        this.player = player;
 | 
			
		||||
        this.npc = npc;
 | 
			
		||||
@@ -88,7 +88,7 @@ public class ReforgeSession implements Runnable {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            // Damage the item
 | 
			
		||||
            short reforgeDurability = BlacksmithPlugin.getDurability(itemToReforge);
 | 
			
		||||
            short reforgeDurability = EconomyManager.getDurability(itemToReforge);
 | 
			
		||||
            short durability = (short) (reforgeDurability + reforgeDurability * random.nextInt(8));
 | 
			
		||||
            short maxDurability = itemToReforge.getType().getMaxDurability();
 | 
			
		||||
            if (durability <= 0) {
 | 
			
		||||
@@ -151,7 +151,7 @@ public class ReforgeSession implements Runnable {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        // The player is unable to pay
 | 
			
		||||
        if (!BlacksmithPlugin.getInstance().canPay(player)) {
 | 
			
		||||
        if (!EconomyManager.canPay(player)) {
 | 
			
		||||
            player.sendMessage(config.getInsufficientFundsMessage());
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,23 @@
 | 
			
		||||
package net.knarcraft.blacksmith.command;
 | 
			
		||||
 | 
			
		||||
import org.bukkit.command.Command;
 | 
			
		||||
import org.bukkit.command.CommandExecutor;
 | 
			
		||||
import org.bukkit.command.CommandSender;
 | 
			
		||||
import org.jetbrains.annotations.NotNull;
 | 
			
		||||
 | 
			
		||||
public class BlackSmithCommand implements CommandExecutor {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
 | 
			
		||||
                             @NotNull String[] args) {
 | 
			
		||||
        //TODO: This command should have one config sub-command which changes the default config values, and all 
 | 
			
		||||
        // setting names which can be changed for each NPC.
 | 
			
		||||
        if (args.length > 0) {
 | 
			
		||||
            if (args[0].equalsIgnoreCase("reload")) {
 | 
			
		||||
                return new ReloadCommand().onCommand(sender, command, label, args);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,29 @@
 | 
			
		||||
package net.knarcraft.blacksmith.command;
 | 
			
		||||
 | 
			
		||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
 | 
			
		||||
import org.bukkit.ChatColor;
 | 
			
		||||
import org.bukkit.command.Command;
 | 
			
		||||
import org.bukkit.command.CommandSender;
 | 
			
		||||
import org.bukkit.command.TabExecutor;
 | 
			
		||||
import org.jetbrains.annotations.NotNull;
 | 
			
		||||
import org.jetbrains.annotations.Nullable;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
public class ReloadCommand implements TabExecutor {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
 | 
			
		||||
        BlacksmithPlugin.getInstance().reload();
 | 
			
		||||
        sender.sendMessage(ChatColor.GREEN + "Blacksmith config reloaded!");
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
 | 
			
		||||
        return new ArrayList<>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,79 @@
 | 
			
		||||
package net.knarcraft.blacksmith.config;
 | 
			
		||||
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
 | 
			
		||||
public enum GlobalSetting {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The base price for repairing, regardless of durability
 | 
			
		||||
     *
 | 
			
		||||
     * <p>This allows specifying a price for each item, by setting base-price.item_name.</p>
 | 
			
		||||
     */
 | 
			
		||||
    BASE_PRICE("global.base-price.default", 10.0),
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The base price for each durability point
 | 
			
		||||
     *
 | 
			
		||||
     * <p>If natural cost, this is the cost each missing durability point will add to the cost. If not natural cost,
 | 
			
		||||
     * this is the cost each present durability point will add to the cost. This allows specifying a price per
 | 
			
		||||
     * durability point value for each item, by setting price-per-durability-point.item_name</p>
 | 
			
		||||
     */
 | 
			
		||||
    PRICE_PER_DURABILITY_POINT("global.price-per-durability-point.default", 0.005),
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The price increase for each level of each present enchantment
 | 
			
		||||
     *
 | 
			
		||||
     * <p>This can be specified for each possible enchantment by setting enchantment-modifiers.enchantment_name</p>
 | 
			
		||||
     */
 | 
			
		||||
    ENCHANTMENT_MODIFIER("global.enchantment-cost.default", 5),
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Whether the cost should increase for damage taken, as opposed to increase for durability present
 | 
			
		||||
     */
 | 
			
		||||
    NATURAL_COST("global.natural-cost", true);
 | 
			
		||||
 | 
			
		||||
    private final String path;
 | 
			
		||||
    private final String parent;
 | 
			
		||||
    private final Object value;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Instantiates a new setting
 | 
			
		||||
     *
 | 
			
		||||
     * @param path  <p>The full config path for this setting</p>
 | 
			
		||||
     * @param value <p>The default value of this setting</p>
 | 
			
		||||
     */
 | 
			
		||||
    GlobalSetting(String path, Object value) {
 | 
			
		||||
        this.path = path;
 | 
			
		||||
        this.value = value;
 | 
			
		||||
        String[] pathParts = path.split("\\.");
 | 
			
		||||
        this.parent = String.join(".", Arrays.copyOfRange(pathParts, 0, pathParts.length - 1));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the full config path for this setting
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The full config path for this setting</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getPath() {
 | 
			
		||||
        return path;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the parent item of the defined path
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The parent node</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getParent() {
 | 
			
		||||
        return parent;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the value of this setting
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The value of this setting</p>
 | 
			
		||||
     */
 | 
			
		||||
    Object getDefaultValue() {
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,263 @@
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A class which keeps track of all default NPC settings and all global settings
 | 
			
		||||
 */
 | 
			
		||||
public class GlobalSettings {
 | 
			
		||||
 | 
			
		||||
    private final Map<Material, Double> materialBasePrices = new HashMap<>();
 | 
			
		||||
    private final Map<Material, Double> materialPricePerDurabilityPoints = new HashMap<>();
 | 
			
		||||
    private final Map<Enchantment, Double> enchantmentModifiers = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
    private final Map<NPCSetting, Object> defaultNPCSettings = new HashMap<>();
 | 
			
		||||
    private final Map<GlobalSetting, Object> globalSettings = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
    private final YamlStorage defaultConfig;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Instantiates a new "Settings"
 | 
			
		||||
     *
 | 
			
		||||
     * @param plugin <p>A reference to the blacksmith plugin</p>
 | 
			
		||||
     */
 | 
			
		||||
    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 <p>The current value of the default NPC settings</p>
 | 
			
		||||
     */
 | 
			
		||||
    public Map<NPCSetting, Object> getDefaultNPCSettings() {
 | 
			
		||||
        return new HashMap<>(this.defaultNPCSettings);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets whether to use natural cost for cost calculation
 | 
			
		||||
     *
 | 
			
		||||
     * <p>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.</p>
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>Whether to use natural cost</p>
 | 
			
		||||
     */
 | 
			
		||||
    public boolean getUseNaturalCost() {
 | 
			
		||||
        return asBoolean(GlobalSetting.NATURAL_COST);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the base price for the given material
 | 
			
		||||
     *
 | 
			
		||||
     * @param material <p>The material to get the base price for</p>
 | 
			
		||||
     * @return <p>The base price for the material</p>
 | 
			
		||||
     */
 | 
			
		||||
    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 <p>The material to get the durability point price for</p>
 | 
			
		||||
     * @return <p>The durability point price for the material</p>
 | 
			
		||||
     */
 | 
			
		||||
    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 <p>The enchantment to get the cost for</p>
 | 
			
		||||
     * @return <p>The cost of each enchantment level</p>
 | 
			
		||||
     */
 | 
			
		||||
    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
 | 
			
		||||
     *
 | 
			
		||||
     * <p>This will throw an exception if used for a non-boolean value</p>
 | 
			
		||||
     *
 | 
			
		||||
     * @param setting <p>The setting to get the value of</p>
 | 
			
		||||
     * @return <p>The value of the given setting as a boolean</p>
 | 
			
		||||
     */
 | 
			
		||||
    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
 | 
			
		||||
     *
 | 
			
		||||
     * <p>This will throw an exception if used for a non-double setting</p>
 | 
			
		||||
     *
 | 
			
		||||
     * @param setting <p>The setting to get the value of</p>
 | 
			
		||||
     * @return <p>The value of the given setting as a double</p>
 | 
			
		||||
     */
 | 
			
		||||
    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 <p>The setting to get the value of</p>
 | 
			
		||||
     * @return <p>The current value</p>
 | 
			
		||||
     */
 | 
			
		||||
    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 <p>The root node of all global settings</p>
 | 
			
		||||
     */
 | 
			
		||||
    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<String, String> relevantKeys = getRelevantKeys(basePriceNode);
 | 
			
		||||
        for (String key : relevantKeys.keySet()) {
 | 
			
		||||
            Material material = Material.matchMaterial(relevantKeys.get(key));
 | 
			
		||||
            if (material != null) {
 | 
			
		||||
                materialBasePrices.put(material, basePriceNode.getDouble(key));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //Load all per-durability-point prices
 | 
			
		||||
        DataKey basePerDurabilityPriceNode = root.getRelative(GlobalSetting.PRICE_PER_DURABILITY_POINT.getParent());
 | 
			
		||||
        relevantKeys = getRelevantKeys(basePerDurabilityPriceNode);
 | 
			
		||||
        for (String key : relevantKeys.keySet()) {
 | 
			
		||||
            Material material = Material.matchMaterial(relevantKeys.get(key));
 | 
			
		||||
            if (material != null) {
 | 
			
		||||
                materialPricePerDurabilityPoints.put(material, basePerDurabilityPriceNode.getDouble(key));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //Load all enchantment prices
 | 
			
		||||
        DataKey enchantmentModifiersNode = root.getRelative(GlobalSetting.ENCHANTMENT_MODIFIER.getParent());
 | 
			
		||||
        relevantKeys = getRelevantKeys(basePerDurabilityPriceNode);
 | 
			
		||||
        for (String key : relevantKeys.keySet()) {
 | 
			
		||||
            Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(relevantKeys.get(key)));
 | 
			
		||||
            if (enchantment != null) {
 | 
			
		||||
                enchantmentModifiers.put(enchantment, enchantmentModifiersNode.getDouble(key));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets a map between relevant keys and their normalized name
 | 
			
		||||
     *
 | 
			
		||||
     * @param rootKey <p>The root data key containing sub-keys</p>
 | 
			
		||||
     * @return <p>Any sub-keys found that aren't the default</p>
 | 
			
		||||
     */
 | 
			
		||||
    private Map<String, String> getRelevantKeys(DataKey rootKey) {
 | 
			
		||||
        Map<String, String> 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 <p>The root node of all default NPC settings</p>
 | 
			
		||||
     */
 | 
			
		||||
    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()));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -5,10 +5,22 @@ import java.util.Arrays;
 | 
			
		||||
/**
 | 
			
		||||
 * An enum representing all of Blacksmith's settings
 | 
			
		||||
 */
 | 
			
		||||
public enum Setting {
 | 
			
		||||
public enum NPCSetting {
 | 
			
		||||
 | 
			
		||||
    BASE_PRICE("base-prices.default", 10.0),
 | 
			
		||||
    PRICE_PER_DURABILITY_POINT("price-per-durability-point.default", 1.0),
 | 
			
		||||
    DROP_ITEM("defaults.drop-item", true),
 | 
			
		||||
    DISABLE_COOL_DOWN("defaults.disable-cool-down", false),
 | 
			
		||||
    DISABLE_DELAY("defaults.disable-delay", false),
 | 
			
		||||
    FAIL_CHANCE("defaults.percent-chance-to-fail-reforge", 10),
 | 
			
		||||
    EXTRA_ENCHANTMENT_CHANCE("defaults.percent-chance-for-extra-enchantment", 5),
 | 
			
		||||
    MAX_ENCHANTMENTS("defaults.maximum-enchantments", 3),
 | 
			
		||||
    MAX_REFORGE_DELAY("defaults.delays-in-seconds.maximum", 30),
 | 
			
		||||
    MIN_REFORGE_DELAY("defaults.delays-in-seconds.minimum", 5),
 | 
			
		||||
    REFORGE_COOL_DOWN("defaults.delays-in-seconds.reforge-cool-down", 60),
 | 
			
		||||
    REFORGE_ABLE_ITEMS("defaults.reforge-able-items", new String[]{}),
 | 
			
		||||
 | 
			
		||||
    /*-----------
 | 
			
		||||
     | Messages |
 | 
			
		||||
     -----------*/
 | 
			
		||||
    BUSY_WITH_PLAYER_MESSAGE("defaults.messages.busy-with-player", "§cI'm busy at the moment. Come back later!"),
 | 
			
		||||
    BUSY_WITH_REFORGE_MESSAGE("defaults.messages.busy-with-reforge", "§cI'm working on it. Be patient!"),
 | 
			
		||||
    COOL_DOWN_UNEXPIRED_MESSAGE(
 | 
			
		||||
@@ -17,11 +29,6 @@ public enum Setting {
 | 
			
		||||
    COST_MESSAGE(
 | 
			
		||||
            "defaults.messages.cost",
 | 
			
		||||
            "§eIt will cost §a<price> §eto reforge that §a<item>§e! Click again to reforge!"),
 | 
			
		||||
    DROP_ITEM("defaults.drop-item", true),
 | 
			
		||||
    DISABLE_COOL_DOWN("defaults.disable-cool-down", false),
 | 
			
		||||
    DISABLE_DELAY("defaults.disable-delay", false),
 | 
			
		||||
    ENCHANTMENT_MODIFIER("enchantment-modifiers.default", 5),
 | 
			
		||||
    FAIL_CHANCE("defaults.percent-chance-to-fail-reforge", 10),
 | 
			
		||||
    FAIL_MESSAGE("defaults.messages.fail-reforge", "§cWhoops! Didn't mean to do that! Maybe next time?"),
 | 
			
		||||
    INSUFFICIENT_FUNDS_MESSAGE(
 | 
			
		||||
            "defaults.messages.insufficient-funds",
 | 
			
		||||
@@ -30,18 +37,12 @@ public enum Setting {
 | 
			
		||||
    ITEM_UNEXPECTEDLY_CHANGED_MESSAGE(
 | 
			
		||||
            "defaults.messages.item-changed-during-reforge",
 | 
			
		||||
            "§cThat's not the item you wanted to reforge before!"),
 | 
			
		||||
    EXTRA_ENCHANTMENT_CHANCE("defaults.percent-chance-for-extra-enchantment", 5),
 | 
			
		||||
    MAX_ENCHANTMENTS("defaults.maximum-enchantments", 3),
 | 
			
		||||
    MAX_REFORGE_DELAY("defaults.delays-in-seconds.maximum", 30),
 | 
			
		||||
    MIN_REFORGE_DELAY("defaults.delays-in-seconds.minimum", 5),
 | 
			
		||||
    REFORGE_COOL_DOWN("defaults.delays-in-seconds.reforge-cool-down", 60),
 | 
			
		||||
    START_REFORGE_MESSAGE("defaults.messages.start-reforge", "§eOk, let's see what I can do..."),
 | 
			
		||||
    SUCCESS_MESSAGE("defaults.messages.successful-reforge", "There you go! All better!"),
 | 
			
		||||
    NATURAL_COST("defaults.natural-cost", true);
 | 
			
		||||
    SUCCESS_MESSAGE("defaults.messages.successful-reforge", "There you go! All better!");
 | 
			
		||||
 | 
			
		||||
    private final String path;
 | 
			
		||||
    private final String childPath;
 | 
			
		||||
    private Object value;
 | 
			
		||||
    private final Object value;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Instantiates a new setting
 | 
			
		||||
@@ -49,7 +50,7 @@ public enum Setting {
 | 
			
		||||
     * @param path  <p>The full config path for this setting</p>
 | 
			
		||||
     * @param value <p>The default value of this setting</p>
 | 
			
		||||
     */
 | 
			
		||||
    Setting(String path, Object value) {
 | 
			
		||||
    NPCSetting(String path, Object value) {
 | 
			
		||||
        this.path = path;
 | 
			
		||||
        this.value = value;
 | 
			
		||||
        String[] pathParts = path.split("\\.");
 | 
			
		||||
@@ -74,78 +75,13 @@ public enum Setting {
 | 
			
		||||
        return childPath;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets this setting as a boolean
 | 
			
		||||
     *
 | 
			
		||||
     * <p>This will throw an exception if used for a non-boolean value</p>
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>This setting as a boolean</p>
 | 
			
		||||
     */
 | 
			
		||||
    public boolean asBoolean() {
 | 
			
		||||
        if (value instanceof String) {
 | 
			
		||||
            return Boolean.parseBoolean((String) value);
 | 
			
		||||
        } else {
 | 
			
		||||
            return (Boolean) value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets this setting as a double
 | 
			
		||||
     *
 | 
			
		||||
     * <p>This will throw an exception if used for a non-double setting</p>
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>This setting as a double</p>
 | 
			
		||||
     */
 | 
			
		||||
    public double asDouble() {
 | 
			
		||||
        if (value instanceof String) {
 | 
			
		||||
            return Double.parseDouble((String) value);
 | 
			
		||||
        } else if (value instanceof Integer) {
 | 
			
		||||
            return (Integer) value;
 | 
			
		||||
        } else {
 | 
			
		||||
            return (Double) value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets this setting as an integer
 | 
			
		||||
     *
 | 
			
		||||
     * <p>This will throw an exception if used for a non-integer setting</p>
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>This setting as an integer</p>
 | 
			
		||||
     */
 | 
			
		||||
    public int asInt() {
 | 
			
		||||
        if (value instanceof String) {
 | 
			
		||||
            return Integer.parseInt((String) value);
 | 
			
		||||
        } else {
 | 
			
		||||
            return (Integer) value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets this setting as a string
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>This setting as a string</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String asString() {
 | 
			
		||||
        return value.toString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the value of this setting
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The value of this setting</p>
 | 
			
		||||
     */
 | 
			
		||||
    Object get() {
 | 
			
		||||
    Object getDefaultValue() {
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the value of this setting
 | 
			
		||||
     *
 | 
			
		||||
     * @param value <p>The new value of this setting</p>
 | 
			
		||||
     */
 | 
			
		||||
    void set(Object value) {
 | 
			
		||||
        this.value = value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										322
									
								
								src/main/java/net/knarcraft/blacksmith/config/NPCSettings.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										322
									
								
								src/main/java/net/knarcraft/blacksmith/config/NPCSettings.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,322 @@
 | 
			
		||||
package net.knarcraft.blacksmith.config;
 | 
			
		||||
 | 
			
		||||
import net.citizensnpcs.api.util.DataKey;
 | 
			
		||||
import org.bukkit.Material;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A class which keeps track of all Blacksmith settings/config values for one NPC
 | 
			
		||||
 */
 | 
			
		||||
public class NPCSettings {
 | 
			
		||||
 | 
			
		||||
    private final List<Material> reforgeAbleItems = new ArrayList<>();
 | 
			
		||||
    private final Map<NPCSetting, Object> currentValues = new HashMap<>();
 | 
			
		||||
    private final GlobalSettings globalSettings;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Instantiates a new "Settings" object
 | 
			
		||||
     */
 | 
			
		||||
    public NPCSettings(GlobalSettings globalSettings) {
 | 
			
		||||
        this.globalSettings = globalSettings;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Loads variables from the given data key
 | 
			
		||||
     *
 | 
			
		||||
     * @param key <p>The data key to load variables from</p>
 | 
			
		||||
     */
 | 
			
		||||
    public void loadVariables(DataKey key) {
 | 
			
		||||
        for (NPCSetting setting : NPCSetting.values()) {
 | 
			
		||||
            if (key.keyExists(setting.getChildPath())) {
 | 
			
		||||
                currentValues.put(setting, key.getRaw(setting.getChildPath()));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        //Updates the list of reforge-able items/materials
 | 
			
		||||
        updateReforgeAbleItems();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Saves variables to the given data key
 | 
			
		||||
     *
 | 
			
		||||
     * @param key <p>The data key to save variables to</p>
 | 
			
		||||
     */
 | 
			
		||||
    public void saveVariables(DataKey key) {
 | 
			
		||||
        for (NPCSetting setting : NPCSetting.values()) {
 | 
			
		||||
            key.setRaw(setting.getChildPath(), currentValues.get(setting));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when the blacksmith is busy with another player
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The busy with player message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getBusyWithPlayerMessage() {
 | 
			
		||||
        return asString(NPCSetting.BUSY_WITH_PLAYER_MESSAGE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when the blacksmith is busy with reforging an item
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The busy reforging message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getBusyReforgingMessage() {
 | 
			
		||||
        return asString(NPCSetting.BUSY_WITH_REFORGE_MESSAGE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to use for displaying an item's cost
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The message to use for displaying item cost</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getCostMessage() {
 | 
			
		||||
        return asString(NPCSetting.COST_MESSAGE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when a blacksmith has been given an invalid item
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The invalid item message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getInvalidItemMessage() {
 | 
			
		||||
        return asString(NPCSetting.INVALID_ITEM_MESSAGE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when a blacksmith starts reforging an item
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The start reforge message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getStartReforgeMessage() {
 | 
			
		||||
        return asString(NPCSetting.START_REFORGE_MESSAGE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when a blacksmith has successfully repaired an item
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The reforge success message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getSuccessMessage() {
 | 
			
		||||
        return asString(NPCSetting.SUCCESS_MESSAGE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when a blacksmith has failed to repair an item
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The reforge fail message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getFailMessage() {
 | 
			
		||||
        return asString(NPCSetting.FAIL_MESSAGE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when a player cannot afford re-forging an item
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The insufficient funds message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getInsufficientFundsMessage() {
 | 
			
		||||
        return asString(NPCSetting.INSUFFICIENT_FUNDS_MESSAGE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when a blacksmith is still affected by a cool-down
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The cool down unexpired message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getCoolDownUnexpiredMessage() {
 | 
			
		||||
        return asString(NPCSetting.COOL_DOWN_UNEXPIRED_MESSAGE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when a player has changed the item they're trying to reforge
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The item changed message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getItemChangedMessage() {
 | 
			
		||||
        return asString(NPCSetting.ITEM_UNEXPECTEDLY_CHANGED_MESSAGE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets all items reforge-able by this NPC
 | 
			
		||||
     *
 | 
			
		||||
     * <p>If this is not empty, only the items specified can be repaired by this NPC.</p>
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>All items reforge-able by this NPC</p>
 | 
			
		||||
     */
 | 
			
		||||
    public List<Material> getReforgeAbleItems() {
 | 
			
		||||
        return new ArrayList<>(reforgeAbleItems);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the minimum delay used to wait for a re-forge to finish.
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The minimum reforge delay</p>
 | 
			
		||||
     */
 | 
			
		||||
    public int getMinReforgeDelay() {
 | 
			
		||||
        return asInt(NPCSetting.MIN_REFORGE_DELAY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the maximum delay used to wait for a re-forge to finish
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The maximum reforge delay</p>
 | 
			
		||||
     */
 | 
			
		||||
    public int getMaxReforgeDelay() {
 | 
			
		||||
        return asInt(NPCSetting.MAX_REFORGE_DELAY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the cool-down between each reforge
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The reforge cool-down</p>
 | 
			
		||||
     */
 | 
			
		||||
    public int getReforgeCoolDown() {
 | 
			
		||||
        return asInt(NPCSetting.REFORGE_COOL_DOWN);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the chance to fail a re-forge
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The fail chance</p>
 | 
			
		||||
     */
 | 
			
		||||
    public int getFailChance() {
 | 
			
		||||
        return asInt(NPCSetting.FAIL_CHANCE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the chance for adding an extra enchantment to an item
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The extra enchantment chance</p>
 | 
			
		||||
     */
 | 
			
		||||
    public int getExtraEnchantmentChance() {
 | 
			
		||||
        return asInt(NPCSetting.EXTRA_ENCHANTMENT_CHANCE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the max number of enchantment to add to an item
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The maximum enchantments</p>
 | 
			
		||||
     */
 | 
			
		||||
    public int getMaxEnchantments() {
 | 
			
		||||
        return asInt(NPCSetting.MAX_ENCHANTMENTS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets whether an item should be dropped on the ground instead of being given to the player
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>Whether to drop reforged items on the ground</p>
 | 
			
		||||
     */
 | 
			
		||||
    public boolean getDropItem() {
 | 
			
		||||
        return asBoolean(NPCSetting.DROP_ITEM);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets whether to disable the reforge-cool-down
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>Whether to disable the reforge-cool-down</p>
 | 
			
		||||
     */
 | 
			
		||||
    public boolean getDisableCoolDown() {
 | 
			
		||||
        return asBoolean(NPCSetting.DISABLE_COOL_DOWN);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets whether to disable the delay between starting reforging and the re-forge finishing
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>Whether to disable the reforge delay</p>
 | 
			
		||||
     */
 | 
			
		||||
    public boolean getDisableDelay() {
 | 
			
		||||
        return asBoolean(NPCSetting.DISABLE_DELAY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the given value as a boolean
 | 
			
		||||
     *
 | 
			
		||||
     * <p>This will throw an exception if used for a non-boolean value</p>
 | 
			
		||||
     *
 | 
			
		||||
     * @param setting <p>The setting to get the value of</p>
 | 
			
		||||
     * @return <p>The value of the given setting as a boolean</p>
 | 
			
		||||
     */
 | 
			
		||||
    private boolean asBoolean(NPCSetting setting) {
 | 
			
		||||
        Object value = getValue(setting);
 | 
			
		||||
        if (value instanceof String) {
 | 
			
		||||
            return Boolean.parseBoolean((String) value);
 | 
			
		||||
        } else {
 | 
			
		||||
            return (Boolean) value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the given value as an integer
 | 
			
		||||
     *
 | 
			
		||||
     * <p>This will throw an exception if used for a non-integer setting</p>
 | 
			
		||||
     *
 | 
			
		||||
     * @param setting <p>The setting to get the value of</p>
 | 
			
		||||
     * @return <p>The value of the given setting as an integer</p>
 | 
			
		||||
     */
 | 
			
		||||
    private int asInt(NPCSetting setting) {
 | 
			
		||||
        Object value = getValue(setting);
 | 
			
		||||
        if (value instanceof String) {
 | 
			
		||||
            return Integer.parseInt((String) value);
 | 
			
		||||
        } else {
 | 
			
		||||
            return (Integer) value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the string value of the given setting
 | 
			
		||||
     *
 | 
			
		||||
     * @param setting <p>The setting to get the value of</p>
 | 
			
		||||
     * @return <p>The value of the given setting as a string</p>
 | 
			
		||||
     */
 | 
			
		||||
    private String asString(NPCSetting setting) {
 | 
			
		||||
        return getValue(setting).toString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the value of a setting, using the default if not set
 | 
			
		||||
     *
 | 
			
		||||
     * @param setting <p>The setting to get the value of</p>
 | 
			
		||||
     * @return <p>The current value</p>
 | 
			
		||||
     */
 | 
			
		||||
    private Object getValue(NPCSetting setting) {
 | 
			
		||||
        Object value = currentValues.get(setting);
 | 
			
		||||
        //If not set, use the default value from the config.yml file
 | 
			
		||||
        if (value == null) {
 | 
			
		||||
            Map<NPCSetting, Object> defaultNPCSettings = globalSettings.getDefaultNPCSettings();
 | 
			
		||||
            if (defaultNPCSettings.containsKey(setting)) {
 | 
			
		||||
                value = defaultNPCSettings.get(setting);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        //If not set in config.yml, use the default value from the enum
 | 
			
		||||
        if (value == null) {
 | 
			
		||||
            value = setting.getDefaultValue();
 | 
			
		||||
        }
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the reforge-able items according to the current value of the setting
 | 
			
		||||
     */
 | 
			
		||||
    private void updateReforgeAbleItems() {
 | 
			
		||||
        this.reforgeAbleItems.clear();
 | 
			
		||||
        List<?> reforgeAbleItems = (List<?>) currentValues.get(NPCSetting.REFORGE_ABLE_ITEMS);
 | 
			
		||||
        if (reforgeAbleItems == null) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (Object item : reforgeAbleItems) {
 | 
			
		||||
            if (item == null) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            Material material = Material.matchMaterial(String.valueOf(item));
 | 
			
		||||
            if (material != null) {
 | 
			
		||||
                this.reforgeAbleItems.add(material);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,357 +0,0 @@
 | 
			
		||||
package net.knarcraft.blacksmith.config;
 | 
			
		||||
 | 
			
		||||
import net.citizensnpcs.api.util.DataKey;
 | 
			
		||||
import net.citizensnpcs.api.util.YamlStorage;
 | 
			
		||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A class which keeps track of all Blacksmith settings/config values
 | 
			
		||||
 */
 | 
			
		||||
public class Settings {
 | 
			
		||||
 | 
			
		||||
    private String busyWithPlayerMessage = Setting.BUSY_WITH_PLAYER_MESSAGE.asString();
 | 
			
		||||
    private String busyReforgingMessage = Setting.BUSY_WITH_REFORGE_MESSAGE.asString();
 | 
			
		||||
    private String costMessage = Setting.COST_MESSAGE.asString();
 | 
			
		||||
    private String invalidItemMessage = Setting.INVALID_ITEM_MESSAGE.asString();
 | 
			
		||||
    private String startReforgeMessage = Setting.START_REFORGE_MESSAGE.asString();
 | 
			
		||||
    private String successMessage = Setting.SUCCESS_MESSAGE.asString();
 | 
			
		||||
    private String failMessage = Setting.FAIL_MESSAGE.asString();
 | 
			
		||||
    private String insufficientFundsMessage = Setting.INSUFFICIENT_FUNDS_MESSAGE.asString();
 | 
			
		||||
    private String coolDownUnexpiredMessage = Setting.COOL_DOWN_UNEXPIRED_MESSAGE.asString();
 | 
			
		||||
    private String itemChangedMessage = Setting.ITEM_UNEXPECTEDLY_CHANGED_MESSAGE.asString();
 | 
			
		||||
    private int minReforgeDelay = Setting.MIN_REFORGE_DELAY.asInt();
 | 
			
		||||
    private int maxReforgeDelay = Setting.MAX_REFORGE_DELAY.asInt();
 | 
			
		||||
    private int reforgeCoolDown = Setting.REFORGE_COOL_DOWN.asInt();
 | 
			
		||||
    private int failChance = Setting.FAIL_CHANCE.asInt();
 | 
			
		||||
    private int extraEnchantmentChance = Setting.EXTRA_ENCHANTMENT_CHANCE.asInt();
 | 
			
		||||
    private int maxEnchantments = Setting.MAX_ENCHANTMENTS.asInt();
 | 
			
		||||
    private boolean dropItem = Setting.DROP_ITEM.asBoolean();
 | 
			
		||||
    private boolean disableCoolDown = Setting.DISABLE_COOL_DOWN.asBoolean();
 | 
			
		||||
    private boolean disableDelay = Setting.DISABLE_DELAY.asBoolean();
 | 
			
		||||
    private boolean naturalCost = Setting.NATURAL_COST.asBoolean();
 | 
			
		||||
    private final YamlStorage config;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Instantiates a new "Settings"
 | 
			
		||||
     *
 | 
			
		||||
     * @param plugin <p>A reference to the blacksmith plugin</p>
 | 
			
		||||
     */
 | 
			
		||||
    public Settings(BlacksmithPlugin plugin) {
 | 
			
		||||
        config = 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
 | 
			
		||||
        config.load();
 | 
			
		||||
        DataKey root = config.getKey("");
 | 
			
		||||
        for (Setting setting : Setting.values()) {
 | 
			
		||||
            if (!root.keyExists(setting.getPath())) {
 | 
			
		||||
                //If the setting does not exist in the config file, add it
 | 
			
		||||
                root.setRaw(setting.getPath(), setting.get());
 | 
			
		||||
            } else {
 | 
			
		||||
                //Set the setting to the value found in the path
 | 
			
		||||
                setting.set(root.getRaw(setting.getPath()));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        //Save any modified values to disk
 | 
			
		||||
        config.save();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the configuration used for saving/loading from disk
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The configuration</p>
 | 
			
		||||
     */
 | 
			
		||||
    public YamlStorage getConfig() {
 | 
			
		||||
        return config;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Loads variables from the given data key
 | 
			
		||||
     *
 | 
			
		||||
     * @param key <p>The data key to load variables from</p>
 | 
			
		||||
     */
 | 
			
		||||
    public void loadVariables(DataKey key) {
 | 
			
		||||
        // Override defaults if they exist
 | 
			
		||||
        if (key.keyExists(Setting.BUSY_WITH_PLAYER_MESSAGE.getChildPath())) {
 | 
			
		||||
            busyWithPlayerMessage = key.getString(Setting.BUSY_WITH_PLAYER_MESSAGE.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.BUSY_WITH_REFORGE_MESSAGE.getChildPath())) {
 | 
			
		||||
            busyReforgingMessage = key.getString(Setting.BUSY_WITH_REFORGE_MESSAGE.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.COST_MESSAGE.getChildPath())) {
 | 
			
		||||
            costMessage = key.getString(Setting.COST_MESSAGE.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.INVALID_ITEM_MESSAGE.getChildPath())) {
 | 
			
		||||
            invalidItemMessage = key.getString(Setting.INVALID_ITEM_MESSAGE.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.START_REFORGE_MESSAGE.getChildPath())) {
 | 
			
		||||
            startReforgeMessage = key.getString(Setting.START_REFORGE_MESSAGE.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.SUCCESS_MESSAGE.getChildPath())) {
 | 
			
		||||
            successMessage = key.getString(Setting.SUCCESS_MESSAGE.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.FAIL_MESSAGE.getChildPath())) {
 | 
			
		||||
            failMessage = key.getString(Setting.FAIL_MESSAGE.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.INSUFFICIENT_FUNDS_MESSAGE.getChildPath())) {
 | 
			
		||||
            insufficientFundsMessage = key.getString(Setting.INSUFFICIENT_FUNDS_MESSAGE.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.COOL_DOWN_UNEXPIRED_MESSAGE.getChildPath())) {
 | 
			
		||||
            coolDownUnexpiredMessage = key.getString(Setting.COOL_DOWN_UNEXPIRED_MESSAGE.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.ITEM_UNEXPECTEDLY_CHANGED_MESSAGE.getChildPath())) {
 | 
			
		||||
            itemChangedMessage = key.getString(Setting.ITEM_UNEXPECTEDLY_CHANGED_MESSAGE.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.MIN_REFORGE_DELAY.getChildPath())) {
 | 
			
		||||
            minReforgeDelay = key.getInt(Setting.MIN_REFORGE_DELAY.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.MAX_REFORGE_DELAY.getChildPath())) {
 | 
			
		||||
            maxReforgeDelay = key.getInt(Setting.MAX_REFORGE_DELAY.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.REFORGE_COOL_DOWN.getChildPath())) {
 | 
			
		||||
            reforgeCoolDown = key.getInt(Setting.REFORGE_COOL_DOWN.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.FAIL_CHANCE.getChildPath())) {
 | 
			
		||||
            failChance = key.getInt(Setting.FAIL_CHANCE.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.MAX_ENCHANTMENTS.getChildPath())) {
 | 
			
		||||
            maxEnchantments = key.getInt(Setting.MAX_ENCHANTMENTS.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.EXTRA_ENCHANTMENT_CHANCE.getChildPath())) {
 | 
			
		||||
            extraEnchantmentChance = key.getInt(Setting.EXTRA_ENCHANTMENT_CHANCE.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.DROP_ITEM.getChildPath())) {
 | 
			
		||||
            dropItem = key.getBoolean(Setting.DROP_ITEM.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.DISABLE_COOL_DOWN.getChildPath())) {
 | 
			
		||||
            disableCoolDown = key.getBoolean(Setting.DISABLE_COOL_DOWN.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.DISABLE_DELAY.getChildPath())) {
 | 
			
		||||
            disableDelay = key.getBoolean(Setting.DISABLE_DELAY.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
        if (key.keyExists(Setting.NATURAL_COST.getChildPath())) {
 | 
			
		||||
            naturalCost = key.getBoolean(Setting.NATURAL_COST.getChildPath());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Saves variables to the given data key
 | 
			
		||||
     *
 | 
			
		||||
     * @param key <p>The data key to save variables to</p>
 | 
			
		||||
     */
 | 
			
		||||
    public void saveVariables(DataKey key) {
 | 
			
		||||
        //This saves variables to the specific NPC. 
 | 
			
		||||
        key.setString(Setting.BUSY_WITH_PLAYER_MESSAGE.getChildPath(), getBusyWithPlayerMessage());
 | 
			
		||||
        key.setString(Setting.BUSY_WITH_REFORGE_MESSAGE.getChildPath(), getBusyReforgingMessage());
 | 
			
		||||
        key.setString(Setting.COST_MESSAGE.getChildPath(), getCostMessage());
 | 
			
		||||
        key.setString(Setting.INVALID_ITEM_MESSAGE.getChildPath(), getInvalidItemMessage());
 | 
			
		||||
        key.setString(Setting.START_REFORGE_MESSAGE.getChildPath(), getStartReforgeMessage());
 | 
			
		||||
        key.setString(Setting.SUCCESS_MESSAGE.getChildPath(), getSuccessMessage());
 | 
			
		||||
        key.setString(Setting.FAIL_MESSAGE.getChildPath(), getFailMessage());
 | 
			
		||||
        key.setString(Setting.INSUFFICIENT_FUNDS_MESSAGE.getChildPath(), getInsufficientFundsMessage());
 | 
			
		||||
        key.setString(Setting.COOL_DOWN_UNEXPIRED_MESSAGE.getChildPath(), getCoolDownUnexpiredMessage());
 | 
			
		||||
        key.setString(Setting.ITEM_UNEXPECTEDLY_CHANGED_MESSAGE.getChildPath(), getItemChangedMessage());
 | 
			
		||||
        key.setInt(Setting.MIN_REFORGE_DELAY.getChildPath(), getMinReforgeDelay());
 | 
			
		||||
        key.setInt(Setting.MAX_REFORGE_DELAY.getChildPath(), getMaxReforgeDelay());
 | 
			
		||||
        key.setInt(Setting.REFORGE_COOL_DOWN.getChildPath(), getReforgeCoolDown());
 | 
			
		||||
        key.setInt(Setting.FAIL_CHANCE.getChildPath(), getFailChance());
 | 
			
		||||
        key.setInt(Setting.EXTRA_ENCHANTMENT_CHANCE.getChildPath(), getExtraEnchantmentChance());
 | 
			
		||||
        key.setInt(Setting.MAX_ENCHANTMENTS.getChildPath(), getMaxEnchantments());
 | 
			
		||||
        key.setBoolean(Setting.DROP_ITEM.getChildPath(), getDropItem());
 | 
			
		||||
        key.setBoolean(Setting.DISABLE_DELAY.getChildPath(), getDisableDelay());
 | 
			
		||||
        key.setBoolean(Setting.DISABLE_COOL_DOWN.getChildPath(), getDisableCoolDown());
 | 
			
		||||
        key.setBoolean(Setting.DISABLE_COOL_DOWN.getChildPath(), getDisableCoolDown());
 | 
			
		||||
        key.setBoolean(Setting.NATURAL_COST.getChildPath(), getNaturalCost());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when the blacksmith is busy with another player
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The busy with player message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getBusyWithPlayerMessage() {
 | 
			
		||||
        return busyWithPlayerMessage;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when the blacksmith is busy with reforging an item
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The busy reforging message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getBusyReforgingMessage() {
 | 
			
		||||
        return busyReforgingMessage;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to use for displaying an item's cost
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The message to use for displaying item cost</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getCostMessage() {
 | 
			
		||||
        return costMessage;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when a blacksmith has been given an invalid item
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The invalid item message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getInvalidItemMessage() {
 | 
			
		||||
        return invalidItemMessage;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when a blacksmith starts reforging an item
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The start reforge message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getStartReforgeMessage() {
 | 
			
		||||
        return startReforgeMessage;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when a blacksmith has successfully repaired an item
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The reforge success message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getSuccessMessage() {
 | 
			
		||||
        return successMessage;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when a blacksmith has failed to repair an item
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The reforge fail message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getFailMessage() {
 | 
			
		||||
        return failMessage;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when a player cannot afford re-forging an item
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The insufficient funds message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getInsufficientFundsMessage() {
 | 
			
		||||
        return insufficientFundsMessage;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when a blacksmith is still affected by a cool-down
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The cool down unexpired message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getCoolDownUnexpiredMessage() {
 | 
			
		||||
        return coolDownUnexpiredMessage;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the message to display when a player has changed the item they're trying to reforge
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The item changed message</p>
 | 
			
		||||
     */
 | 
			
		||||
    public String getItemChangedMessage() {
 | 
			
		||||
        return itemChangedMessage;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the minimum delay used to wait for a re-forge to finish.
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The minimum reforge delay</p>
 | 
			
		||||
     */
 | 
			
		||||
    public int getMinReforgeDelay() {
 | 
			
		||||
        return minReforgeDelay;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the maximum delay used to wait for a re-forge to finish
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The maximum reforge delay</p>
 | 
			
		||||
     */
 | 
			
		||||
    public int getMaxReforgeDelay() {
 | 
			
		||||
        return maxReforgeDelay;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the cool-down between each reforge
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The reforge cool-down</p>
 | 
			
		||||
     */
 | 
			
		||||
    public int getReforgeCoolDown() {
 | 
			
		||||
        return reforgeCoolDown;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the chance to fail a re-forge
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The fail chance</p>
 | 
			
		||||
     */
 | 
			
		||||
    public int getFailChance() {
 | 
			
		||||
        return failChance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the chance for adding an extra enchantment to an item
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The extra enchantment chance</p>
 | 
			
		||||
     */
 | 
			
		||||
    public int getExtraEnchantmentChance() {
 | 
			
		||||
        return extraEnchantmentChance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the max number of enchantment to add to an item
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>The maximum enchantments</p>
 | 
			
		||||
     */
 | 
			
		||||
    public int getMaxEnchantments() {
 | 
			
		||||
        return maxEnchantments;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets whether an item should be dropped on the ground instead of being given to the player
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>Whether to drop reforged items on the ground</p>
 | 
			
		||||
     */
 | 
			
		||||
    public boolean getDropItem() {
 | 
			
		||||
        return dropItem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets whether to disable the reforge-cool-down
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>Whether to disable the reforge-cool-down</p>
 | 
			
		||||
     */
 | 
			
		||||
    public boolean getDisableCoolDown() {
 | 
			
		||||
        return disableCoolDown;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets whether to disable the delay between starting reforging and the re-forge finishing
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>Whether to disable the reforge delay</p>
 | 
			
		||||
     */
 | 
			
		||||
    public boolean getDisableDelay() {
 | 
			
		||||
        return disableDelay;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets whether to use a natural cost calculation
 | 
			
		||||
     *
 | 
			
		||||
     * <p>The natural cost makes repairs more expensive the more damaged an item is, rather than the opposite.</p>
 | 
			
		||||
     *
 | 
			
		||||
     * @return <p>Whether to use a natural cost calculation</p>
 | 
			
		||||
     */
 | 
			
		||||
    public boolean getNaturalCost() {
 | 
			
		||||
        return naturalCost;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,29 +0,0 @@
 | 
			
		||||
package net.knarcraft.blacksmith.util;
 | 
			
		||||
 | 
			
		||||
public final class Sanitizer {
 | 
			
		||||
 | 
			
		||||
    private Sanitizer() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sanitizes an item name to the format used by this plugin
 | 
			
		||||
     *
 | 
			
		||||
     * @param itemName <p>The item name to sanitize</p>
 | 
			
		||||
     * @return <p>The sanitized name</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static String sanitizeItemName(String itemName) {
 | 
			
		||||
        return itemName.toLowerCase().replace('_', '-');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Converts a sanitized item name to the original name
 | 
			
		||||
     *
 | 
			
		||||
     * @param itemName <p>The item name to convert</p>
 | 
			
		||||
     * @return <p>The un-sanitized name</p>
 | 
			
		||||
     */
 | 
			
		||||
    public static String sanitizedToItemName(String itemName) {
 | 
			
		||||
        return itemName.toUpperCase().replace('-', '_');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										86
									
								
								src/main/resources/config.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/main/resources/config.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
			
		||||
# Blacksmith Configuration
 | 
			
		||||
 | 
			
		||||
# The settings which apply to all Blacksmith NPCs
 | 
			
		||||
global:
 | 
			
		||||
  # The minimum price of each cost
 | 
			
		||||
  base-price:
 | 
			
		||||
    # You can add, for example "diamond-sword: 15.3" to change the base cost for a specific item
 | 
			
		||||
    default: 10.0
 | 
			
		||||
 | 
			
		||||
  # The additional cost for each durability point missing (natural cost) or present (not natural cost)
 | 
			
		||||
  price-per-durability-point:
 | 
			
		||||
    # You can add, for example "diamond-sword: 0.09" to change the base cost for a specific item
 | 
			
		||||
    default: 0.005
 | 
			
		||||
 | 
			
		||||
  # The additional cost for each enchantment level present on an item
 | 
			
		||||
  enchantment-cost:
 | 
			
		||||
    # You can add, for example "arrow-infinite: 0.09" to change the enchantment cost for a specific enchantment
 | 
			
		||||
    default: 5
 | 
			
		||||
 | 
			
		||||
  # Natural cost makes re-forging more expensive the more damaged the item is. Disabling this will enable the legacy 
 | 
			
		||||
  #  blacksmith behavior instead
 | 
			
		||||
  natural-cost: true
 | 
			
		||||
 | 
			
		||||
# The settings which are set to any new NPC. To change any of these settings for an existing NPC, you must change the 
 | 
			
		||||
#  Citizens NPC file
 | 
			
		||||
defaults:
 | 
			
		||||
  # Whether the item will drop a re-forged item on the ground, instead of putting it into the user's inventory
 | 
			
		||||
  drop-item: true
 | 
			
		||||
 | 
			
		||||
  # The items a blacksmith is able to reforge. Setting this only allows the NPC to repair the listed items
 | 
			
		||||
  reforge-able-items: [ ]
 | 
			
		||||
 | 
			
		||||
  # Whether to disable the cool-down period between each re-forge
 | 
			
		||||
  disable-cool-down: false
 | 
			
		||||
 | 
			
		||||
  # Whether to disable the re-forge delay, making re-forging complete instantly
 | 
			
		||||
  disable-delay: false
 | 
			
		||||
 | 
			
		||||
  # The chance to fail a re-forge, which only repairs the item a tiny bit or not at all (0-100)
 | 
			
		||||
  percent-chance-to-fail-reforge: 10
 | 
			
		||||
 | 
			
		||||
  # The chance that an enchantment will be added to the re-forged item (0-100)
 | 
			
		||||
  percent-chance-for-extra-enchantment: 5
 | 
			
		||||
 | 
			
		||||
  # The maximum number of enchantments the blacksmith will try to add
 | 
			
		||||
  maximum-enchantments: 3
 | 
			
		||||
 | 
			
		||||
  # All settable delays
 | 
			
		||||
  delays-in-seconds:
 | 
			
		||||
    maximum: 30 # The maximum time for a re-forge to finish
 | 
			
		||||
 | 
			
		||||
    minimum: 5 # The minimum time for a re-forge to finish
 | 
			
		||||
 | 
			
		||||
    reforge-cool-down: 60 # The cool-down period between each re-forge
 | 
			
		||||
 | 
			
		||||
  # All messages used by the NPC
 | 
			
		||||
  messages:
 | 
			
		||||
    # The message to display when another player is using the blacksmith
 | 
			
		||||
    busy-with-player: "§cI'm busy at the moment. Come back later!"
 | 
			
		||||
 | 
			
		||||
    # The message to display when the blacksmith is working on the re-forge
 | 
			
		||||
    busy-with-reforge: "§cI'm working on it. Be patient!"
 | 
			
		||||
 | 
			
		||||
    # The message to display when the blacksmith is still on a cool-down from the previous re-forging
 | 
			
		||||
    cool-down-not-expired: "§cYou've already had your chance! Give me a break!"
 | 
			
		||||
 | 
			
		||||
    # The message to display when informing a player about the re-forge cost
 | 
			
		||||
    cost: "§eIt will cost §a<price> §eto reforge that §a<item>§e! Click again to reforge!"
 | 
			
		||||
 | 
			
		||||
    # The message to display when the blacksmith fails to re-forge an item
 | 
			
		||||
    fail-reforge: "§cWhoops! Didn't mean to do that! Maybe next time?"
 | 
			
		||||
 | 
			
		||||
    # The message to display when a player cannot pay for the re-forge
 | 
			
		||||
    insufficient-funds: "§cYou don't have enough money to reforge that item!"
 | 
			
		||||
 | 
			
		||||
    # The message to display when holding an item the blacksmith is unable to re-forge
 | 
			
		||||
    invalid-item: "§cI'm sorry, but I don't know how to reforge that!"
 | 
			
		||||
 | 
			
		||||
    # The message to display when presenting a different item than the one just evaluated
 | 
			
		||||
    item-changed-during-reforge: "§cThat's not the item you wanted to reforge before!"
 | 
			
		||||
 | 
			
		||||
    # The message to display once the blacksmith starts re-forging
 | 
			
		||||
    start-reforge: "§eOk, let's see what I can do..."
 | 
			
		||||
 | 
			
		||||
    # The message to display once the re-forge has successfully finished
 | 
			
		||||
    successful-reforge: "There you go! All better!"
 | 
			
		||||
@@ -4,15 +4,14 @@ authors: [ EpicKnarvik97, aPunch, jrbudda, HurricanKai ]
 | 
			
		||||
version: 1.18.1
 | 
			
		||||
main: net.knarcraft.blacksmith.BlacksmithPlugin
 | 
			
		||||
depend: [ Citizens, Vault ]
 | 
			
		||||
softdepend: [ HyperConomy ]
 | 
			
		||||
 | 
			
		||||
api-version: 1.18
 | 
			
		||||
 | 
			
		||||
commands:
 | 
			
		||||
  blacksmithreload:
 | 
			
		||||
    permission: blacksmith.reload
 | 
			
		||||
  blacksmith:
 | 
			
		||||
    permission: blacksmith.admin
 | 
			
		||||
    description: reloads the config file for Blacksmith
 | 
			
		||||
permissions:
 | 
			
		||||
  blacksmith.reload:
 | 
			
		||||
    description: Allows the player to run the /reload command
 | 
			
		||||
  blacksmith.admin:
 | 
			
		||||
    description: Allows blacksmith configuration
 | 
			
		||||
    default: op
 | 
			
		||||
		Reference in New Issue
	
	Block a user