diff --git a/README.md b/README.md index 4c75e49..88dbc60 100644 --- a/README.md +++ b/README.md @@ -142,13 +142,15 @@ All currently supported presets, and available filters for each preset: ### Global-only options -| Key | Value type | Description | -|-------------------------|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| basePrice | positive decimal number | The base price which has to be paid regardless of the durability remaining for an item. Setting this without specifying a material sets the basePrice for any item the basePrice has not been set for. You can use for example "netherite*: 10" to set the value for any material beginning with "netherite". | -| pricePerDurabilityPoint | positive decimal number | The price added for each durability point present/missing (depends on whether natural cost is set to true or false). Setting this without specifying a material sets the pricePerDurabilityPoint for any item the pricePerDurabilityPoint has not been set for. You can use for example "netherite*: 10" to set the value for any material beginning with "netherite". | -| enchantmentCost | positive decimal number | The added cost for each level of an enchantment present on the item. The cost can be set for specific enchantments. Not specifying an enchantment sets the value for all enchantments without a set value. | -| useNaturalCost | true/false | If true, each missing durability will add to the cost (price = basePrice + missingDurability * pricePerDurabilityPoint + enchantmentCost). If false, durability will be used to calculate the cost instead of missingDurability (this was the behavior before natural cost was added). | -| showExactTime | true/false | If true, blacksmiths will display exact time remaining in minutes and seconds, instead of vague expressions | +| Key | Value type | Description | +|---------------------------|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| basePrice | positive decimal number | The base price which has to be paid regardless of the durability remaining for an item. Setting this without specifying a material sets the basePrice for any item the basePrice has not been set for. You can use for example "netherite*: 10" to set the value for any material beginning with "netherite". | +| pricePerDurabilityPoint | positive decimal number | The price added for each durability point present/missing (depends on whether natural cost is set to true or false). Setting this without specifying a material sets the pricePerDurabilityPoint for any item the pricePerDurabilityPoint has not been set for. You can use for example "netherite*: 10" to set the value for any material beginning with "netherite". | +| enchantmentCost | positive decimal number | The added cost for each level of an enchantment present on the item. The cost can be set for specific enchantments. Not specifying an enchantment sets the value for all enchantments without a set value. | +| useNaturalCost | true/false | If true, each missing durability will add to the cost (price = basePrice + missingDurability * pricePerDurabilityPoint + enchantmentCost). If false, durability will be used to calculate the cost instead of missingDurability (this was the behavior before natural cost was added). | +| showExactTime | true/false | If true, blacksmiths will display exact time remaining in minutes and seconds, instead of vague expressions | +| chippedAnvilReforgingCost | positive decimal number | The price for reforging a chipped anvil (slightly damaged). No other costs apply! | +| damagedAnvilReforgingCost | positive decimal number | The price for reforging a damaged anvil (very damaged). No other costs apply! | ### Per-npc (with default values set in config.yml) @@ -168,6 +170,7 @@ All currently supported presets, and available filters for each preset: | reforgeAbleItems | DIAMOND_LEGGINGS,GOLD-pickaxe,bow, etc. | Specifies which items this blacksmith is able to reforge. If set to "" or null, all normally repairable items can be repaired. If set to a list of items, only the items specified can be repaired. Some presets have been included for ease of use. Use a preset by specifying "preset:sword-smith" instead of a material such as "gold-pickaxe". | | blacksmithTitle | text string | The title displayed as part of the message explaining that a blacksmith doesn't recognize a player's held item | | enchantmentBlocklist | string list | A string list of all enchantments a blacksmith should not be allowed to add to items. | +| reforgeAnvils | true/false | Whether to allow the blacksmith to reforge anvils. If enabled, chipped and damaged anvils will be replaced with a normal anvil. | #### Messages diff --git a/src/main/java/net/knarcraft/blacksmith/config/GlobalSetting.java b/src/main/java/net/knarcraft/blacksmith/config/GlobalSetting.java index 15c7d48..4613600 100644 --- a/src/main/java/net/knarcraft/blacksmith/config/GlobalSetting.java +++ b/src/main/java/net/knarcraft/blacksmith/config/GlobalSetting.java @@ -26,7 +26,8 @@ public enum GlobalSetting { * *

This can be specified for each possible enchantment by setting enchantment-cost.enchantment_name

*/ - ENCHANTMENT_COST("global.enchantmentCost.default", SettingValueType.POSITIVE_DOUBLE, 5.0, "enchantmentCost"), + ENCHANTMENT_COST("global.enchantmentCost.default", SettingValueType.POSITIVE_DOUBLE, 5.0, + "enchantmentCost"), /** * Whether the cost should increase for damage taken, as opposed to increase for durability present @@ -36,7 +37,19 @@ public enum GlobalSetting { /** * Whether to show exact time when displaying the wait time for a reforging or the cool-down */ - SHOW_EXACT_TIME("global.showExactTime", SettingValueType.BOOLEAN, false, "showExactTime"); + SHOW_EXACT_TIME("global.showExactTime", SettingValueType.BOOLEAN, false, "showExactTime"), + + /** + * The cost for repairing a chipped anvil + */ + ANVIL_CHIPPED_COST("global.chippedAnvilReforgingCost", SettingValueType.POSITIVE_DOUBLE, 10.0, + "chippedAnvilReforgingCost"), + + /** + * The cost for repairing a damaged anvil + */ + ANVIL_DAMAGED_COST("global.damagedAnvilReforgingCost", SettingValueType.POSITIVE_DOUBLE, 20.0, + "damagedAnvilReforgingCost"); private final String path; private final String parent; diff --git a/src/main/java/net/knarcraft/blacksmith/config/GlobalSettings.java b/src/main/java/net/knarcraft/blacksmith/config/GlobalSettings.java index 5c5414b..7087ca9 100644 --- a/src/main/java/net/knarcraft/blacksmith/config/GlobalSettings.java +++ b/src/main/java/net/knarcraft/blacksmith/config/GlobalSettings.java @@ -252,6 +252,22 @@ public class GlobalSettings { } } + /** + * Gets the cost for repairing the given type of anvil + * + * @param material

The anvil material to repair

+ * @return

The cost of repairing the anvil

+ */ + public double getAnvilCost(Material material) { + if (material == Material.CHIPPED_ANVIL) { + return asDouble(GlobalSetting.ANVIL_CHIPPED_COST); + } else if (material == Material.DAMAGED_ANVIL) { + return asDouble(GlobalSetting.ANVIL_DAMAGED_COST); + } else { + throw new IllegalArgumentException("An unexpected item was encountered!"); + } + } + /** * Gets the given value as a boolean * diff --git a/src/main/java/net/knarcraft/blacksmith/config/NPCSetting.java b/src/main/java/net/knarcraft/blacksmith/config/NPCSetting.java index f932b10..56c81fe 100644 --- a/src/main/java/net/knarcraft/blacksmith/config/NPCSetting.java +++ b/src/main/java/net/knarcraft/blacksmith/config/NPCSetting.java @@ -62,6 +62,11 @@ public enum NPCSetting { ENCHANTMENT_BLOCKLIST("enchantmentBlocklist", SettingValueType.STRING_LIST, new String[]{"binding_curse", "mending", "vanishing_curse"}, "enchantmentBlocklist"), + /** + * Whether to allow this blacksmith to repair anvils + */ + REPAIR_ANVILS("reforgeAnvils", SettingValueType.BOOLEAN, false, "reforgeAnvils"), + /*----------- | Messages | -----------*/ diff --git a/src/main/java/net/knarcraft/blacksmith/config/NPCSettings.java b/src/main/java/net/knarcraft/blacksmith/config/NPCSettings.java index 61d13b4..67e248e 100644 --- a/src/main/java/net/knarcraft/blacksmith/config/NPCSettings.java +++ b/src/main/java/net/knarcraft/blacksmith/config/NPCSettings.java @@ -301,6 +301,15 @@ public class NPCSettings { return asInt(NPCSetting.MAX_REFORGE_DELAY) <= 0; } + /** + * Gets whether this blacksmith is able to repair anvils + * + * @return

True if this blacksmith is able to repair anvils

+ */ + public boolean getRepairAnvils() { + return ConfigHelper.asBoolean(getValue(NPCSetting.REPAIR_ANVILS)); + } + /** * Gets the given value as an integer * diff --git a/src/main/java/net/knarcraft/blacksmith/manager/EconomyManager.java b/src/main/java/net/knarcraft/blacksmith/manager/EconomyManager.java index f7d41c4..11e5c59 100644 --- a/src/main/java/net/knarcraft/blacksmith/manager/EconomyManager.java +++ b/src/main/java/net/knarcraft/blacksmith/manager/EconomyManager.java @@ -91,6 +91,7 @@ public class EconomyManager { private static double getCost(ItemStack item) { GlobalSettings globalSettings = BlacksmithPlugin.getInstance().getSettings(); Material material = item.getType(); + //Calculate the base price double price = globalSettings.getBasePrice(material); @@ -106,6 +107,11 @@ public class EconomyManager { //Increase price for any enchantments price += getEnchantmentCost(item); + + //Override the cost for anvils + if (ItemHelper.isAnvil(material, true)) { + price = globalSettings.getAnvilCost(material); + } return price; } diff --git a/src/main/java/net/knarcraft/blacksmith/trait/BlacksmithTrait.java b/src/main/java/net/knarcraft/blacksmith/trait/BlacksmithTrait.java index 174b9db..7eb1713 100644 --- a/src/main/java/net/knarcraft/blacksmith/trait/BlacksmithTrait.java +++ b/src/main/java/net/knarcraft/blacksmith/trait/BlacksmithTrait.java @@ -114,7 +114,7 @@ public class BlacksmithTrait extends Trait { coolDowns.remove(playerId); } //Deny if permission is missing - if (!player.hasPermission("blacksmith.reforge")) { + if (!player.hasPermission("blacksmith.use")) { return false; } @@ -157,8 +157,8 @@ public class BlacksmithTrait extends Trait { if (session.isRunning()) { int timeRemaining = (int) ((session.getFinishTime() - System.currentTimeMillis()) / 1000); boolean showExactTime = BlacksmithPlugin.getInstance().getSettings().getShowExactTime(); - sendNPCMessage(this.npc, player, StringFormatter.replacePlaceholder(config.getBusyReforgingMessage(), "{time}", - TimeFormatter.formatTime(showExactTime, timeRemaining))); + sendNPCMessage(this.npc, player, StringFormatter.replacePlaceholder(config.getBusyReforgingMessage(), + "{time}", TimeFormatter.formatTime(showExactTime, timeRemaining))); return; } if (session.endSession()) { @@ -179,14 +179,15 @@ public class BlacksmithTrait extends Trait { ItemStack hand = player.getInventory().getItemInMainHand(); //Refuse if not repairable, or if reforge-able items is set, but doesn't include the held item List reforgeAbleItems = config.getReforgeAbleItems(); - if (!isRepairable(hand) || (!reforgeAbleItems.isEmpty() && !reforgeAbleItems.contains(hand.getType()))) { + if ((!this.config.getRepairAnvils() || !ItemHelper.isAnvil(hand.getType(), false)) && + (!isRepairable(hand) || (!reforgeAbleItems.isEmpty() && !reforgeAbleItems.contains(hand.getType())))) { String invalidMessage = StringFormatter.replacePlaceholder(config.getInvalidItemMessage(), "{title}", config.getBlacksmithTitle()); sendNPCMessage(this.npc, player, invalidMessage); return; } - if (ItemHelper.getDamage(hand) == 0) { + if (ItemHelper.getDamage(hand) == 0 && !ItemHelper.isAnvil(hand.getType(), true)) { sendNPCMessage(this.npc, player, config.getNotDamagedMessage()); return; } diff --git a/src/main/java/net/knarcraft/blacksmith/trait/ReforgeSession.java b/src/main/java/net/knarcraft/blacksmith/trait/ReforgeSession.java index cd096a2..03ed165 100644 --- a/src/main/java/net/knarcraft/blacksmith/trait/ReforgeSession.java +++ b/src/main/java/net/knarcraft/blacksmith/trait/ReforgeSession.java @@ -6,6 +6,7 @@ import net.knarcraft.blacksmith.config.NPCSettings; import net.knarcraft.blacksmith.manager.EconomyManager; import net.knarcraft.blacksmith.util.InputParsingHelper; import net.knarcraft.blacksmith.util.ItemHelper; +import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -129,6 +130,11 @@ public class ReforgeSession implements Runnable { // Remove any damage done to the item updateDamage(itemToReforge, 0); + //Replace damaged anvils with a normal anvil + if (ItemHelper.isAnvil(itemToReforge.getType(), true)) { + itemToReforge.setType(Material.ANVIL); + } + // Add random enchantments int roll = random.nextInt(100); if (!(roll < config.getExtraEnchantmentChance() && diff --git a/src/main/java/net/knarcraft/blacksmith/util/ItemHelper.java b/src/main/java/net/knarcraft/blacksmith/util/ItemHelper.java index db2c759..67915b5 100644 --- a/src/main/java/net/knarcraft/blacksmith/util/ItemHelper.java +++ b/src/main/java/net/knarcraft/blacksmith/util/ItemHelper.java @@ -61,4 +61,17 @@ public final class ItemHelper { return reforgeAbleMaterials; } + /** + * Checks whether the given material is an anvil + * + * @param material

The material to check

+ * @param requireDamaged

Whether only a damaged anvil should count

+ * @return

True if the given material is an anvil

+ */ + public static boolean isAnvil(Material material, boolean requireDamaged) { + boolean isDamagedAnvil = material == Material.CHIPPED_ANVIL || material == Material.DAMAGED_ANVIL; + boolean isAnvil = isDamagedAnvil || material == Material.ANVIL; + return (requireDamaged && isDamagedAnvil) || (!requireDamaged && isAnvil); + } + } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 1de3689..0afe128 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -27,6 +27,12 @@ global: # Exact time displays the exact number of seconds and minutes remaining as part of the reforging cool-down and # reforging delay messages, instead of just vaguely hinting at the remaining time. showExactTime: false + + # The cost of fully repairing a chipped anvil + chippedAnvilReforgingCost: 10.0 + + # The cost of fully repairing a damaged anvil + damagedAnvilReforgingCost: 20.0 # 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, or use the /blacksmith command @@ -50,6 +56,9 @@ defaults: # The maximum number of enchantments the blacksmith will try to add maxEnchantments: 3 + + # Whether the blacksmith will reforge anvils as a special case + reforgeAnvils: false # All settable delays delaysInSeconds: