Adds optional ability to reforge anvils #15
All checks were successful
EpicKnarvik97/Blacksmith/pipeline/head This commit looks good

This commit is contained in:
Kristian Knarvik 2023-01-09 23:47:17 +01:00
parent a856aa03e0
commit 753c7c6275
10 changed files with 95 additions and 14 deletions

View File

@ -143,12 +143,14 @@ All currently supported presets, and available filters for each preset:
### Global-only options ### Global-only options
| Key | Value type | Description | | 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". | | 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". | | 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. | | 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). | | 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 | | 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) ### 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". | | 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 | | 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. | | 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 #### Messages

View File

@ -26,7 +26,8 @@ public enum GlobalSetting {
* *
* <p>This can be specified for each possible enchantment by setting enchantment-cost.enchantment_name</p> * <p>This can be specified for each possible enchantment by setting enchantment-cost.enchantment_name</p>
*/ */
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 * 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 * 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 path;
private final String parent; private final String parent;

View File

@ -252,6 +252,22 @@ public class GlobalSettings {
} }
} }
/**
* Gets the cost for repairing the given type of anvil
*
* @param material <p>The anvil material to repair</p>
* @return <p>The cost of repairing the anvil</p>
*/
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 * Gets the given value as a boolean
* *

View File

@ -62,6 +62,11 @@ public enum NPCSetting {
ENCHANTMENT_BLOCKLIST("enchantmentBlocklist", SettingValueType.STRING_LIST, new String[]{"binding_curse", ENCHANTMENT_BLOCKLIST("enchantmentBlocklist", SettingValueType.STRING_LIST, new String[]{"binding_curse",
"mending", "vanishing_curse"}, "enchantmentBlocklist"), "mending", "vanishing_curse"}, "enchantmentBlocklist"),
/**
* Whether to allow this blacksmith to repair anvils
*/
REPAIR_ANVILS("reforgeAnvils", SettingValueType.BOOLEAN, false, "reforgeAnvils"),
/*----------- /*-----------
| Messages | | Messages |
-----------*/ -----------*/

View File

@ -301,6 +301,15 @@ public class NPCSettings {
return asInt(NPCSetting.MAX_REFORGE_DELAY) <= 0; return asInt(NPCSetting.MAX_REFORGE_DELAY) <= 0;
} }
/**
* Gets whether this blacksmith is able to repair anvils
*
* @return <p>True if this blacksmith is able to repair anvils</p>
*/
public boolean getRepairAnvils() {
return ConfigHelper.asBoolean(getValue(NPCSetting.REPAIR_ANVILS));
}
/** /**
* Gets the given value as an integer * Gets the given value as an integer
* *

View File

@ -91,6 +91,7 @@ public class EconomyManager {
private static double getCost(ItemStack item) { private static double getCost(ItemStack item) {
GlobalSettings globalSettings = BlacksmithPlugin.getInstance().getSettings(); GlobalSettings globalSettings = BlacksmithPlugin.getInstance().getSettings();
Material material = item.getType(); Material material = item.getType();
//Calculate the base price //Calculate the base price
double price = globalSettings.getBasePrice(material); double price = globalSettings.getBasePrice(material);
@ -106,6 +107,11 @@ public class EconomyManager {
//Increase price for any enchantments //Increase price for any enchantments
price += getEnchantmentCost(item); price += getEnchantmentCost(item);
//Override the cost for anvils
if (ItemHelper.isAnvil(material, true)) {
price = globalSettings.getAnvilCost(material);
}
return price; return price;
} }

View File

@ -114,7 +114,7 @@ public class BlacksmithTrait extends Trait {
coolDowns.remove(playerId); coolDowns.remove(playerId);
} }
//Deny if permission is missing //Deny if permission is missing
if (!player.hasPermission("blacksmith.reforge")) { if (!player.hasPermission("blacksmith.use")) {
return false; return false;
} }
@ -157,8 +157,8 @@ public class BlacksmithTrait extends Trait {
if (session.isRunning()) { if (session.isRunning()) {
int timeRemaining = (int) ((session.getFinishTime() - System.currentTimeMillis()) / 1000); int timeRemaining = (int) ((session.getFinishTime() - System.currentTimeMillis()) / 1000);
boolean showExactTime = BlacksmithPlugin.getInstance().getSettings().getShowExactTime(); boolean showExactTime = BlacksmithPlugin.getInstance().getSettings().getShowExactTime();
sendNPCMessage(this.npc, player, StringFormatter.replacePlaceholder(config.getBusyReforgingMessage(), "{time}", sendNPCMessage(this.npc, player, StringFormatter.replacePlaceholder(config.getBusyReforgingMessage(),
TimeFormatter.formatTime(showExactTime, timeRemaining))); "{time}", TimeFormatter.formatTime(showExactTime, timeRemaining)));
return; return;
} }
if (session.endSession()) { if (session.endSession()) {
@ -179,14 +179,15 @@ public class BlacksmithTrait extends Trait {
ItemStack hand = player.getInventory().getItemInMainHand(); ItemStack hand = player.getInventory().getItemInMainHand();
//Refuse if not repairable, or if reforge-able items is set, but doesn't include the held item //Refuse if not repairable, or if reforge-able items is set, but doesn't include the held item
List<Material> reforgeAbleItems = config.getReforgeAbleItems(); List<Material> 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(), String invalidMessage = StringFormatter.replacePlaceholder(config.getInvalidItemMessage(),
"{title}", config.getBlacksmithTitle()); "{title}", config.getBlacksmithTitle());
sendNPCMessage(this.npc, player, invalidMessage); sendNPCMessage(this.npc, player, invalidMessage);
return; return;
} }
if (ItemHelper.getDamage(hand) == 0) { if (ItemHelper.getDamage(hand) == 0 && !ItemHelper.isAnvil(hand.getType(), true)) {
sendNPCMessage(this.npc, player, config.getNotDamagedMessage()); sendNPCMessage(this.npc, player, config.getNotDamagedMessage());
return; return;
} }

View File

@ -6,6 +6,7 @@ import net.knarcraft.blacksmith.config.NPCSettings;
import net.knarcraft.blacksmith.manager.EconomyManager; import net.knarcraft.blacksmith.manager.EconomyManager;
import net.knarcraft.blacksmith.util.InputParsingHelper; import net.knarcraft.blacksmith.util.InputParsingHelper;
import net.knarcraft.blacksmith.util.ItemHelper; import net.knarcraft.blacksmith.util.ItemHelper;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -129,6 +130,11 @@ public class ReforgeSession implements Runnable {
// Remove any damage done to the item // Remove any damage done to the item
updateDamage(itemToReforge, 0); updateDamage(itemToReforge, 0);
//Replace damaged anvils with a normal anvil
if (ItemHelper.isAnvil(itemToReforge.getType(), true)) {
itemToReforge.setType(Material.ANVIL);
}
// Add random enchantments // Add random enchantments
int roll = random.nextInt(100); int roll = random.nextInt(100);
if (!(roll < config.getExtraEnchantmentChance() && if (!(roll < config.getExtraEnchantmentChance() &&

View File

@ -61,4 +61,17 @@ public final class ItemHelper {
return reforgeAbleMaterials; return reforgeAbleMaterials;
} }
/**
* Checks whether the given material is an anvil
*
* @param material <p>The material to check</p>
* @param requireDamaged <p>Whether only a damaged anvil should count</p>
* @return <p>True if the given material is an anvil</p>
*/
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);
}
} }

View File

@ -28,6 +28,12 @@ global:
# reforging delay messages, instead of just vaguely hinting at the remaining time. # reforging delay messages, instead of just vaguely hinting at the remaining time.
showExactTime: false 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 # 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 # Citizens NPC file, or use the /blacksmith command
defaults: defaults:
@ -51,6 +57,9 @@ defaults:
# The maximum number of enchantments the blacksmith will try to add # The maximum number of enchantments the blacksmith will try to add
maxEnchantments: 3 maxEnchantments: 3
# Whether the blacksmith will reforge anvils as a special case
reforgeAnvils: false
# All settable delays # All settable delays
delaysInSeconds: delaysInSeconds:
# The maximum time for a reforging to finish # The maximum time for a reforging to finish