package net.knarcraft.blacksmith.config; import net.citizensnpcs.api.util.DataKey; import net.knarcraft.blacksmith.BlacksmithPlugin; import net.knarcraft.blacksmith.trait.BlacksmithTrait; import net.knarcraft.blacksmith.util.ConfigHelper; import net.knarcraft.blacksmith.util.InputParsingHelper; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemStack; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; /** * A class which keeps track of all Blacksmith settings/config values for one NPC */ public class NPCSettings { private final List reforgeAbleItems = new ArrayList<>(); private final List enchantmentBlocklist = new ArrayList<>(); private final Map 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

The data key to load variables from

*/ 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(); updateEnchantmentBlocklist(); } /** * Saves variables to the given data key * * @param key

The data key to save variables to

*/ public void saveVariables(DataKey key) { for (NPCSetting setting : NPCSetting.values()) { key.setRaw(setting.getChildPath(), currentValues.get(setting)); } } /** * Changes one setting to the given value * * @param setting

The setting to change

* @param newValue

The new value of the setting

*/ public void changeSetting(NPCSetting setting, Object newValue) { if (setting.getValueType() == SettingValueType.STRING_LIST) { //Workaround to make sure it's treated as the correct type currentValues.put(setting, ConfigHelper.asStringList(newValue)); } else { currentValues.put(setting, newValue); } if (setting == NPCSetting.REFORGE_ABLE_ITEMS) { updateReforgeAbleItems(); } if (setting == NPCSetting.ENCHANTMENT_BLOCKLIST) { updateEnchantmentBlocklist(); } } /** * Gets the raw current value of a setting * * @param setting

The setting to get the value of

* @return

The current value of the setting

*/ public Object getRawValue(NPCSetting setting) { return currentValues.get(setting); } /** * Gets the message to display when the blacksmith is busy with another player * * @return

The busy with player message

*/ 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

The busy reforging message

*/ public String getBusyReforgingMessage() { return asString(NPCSetting.BUSY_WITH_REFORGE_MESSAGE); } /** * Gets the message to use for displaying an item's cost * * @return

The message to use for displaying item cost

*/ public String getCostMessage() { return asString(NPCSetting.COST_MESSAGE); } /** * Gets the message to display when a blacksmith has been given an invalid item * * @return

The invalid item message

*/ public String getInvalidItemMessage() { return asString(NPCSetting.INVALID_ITEM_MESSAGE); } /** * Gets the message to display when the presented item is at full durability * * @return

The not damaged message

*/ public String getNotDamagedMessage() { return asString(NPCSetting.NOT_DAMAGED_MESSAGE); } /** * Gets the message to display when a blacksmith starts reforging an item * * @return

The start reforge message

*/ public String getStartReforgeMessage() { return asString(NPCSetting.START_REFORGE_MESSAGE); } /** * Gets the message to display when a blacksmith has successfully repaired an item * * @return

The reforge success message

*/ public String getSuccessMessage() { return asString(NPCSetting.SUCCESS_MESSAGE); } /** * Gets the message to display when a blacksmith has failed to repair an item * * @return

The reforge fail message

*/ public String getFailMessage() { return asString(NPCSetting.FAIL_MESSAGE); } /** * Gets the message to display when a player cannot afford re-forging an item * * @return

The insufficient funds message

*/ 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

The cool down unexpired message

*/ 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

The item changed message

*/ public String getItemChangedMessage() { return asString(NPCSetting.ITEM_UNEXPECTEDLY_CHANGED_MESSAGE); } /** * Gets all items reforge-able by this NPC * *

If this is not empty, only the items specified can be repaired by this NPC.

* * @return

All items reforge-able by this NPC

*/ public List getReforgeAbleItems() { return new ArrayList<>(this.reforgeAbleItems); } /** * Gets the list of blocked enchantments * * @return

The list of blocked enchantments

*/ public List getEnchantmentBlocklist() { return new ArrayList<>(this.enchantmentBlocklist); } /** * Gets the minimum delay used to wait for a reforging to finish. * * @return

The minimum reforge delay

*/ public int getMinReforgeDelay() { return asInt(NPCSetting.MIN_REFORGE_DELAY); } /** * Gets the maximum delay used to wait for a reforging to finish * * @return

The maximum reforge delay

*/ public int getMaxReforgeDelay() { return asInt(NPCSetting.MAX_REFORGE_DELAY); } /** * Gets the cool-down between each reforge * * @return

The reforge cool-down

*/ public int getReforgeCoolDown() { return asInt(NPCSetting.REFORGE_COOL_DOWN); } /** * Gets the chance to fail a reforging * * @return

The fail chance

*/ public int getFailChance() { return asInt(NPCSetting.FAIL_CHANCE); } /** * Gets the chance for adding an extra enchantment to an item * * @return

The extra enchantment chance

*/ public int getExtraEnchantmentChance() { return asInt(NPCSetting.EXTRA_ENCHANTMENT_CHANCE); } /** * Gets the max number of enchantment to add to an item * * @return

The maximum enchantments

*/ 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

Whether to drop reforged items on the ground

*/ public boolean getDropItem() { return ConfigHelper.asBoolean(getValue(NPCSetting.DROP_ITEM)); } /** * Gets the title of the blacksmith, describing which items it can reforge * * @return

The title of the blacksmith

*/ public String getBlacksmithTitle() { return asString(NPCSetting.BLACKSMITH_TITLE); } /** * Gets whether to disable the reforge-cool-down * * @return

Whether to disable the reforge-cool-down

*/ public boolean getDisableCoolDown() { return asInt(NPCSetting.REFORGE_COOL_DOWN) <= 0; } /** * Gets whether to disable the delay between starting reforging and the reforging finishing * * @return

Whether to disable the reforge delay

*/ public boolean getDisableDelay() { return asInt(NPCSetting.MAX_REFORGE_DELAY) <= 0; } /** * Gets the given value as an integer * *

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

* * @param setting

The setting to get the value of

* @return

The value of the given setting as an integer

*/ private int asInt(NPCSetting setting) { return ConfigHelper.asInt(getValue(setting)); } /** * Gets the string value of the given setting * * @param setting

The setting to get the value of

* @return

The value of the given setting as a string

*/ private String asString(NPCSetting setting) { return getValue(setting).toString(); } /** * Gets the value of a setting, using the default if not set * * @param setting

The setting to get the value of

* @return

The current value

*/ private Object getValue(NPCSetting setting) { Object value = currentValues.get(setting); //If not set, use the default value from the config.yml file if (value == null) { Map 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; } /** * Replaces placeholders in the given reforge-able value * * @param value

The value specified by a user

* @return

The value with placeholders replaced

*/ private Object replaceReforgeAblePresets(Object value) { if (value instanceof String string) { String[] list = string.split(","); List replaced = new ArrayList<>(list.length); for (String item : list) { replaced.add(SmithPreset.replacePreset(item)); } return String.join(",", replaced); } else if (value instanceof String[] stringList) { List replaced = new ArrayList<>(stringList.length); for (String item : stringList) { replaced.add(SmithPreset.replacePreset(item)); } return replaced.toArray(); } else { throw new IllegalArgumentException("Unexpected object type encountered!"); } } /** * Updates the list of blocked enchantments */ private void updateEnchantmentBlocklist() { this.enchantmentBlocklist.clear(); List newEnchantmentBlocklist = ConfigHelper.asStringList(getValue(NPCSetting.ENCHANTMENT_BLOCKLIST)); for (String item : newEnchantmentBlocklist) { if (InputParsingHelper.isEmpty(item)) { continue; } Enchantment enchantment = InputParsingHelper.matchEnchantment(item); if (enchantment != null) { this.enchantmentBlocklist.add(enchantment); } else { BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING, "Unable to verify " + item + " as a valid enchantment"); } } } /** * Updates the reforge-able items according to the current value of the setting */ private void updateReforgeAbleItems() { this.reforgeAbleItems.clear(); String newReforgeAbleItems = (String) currentValues.get(NPCSetting.REFORGE_ABLE_ITEMS); if (newReforgeAbleItems == null) { return; } //Convert any presets with a list of materials newReforgeAbleItems = (String) replaceReforgeAblePresets(newReforgeAbleItems); for (String item : newReforgeAbleItems.split(",")) { if (InputParsingHelper.isEmpty(item)) { continue; } Material material = InputParsingHelper.matchMaterial(item); if (material != null && BlacksmithTrait.isRepairable(new ItemStack(material, 1))) { this.reforgeAbleItems.add(material); } else { BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING, "Unable to verify " + item + " as a valid reforge-able item"); } } } }