Fixes some savage fail problems
All checks were successful
EpicKnarvik97/Blacksmith/pipeline/head This commit looks good
All checks were successful
EpicKnarvik97/Blacksmith/pipeline/head This commit looks good
Fixes item not being returned when salvage fails Removes some redundancy when giving back items Makes extended salvage return 50% of the salvage (no items if only one item would be returned) Adds a better message when failing to salvage extended salvage items Fixes a bug in the caching of smith presets
This commit is contained in:
parent
1d7e8a0732
commit
33ef557771
13
README.md
13
README.md
@ -170,10 +170,10 @@ All currently supported presets, and available filters for each preset:
|
|||||||
### Blacksmith global-only options
|
### Blacksmith global-only options
|
||||||
|
|
||||||
| Key | Value type | Default | Description |
|
| Key | Value type | Default | Description |
|
||||||
|---------------------------|-------------------------|-------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|---------------------------|-------------------------|----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| basePrice | positive decimal number | \[default: 10.0] | 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 | default: 10.0 | 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 | \[default: 0.005] | 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 | default: 0.005 | 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 | \[default: 5] | 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 | default: 5 | 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 | true | 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 | true | 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 | false | If true, blacksmiths will display exact time remaining in minutes and seconds, instead of vague expressions. |
|
| showExactTime | true/false | false | If true, blacksmiths will display exact time remaining in minutes and seconds, instead of vague expressions. |
|
||||||
| chippedAnvilReforgingCost | positive decimal number | 10.0 | The price for reforging a chipped anvil (slightly damaged). No other costs apply! |
|
| chippedAnvilReforgingCost | positive decimal number | 10.0 | The price for reforging a chipped anvil (slightly damaged). No other costs apply! |
|
||||||
@ -246,7 +246,7 @@ All currently supported presets, and available filters for each preset:
|
|||||||
#### Messages
|
#### Messages
|
||||||
|
|
||||||
| Message Key | Default | Explanation |
|
| Message Key | Default | Explanation |
|
||||||
|---------------------------------|-----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------|
|
|---------------------------------|-----------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| busyPlayerMessage | &cI'm busy at the moment. Come back later! | The message displayed when the scrapper is serving another player. |
|
| busyPlayerMessage | &cI'm busy at the moment. Come back later! | The message displayed when the scrapper is serving another player. |
|
||||||
| busySalvageMessage | &cI'm working on it. Be patient! I'll finish {time}! | The message displayed when the scrapper is busy salvaging an item. |
|
| busySalvageMessage | &cI'm working on it. Be patient! I'll finish {time}! | The message displayed when the scrapper is busy salvaging an item. |
|
||||||
| coolDownUnexpiredMessage | &cYou've already had your chance! Give me a break! I'll be ready {time}! | The message displayed when the player has to wait for the cool-down to expire before using the scrapper again. |
|
| coolDownUnexpiredMessage | &cYou've already had your chance! Give me a break! I'll be ready {time}! | The message displayed when the player has to wait for the cool-down to expire before using the scrapper again. |
|
||||||
@ -254,6 +254,7 @@ All currently supported presets, and available filters for each preset:
|
|||||||
| tooDamagedForSalvageMessage | &cThat item is too damaged to be salvaged into anything useful | The message displayed when a scrapper is presented with an item too damaged to produce salvage. |
|
| tooDamagedForSalvageMessage | &cThat item is too damaged to be salvaged into anything useful | The message displayed when a scrapper is presented with an item too damaged to produce salvage. |
|
||||||
| successSalvagedMessage | There you go! | The message displayed when a scrapper successfully repairs an item. |
|
| successSalvagedMessage | There you go! | The message displayed when a scrapper successfully repairs an item. |
|
||||||
| failSalvageMessage | &cWhoops! The item broke! Maybe next time? | The message displayed when a scrapper fails to salvage an item. |
|
| failSalvageMessage | &cWhoops! The item broke! Maybe next time? | The message displayed when a scrapper fails to salvage an item. |
|
||||||
|
| failExtendedSalvageMessage | &cWhoops! I was unable to extract much, if any, salvage! Maybe next time? | The message displayed when a scrapper fails to salvage an item without durability (only relevant is extended salvage is enabled). |
|
||||||
| itemChangedMessage | &cThat's not the item you wanted to salvage before! | The message displayed when a player changes their item after being shown the salvage cost. |
|
| itemChangedMessage | &cThat's not the item you wanted to salvage before! | The message displayed when a player changes their item after being shown the salvage cost. |
|
||||||
| startSalvageMessage | &eOk, let's see what I can do... | The message displayed when a scrapper starts salvaging an item. |
|
| startSalvageMessage | &eOk, let's see what I can do... | The message displayed when a scrapper starts salvaging an item. |
|
||||||
| insufficientFundsMessage | &cYou don't have enough money to salvage an item! | The message displayed when a player is unable to pay for salvaging an item. |
|
| insufficientFundsMessage | &cYou don't have enough money to salvage an item! | The message displayed when a player is unable to pay for salvaging an item. |
|
||||||
@ -264,7 +265,7 @@ All currently supported presets, and available filters for each preset:
|
|||||||
| partialSalvageMessage | &cI cannot extract all components from that damaged item.&r | The message displayed as part of costMessage's yield placeholder if only some components will be returned. |
|
| partialSalvageMessage | &cI cannot extract all components from that damaged item.&r | The message displayed as part of costMessage's yield placeholder if only some components will be returned. |
|
||||||
| cannotSalvageEnchantedMessage | &cI'm sorry, but I'm unable to salvage enchanted items! | The message displayed when telling a player that the scrapper cannot salvage enchanted items. |
|
| cannotSalvageEnchantedMessage | &cI'm sorry, but I'm unable to salvage enchanted items! | The message displayed when telling a player that the scrapper cannot salvage enchanted items. |
|
||||||
| cannotSalvageArmorTrimMessage | &cI'm sorry, but I'm unable to salvage armor trims! | The message displayed when telling a player that the scrapper cannot salvage items with armor trim. |
|
| cannotSalvageArmorTrimMessage | &cI'm sorry, but I'm unable to salvage armor trims! | The message displayed when telling a player that the scrapper cannot salvage items with armor trim. |
|
||||||
| armorTrimSalvageNotFoundMessage | &cI'm sorry, but I don't know how to salvage that armor trim! | The message displayed when telling a player that the scrapper cannot find the correct items to return as armor trim salvage. |
|
| armorTrimSalvageNotFoundMessage | &cI'm sorry, but I don't know how to salvage that armor trim! | The message displayed when telling a player that the scrapper cannot find the correct items to return as armor trim salvage. This will happen if more armor trim materials are added, or the Spigot API is changed. |
|
||||||
| cannotSalvageNetheriteMessage | &cI'm sorry, but I'm unable to salvage netherite items! | The message displayed when telling a player that the scrapper cannot salvage netherite items. |
|
| cannotSalvageNetheriteMessage | &cI'm sorry, but I'm unable to salvage netherite items! | The message displayed when telling a player that the scrapper cannot salvage netherite items. |
|
||||||
|
|
||||||
## Language customization
|
## Language customization
|
||||||
|
@ -46,7 +46,7 @@ public enum SmithPreset {
|
|||||||
|
|
||||||
private final SmithPresetFilter[] filters;
|
private final SmithPresetFilter[] filters;
|
||||||
private static final Map<SmithPreset, Set<String>> presetMaterialNames = new HashMap<>();
|
private static final Map<SmithPreset, Set<String>> presetMaterialNames = new HashMap<>();
|
||||||
private static final Map<SmithPresetFilter, Set<String>> filterMaterialNames = new HashMap<>();
|
private static final Map<SmithPreset, Map<SmithPresetFilter, Set<String>>> filterMaterialNames = new HashMap<>();
|
||||||
private static Set<Material> armor = null;
|
private static Set<Material> armor = null;
|
||||||
private static Set<Material> ranged = null;
|
private static Set<Material> ranged = null;
|
||||||
private static Set<Material> weapons = null;
|
private static Set<Material> weapons = null;
|
||||||
@ -145,8 +145,8 @@ public enum SmithPreset {
|
|||||||
materialNames = presetMaterialNames.get(preset);
|
materialNames = presetMaterialNames.get(preset);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (filterMaterialNames.containsKey(filter)) {
|
if (filterMaterialNames.containsKey(preset) && filterMaterialNames.get(preset).containsKey(filter)) {
|
||||||
materialNames = filterMaterialNames.get(filter);
|
materialNames = filterMaterialNames.get(preset).get(filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +154,8 @@ public enum SmithPreset {
|
|||||||
if (materialNames == null) {
|
if (materialNames == null) {
|
||||||
if (filter != null) {
|
if (filter != null) {
|
||||||
materialNames = preset.getMaterialNames(filter);
|
materialNames = preset.getMaterialNames(filter);
|
||||||
filterMaterialNames.put(filter, materialNames);
|
filterMaterialNames.putIfAbsent(preset, new HashMap<>());
|
||||||
|
filterMaterialNames.get(preset).put(filter, materialNames);
|
||||||
} else {
|
} else {
|
||||||
materialNames = preset.getMaterialNames();
|
materialNames = preset.getMaterialNames();
|
||||||
presetMaterialNames.put(preset, materialNames);
|
presetMaterialNames.put(preset, materialNames);
|
||||||
|
@ -127,10 +127,20 @@ public class ScrapperNPCSettings implements TraitSettings<ScrapperSetting> {
|
|||||||
* @return <p>The salvage fail message</p>
|
* @return <p>The salvage fail message</p>
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public String getFailMessage() {
|
public String getFailSalvageMessage() {
|
||||||
return asString(ScrapperSetting.FAIL_SALVAGE_MESSAGE);
|
return asString(ScrapperSetting.FAIL_SALVAGE_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the message to display when a scrapper fails to salvage an item without durability
|
||||||
|
*
|
||||||
|
* @return <p>The extended salvage fail message</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public String getFailExtendedSalvageMessage() {
|
||||||
|
return asString(ScrapperSetting.FAIL_SALVAGE_EXTENDED_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the message to use for displaying salvage cost
|
* Gets the message to use for displaying salvage cost
|
||||||
*
|
*
|
||||||
|
@ -146,6 +146,13 @@ public enum ScrapperSetting implements Setting {
|
|||||||
"next time?", "The message to display when a scrapper fails to salvage an item because of the " +
|
"next time?", "The message to display when a scrapper fails to salvage an item because of the " +
|
||||||
"fail chance.", true, true),
|
"fail chance.", true, true),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The message displayed if a salvage of an item without durability is unsuccessful
|
||||||
|
*/
|
||||||
|
FAIL_SALVAGE_EXTENDED_MESSAGE("failExtendedSalvageMessage", SettingValueType.STRING,
|
||||||
|
"&cWhoops! I was unable to extract much, if any, salvage! Maybe next time?",
|
||||||
|
"The message to display when the scrapper fails to salvage an item without durability", true, true),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The message displayed if a player presents a different item after seeing the price to reforge an item
|
* The message displayed if a player presents a different item after seeing the price to reforge an item
|
||||||
*/
|
*/
|
||||||
|
@ -34,7 +34,6 @@ public class ReforgeSession extends Session implements Runnable {
|
|||||||
private final ItemStack itemToReforge;
|
private final ItemStack itemToReforge;
|
||||||
private final BlacksmithNPCSettings config;
|
private final BlacksmithNPCSettings config;
|
||||||
private static List<String> enchantments = null;
|
private static List<String> enchantments = null;
|
||||||
private static final Random random = new Random();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new session
|
* Instantiates a new session
|
||||||
@ -123,17 +122,8 @@ public class ReforgeSession extends Session implements Runnable {
|
|||||||
* Gives the reforged item back to the player
|
* Gives the reforged item back to the player
|
||||||
*/
|
*/
|
||||||
private void giveReforgedItem() {
|
private void giveReforgedItem() {
|
||||||
if (this.config.getMaxReforgeDelay() > 0) {
|
giveResultingItem(this.config.getMaxReforgeDelay() > 0, this.config.getDropItem(), this.npc,
|
||||||
//If the player isn't online, or the player cannot fit the item, drop the item to prevent it from disappearing
|
this.itemToReforge);
|
||||||
if (this.config.getDropItem() || !this.player.isOnline() || this.player.getInventory().firstEmpty() == -1) {
|
|
||||||
this.player.getWorld().dropItemNaturally(this.npc.getEntity().getLocation(), this.itemToReforge);
|
|
||||||
} else {
|
|
||||||
this.player.getInventory().addItem(this.itemToReforge);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//It can be assumed as this happens instantly, that the player still has the item's previous slot selected
|
|
||||||
this.player.getInventory().setItemInMainHand(this.itemToReforge);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -156,7 +146,10 @@ public class ReforgeSession extends Session implements Runnable {
|
|||||||
*/
|
*/
|
||||||
private void succeedReforge() {
|
private void succeedReforge() {
|
||||||
// Remove any damage done to the item
|
// Remove any damage done to the item
|
||||||
updateDamage(this.itemToReforge, 0);
|
if (ItemHelper.updateDamage(this.itemToReforge, 0)) {
|
||||||
|
BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING, "Unable to update damage for " +
|
||||||
|
this.itemToReforge);
|
||||||
|
}
|
||||||
|
|
||||||
//Replace damaged anvils with a normal anvil
|
//Replace damaged anvils with a normal anvil
|
||||||
if (ItemHelper.isAnvil(this.itemToReforge.getType(), true)) {
|
if (ItemHelper.isAnvil(this.itemToReforge.getType(), true)) {
|
||||||
@ -216,15 +209,7 @@ public class ReforgeSession extends Session implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Damage the item
|
//Damage the item
|
||||||
short currentItemDurability = ItemHelper.getDurability(this.itemToReforge);
|
damageItemRandomly(this.itemToReforge);
|
||||||
short newDurability = (short) (currentItemDurability + (currentItemDurability * random.nextInt(8)));
|
|
||||||
short maxDurability = this.itemToReforge.getType().getMaxDurability();
|
|
||||||
if (newDurability <= 0) {
|
|
||||||
newDurability = (short) (maxDurability / 3);
|
|
||||||
} else if (currentItemDurability + newDurability > maxDurability) {
|
|
||||||
newDurability = (short) (maxDurability - random.nextInt(maxDurability - 25));
|
|
||||||
}
|
|
||||||
updateDamage(this.itemToReforge, maxDurability - newDurability);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -243,16 +228,4 @@ public class ReforgeSession extends Session implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the damage done to an item
|
|
||||||
*
|
|
||||||
* @param item <p>The item to update damage for</p>
|
|
||||||
* @param newDamage <p>The new damage done</p>
|
|
||||||
*/
|
|
||||||
private void updateDamage(ItemStack item, int newDamage) {
|
|
||||||
if (!ItemHelper.updateDamage(item, newDamage)) {
|
|
||||||
BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING, "Unable to change damage of " + item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,19 +6,18 @@ import net.knarcraft.blacksmith.config.scrapper.ScrapperNPCSettings;
|
|||||||
import net.knarcraft.blacksmith.manager.EconomyManager;
|
import net.knarcraft.blacksmith.manager.EconomyManager;
|
||||||
import net.knarcraft.blacksmith.util.ItemHelper;
|
import net.knarcraft.blacksmith.util.ItemHelper;
|
||||||
import net.knarcraft.blacksmith.util.SalvageHelper;
|
import net.knarcraft.blacksmith.util.SalvageHelper;
|
||||||
import org.bukkit.entity.Damageable;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
import org.bukkit.entity.LivingEntity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import static net.knarcraft.blacksmith.formatting.BlacksmithStringFormatter.sendNPCMessage;
|
import static net.knarcraft.blacksmith.formatting.BlacksmithStringFormatter.sendNPCMessage;
|
||||||
import static net.knarcraft.blacksmith.util.ItemHelper.updateDamage;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A representation of the session between a player and a scrapper
|
* A representation of the session between a player and a scrapper
|
||||||
@ -30,6 +29,7 @@ public class SalvageSession extends Session implements Runnable {
|
|||||||
private final ItemStack itemToSalvage;
|
private final ItemStack itemToSalvage;
|
||||||
private final ScrapperNPCSettings config;
|
private final ScrapperNPCSettings config;
|
||||||
private final List<ItemStack> salvage;
|
private final List<ItemStack> salvage;
|
||||||
|
private final int itemsConsumed;
|
||||||
private final int enchantmentLevels;
|
private final int enchantmentLevels;
|
||||||
protected final SalvageMethod salvageMethod;
|
protected final SalvageMethod salvageMethod;
|
||||||
private static final Random random = new Random();
|
private static final Random random = new Random();
|
||||||
@ -42,18 +42,20 @@ public class SalvageSession extends Session implements Runnable {
|
|||||||
* @param npc <p>The scrapper NPC involved in the session</p>
|
* @param npc <p>The scrapper NPC involved in the session</p>
|
||||||
* @param config <p>The config to use for the session</p>
|
* @param config <p>The config to use for the session</p>
|
||||||
* @param salvageMethod <p>The salvage method performed in this session</p>
|
* @param salvageMethod <p>The salvage method performed in this session</p>
|
||||||
|
* @param itemsConsumed <p>The number of items actually consumed, in case a salvaging fails</p>
|
||||||
*/
|
*/
|
||||||
SalvageSession(@NotNull ScrapperTrait scrapperTrait, @NotNull Player player, @NotNull NPC npc,
|
SalvageSession(@NotNull ScrapperTrait scrapperTrait, @NotNull Player player, @NotNull NPC npc,
|
||||||
@NotNull ScrapperNPCSettings config, @NotNull List<ItemStack> salvage,
|
@NotNull ScrapperNPCSettings config, @NotNull List<ItemStack> salvage,
|
||||||
@NotNull SalvageMethod salvageMethod) {
|
@NotNull SalvageMethod salvageMethod, int itemsConsumed) {
|
||||||
super(player);
|
super(player);
|
||||||
this.scrapperTrait = scrapperTrait;
|
this.scrapperTrait = scrapperTrait;
|
||||||
this.npc = npc;
|
this.npc = npc;
|
||||||
this.itemToSalvage = player.getInventory().getItemInMainHand();
|
this.itemToSalvage = player.getInventory().getItemInMainHand().clone();
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.salvage = salvage;
|
this.salvage = salvage;
|
||||||
this.enchantmentLevels = SalvageHelper.getTotalEnchantmentLevels(this.itemToSalvage);
|
this.enchantmentLevels = SalvageHelper.getTotalEnchantmentLevels(this.itemToSalvage);
|
||||||
this.salvageMethod = salvageMethod;
|
this.salvageMethod = salvageMethod;
|
||||||
|
this.itemsConsumed = itemsConsumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -88,7 +90,7 @@ public class SalvageSession extends Session implements Runnable {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
sendNPCMessage(this.npc, this.player, salvageItem() ? this.config.getSuccessMessage() : this.config.getFailMessage());
|
salvageItem();
|
||||||
|
|
||||||
//Stop the reforged item from displaying in the scrapper's hand
|
//Stop the reforged item from displaying in the scrapper's hand
|
||||||
if (this.npc.getEntity() instanceof Player) {
|
if (this.npc.getEntity() instanceof Player) {
|
||||||
@ -108,17 +110,13 @@ public class SalvageSession extends Session implements Runnable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Trues to salvage an item, and gives the return item
|
* Trues to salvage an item, and gives the return item
|
||||||
*
|
|
||||||
* @return <p>True if the salvage was successful. False otherwise.</p>
|
|
||||||
*/
|
*/
|
||||||
private boolean salvageItem() {
|
private void salvageItem() {
|
||||||
if (random.nextInt(100) < this.config.getFailChance()) {
|
if (random.nextInt(100) < this.config.getFailChance()) {
|
||||||
failSalvage();
|
failSalvage();
|
||||||
return false;
|
|
||||||
} else {
|
} else {
|
||||||
// Give the player the result of the salvage
|
|
||||||
giveSalvage();
|
giveSalvage();
|
||||||
return true;
|
sendNPCMessage(this.npc, this.player, this.config.getSuccessMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,19 +124,22 @@ public class SalvageSession extends Session implements Runnable {
|
|||||||
* The method to run when a crapper fails salvaging an item
|
* The method to run when a crapper fails salvaging an item
|
||||||
*/
|
*/
|
||||||
private void failSalvage() {
|
private void failSalvage() {
|
||||||
if (this.itemToSalvage.getItemMeta() instanceof Damageable) {
|
// Make sure the given amount is the same amount taken for salvage to avoid duplication
|
||||||
//Damage the item
|
this.itemToSalvage.setAmount(itemsConsumed);
|
||||||
short currentItemDurability = ItemHelper.getDurability(this.itemToSalvage);
|
|
||||||
short newDurability = (short) (currentItemDurability + (currentItemDurability * random.nextInt(8)));
|
if (ItemHelper.getMaxDurability(this.itemToSalvage) > 0) {
|
||||||
short maxDurability = this.itemToSalvage.getType().getMaxDurability();
|
//Damage the item if possible
|
||||||
if (newDurability <= 0) {
|
damageItemRandomly(this.itemToSalvage);
|
||||||
newDurability = (short) (maxDurability / 3);
|
giveResultingItem(this.config.getMaxSalvageDelay() > 0, this.config.getDropItem(), this.npc,
|
||||||
} else if (currentItemDurability + newDurability > maxDurability) {
|
this.itemToSalvage);
|
||||||
newDurability = (short) (maxDurability - random.nextInt(maxDurability - 25));
|
sendNPCMessage(this.npc, this.player, this.config.getFailSalvageMessage());
|
||||||
}
|
|
||||||
updateDamage(this.itemToSalvage, maxDurability - newDurability);
|
|
||||||
} else {
|
} else {
|
||||||
this.itemToSalvage.setAmount(Math.max(this.itemToSalvage.getAmount() - 1, 1));
|
// Give half the salvage
|
||||||
|
List<ItemStack> halfSalvage = SalvageHelper.pickRandomSalvage(this.salvage, new ArrayList<>(), 0.5);
|
||||||
|
for (ItemStack item : halfSalvage) {
|
||||||
|
giveResultingItem(this.config.getMaxSalvageDelay() > 0, this.config.getDropItem(), this.npc, item);
|
||||||
|
}
|
||||||
|
sendNPCMessage(this.npc, this.player, this.config.getFailExtendedSalvageMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,21 +150,8 @@ public class SalvageSession extends Session implements Runnable {
|
|||||||
// TODO: Find a better calculation than 1 enchantment level = 1 exp level
|
// TODO: Find a better calculation than 1 enchantment level = 1 exp level
|
||||||
// Gives the player back some of the EXP used on an item
|
// Gives the player back some of the EXP used on an item
|
||||||
this.player.giveExpLevels(this.enchantmentLevels);
|
this.player.giveExpLevels(this.enchantmentLevels);
|
||||||
if (this.config.getDropItem() || !this.player.isOnline() || this.player.getInventory().firstEmpty() == -1) {
|
|
||||||
// If the player isn't online, or the player cannot fit the item, drop the item to prevent it from
|
|
||||||
// disappearing, even if drop item is disabled.
|
|
||||||
for (ItemStack item : this.salvage) {
|
for (ItemStack item : this.salvage) {
|
||||||
this.player.getWorld().dropItemNaturally(this.npc.getEntity().getLocation(), item);
|
giveResultingItem(this.config.getMaxSalvageDelay() > 0, this.config.getDropItem(), this.npc, item);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (ItemStack item : this.salvage) {
|
|
||||||
if (ItemHelper.canFitItem(this.player.getInventory(), item)) {
|
|
||||||
this.player.getInventory().addItem(item);
|
|
||||||
} else {
|
|
||||||
// If the player cannot fit all the salvage, drop it on the ground
|
|
||||||
this.player.getWorld().dropItemNaturally(this.player.getLocation(), item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ public class ScrapperTrait extends CustomTrait<ScrapperSetting> {
|
|||||||
* @param player <p>The player to start the session for</p>
|
* @param player <p>The player to start the session for</p>
|
||||||
*/
|
*/
|
||||||
public void startSession(@NotNull Player player) {
|
public void startSession(@NotNull Player player) {
|
||||||
ItemStack itemInHand = player.getInventory().getItemInMainHand();
|
ItemStack itemInHand = player.getInventory().getItemInMainHand().clone();
|
||||||
List<Material> salvageAbleItems = getSettings().getSalvageAbleItems();
|
List<Material> salvageAbleItems = getSettings().getSalvageAbleItems();
|
||||||
boolean extended = getSettings().extendedSalvageEnabled();
|
boolean extended = getSettings().extendedSalvageEnabled();
|
||||||
|
|
||||||
@ -123,6 +123,7 @@ public class ScrapperTrait extends CustomTrait<ScrapperSetting> {
|
|||||||
if (salvageMethod == SalvageMethod.SALVAGE && !SalvageHelper.isSalvageable(player.getServer(), itemInHand)) {
|
if (salvageMethod == SalvageMethod.SALVAGE && !SalvageHelper.isSalvageable(player.getServer(), itemInHand)) {
|
||||||
sendNPCMessage(this.npc, player, StringFormatter.replacePlaceholder(getSettings().getInvalidItemMessage(),
|
sendNPCMessage(this.npc, player, StringFormatter.replacePlaceholder(getSettings().getInvalidItemMessage(),
|
||||||
"{title}", getSettings().getScrapperTitle()));
|
"{title}", getSettings().getScrapperTitle()));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the item is enchanted, and whether this blacksmith can salvage it
|
// Check if the item is enchanted, and whether this blacksmith can salvage it
|
||||||
@ -142,7 +143,9 @@ public class ScrapperTrait extends CustomTrait<ScrapperSetting> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Start a new scrapper session for the player
|
//Start a new scrapper session for the player
|
||||||
startSession(player, salvage, salvageMethod);
|
currentSessionStartTime = System.currentTimeMillis();
|
||||||
|
int itemsConsumed = SalvageHelper.getRequiredAmountForSalvage(player.getServer(), itemInHand);
|
||||||
|
session = new SalvageSession(this, player, npc, getSettings(), salvage, salvageMethod, itemsConsumed);
|
||||||
// Print the cost to the player
|
// Print the cost to the player
|
||||||
printCostMessage(player, itemInHand, EconomyManager.formatSalvageCost(salvageMethod), salvageMethod);
|
printCostMessage(player, itemInHand, EconomyManager.formatSalvageCost(salvageMethod), salvageMethod);
|
||||||
}
|
}
|
||||||
@ -176,20 +179,6 @@ public class ScrapperTrait extends CustomTrait<ScrapperSetting> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts a new scrapper session
|
|
||||||
*
|
|
||||||
* @param player <p>The player to start the session for</p>
|
|
||||||
* @param salvage <p>The salvage to return to the player</p>
|
|
||||||
* @param salvageMethod <p>The type of salvage performed</p>
|
|
||||||
*/
|
|
||||||
private void startSession(@NotNull Player player, @NotNull List<ItemStack> salvage,
|
|
||||||
@NotNull SalvageMethod salvageMethod) {
|
|
||||||
//Start a new scrapper session for the player
|
|
||||||
currentSessionStartTime = System.currentTimeMillis();
|
|
||||||
session = new SalvageSession(this, player, npc, getSettings(), salvage, salvageMethod);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean showExactTime() {
|
protected boolean showExactTime() {
|
||||||
return BlacksmithPlugin.getInstance().getGlobalScrapperSettings().showExactTime();
|
return BlacksmithPlugin.getInstance().getGlobalScrapperSettings().showExactTime();
|
||||||
|
@ -1,15 +1,22 @@
|
|||||||
package net.knarcraft.blacksmith.trait;
|
package net.knarcraft.blacksmith.trait;
|
||||||
|
|
||||||
|
import net.citizensnpcs.api.npc.NPC;
|
||||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||||
|
import net.knarcraft.blacksmith.util.ItemHelper;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.scheduler.BukkitScheduler;
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A runnable session for performing a reforging/salvage task
|
* A runnable session for performing a reforging/salvage task
|
||||||
*/
|
*/
|
||||||
public abstract class Session implements Runnable {
|
public abstract class Session implements Runnable {
|
||||||
|
|
||||||
|
protected static final Random random = new Random();
|
||||||
protected final Player player;
|
protected final Player player;
|
||||||
protected long finishTime;
|
protected long finishTime;
|
||||||
protected int taskId;
|
protected int taskId;
|
||||||
@ -85,6 +92,47 @@ public abstract class Session implements Runnable {
|
|||||||
taskId = scheduler.scheduleSyncDelayedTask(BlacksmithPlugin.getInstance(), this, actionDelay * 20L);
|
taskId = scheduler.scheduleSyncDelayedTask(BlacksmithPlugin.getInstance(), this, actionDelay * 20L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gives the resulting item to the player
|
||||||
|
*
|
||||||
|
* @param hasDelay <p>Whether the session was delayed, or if the item was processed instantly</p>
|
||||||
|
* @param dropItem <p>Whether the item should be dropped on the ground</p>
|
||||||
|
* @param npc <p>The NPC holding the item</p>
|
||||||
|
* @param itemToReturn <p>The item to return to the player</p>
|
||||||
|
*/
|
||||||
|
protected void giveResultingItem(boolean hasDelay, boolean dropItem, @NotNull NPC npc, @NotNull ItemStack itemToReturn) {
|
||||||
|
if (hasDelay) {
|
||||||
|
//If the player isn't online, or the player cannot fit the item, drop the item to prevent it from disappearing
|
||||||
|
if (dropItem || !this.player.isOnline() || !ItemHelper.canFitItem(this.player.getInventory(), itemToReturn)) {
|
||||||
|
this.player.getWorld().dropItemNaturally(npc.getEntity().getLocation(), itemToReturn);
|
||||||
|
} else {
|
||||||
|
this.player.getInventory().addItem(itemToReturn);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//It can be assumed as this happens instantly, that the player still has the item's previous slot selected
|
||||||
|
this.player.getInventory().setItemInMainHand(itemToReturn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Randomly damages the given item
|
||||||
|
*
|
||||||
|
* @param item <p>The item to damage</p>
|
||||||
|
*/
|
||||||
|
protected void damageItemRandomly(@NotNull ItemStack item) {
|
||||||
|
short currentItemDurability = ItemHelper.getDurability(item);
|
||||||
|
short newDurability = (short) (currentItemDurability + (currentItemDurability * random.nextInt(8)));
|
||||||
|
short maxDurability = item.getType().getMaxDurability();
|
||||||
|
if (newDurability <= 0) {
|
||||||
|
newDurability = (short) (maxDurability / 3);
|
||||||
|
} else if (currentItemDurability + newDurability > maxDurability) {
|
||||||
|
newDurability = (short) (maxDurability - random.nextInt(maxDurability - 25));
|
||||||
|
}
|
||||||
|
if (ItemHelper.updateDamage(item, maxDurability - newDurability)) {
|
||||||
|
BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING, "Unable to update damage for " + item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the delay for this session's action to finish
|
* Gets the delay for this session's action to finish
|
||||||
*
|
*
|
||||||
|
@ -83,16 +83,16 @@ public final class ItemHelper {
|
|||||||
*
|
*
|
||||||
* @param item <p>The item to update damage for</p>
|
* @param item <p>The item to update damage for</p>
|
||||||
* @param newDamage <p>The new damage done</p>
|
* @param newDamage <p>The new damage done</p>
|
||||||
* @return <p>True if the damage was updated. False if not damageable.</p>
|
* @return <p>False if the damage was updated. False if not damageable.</p>
|
||||||
*/
|
*/
|
||||||
public static boolean updateDamage(@NotNull ItemStack item, int newDamage) {
|
public static boolean updateDamage(@NotNull ItemStack item, int newDamage) {
|
||||||
ItemMeta meta = item.getItemMeta();
|
ItemMeta meta = item.getItemMeta();
|
||||||
if (!(meta instanceof Damageable damageable)) {
|
if (!(meta instanceof Damageable damageable)) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
damageable.setDamage(newDamage);
|
damageable.setDamage(newDamage);
|
||||||
item.setItemMeta(meta);
|
item.setItemMeta(meta);
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -246,13 +246,32 @@ public final class SalvageHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double percentageRemaining = (double) durability / maxDurability;
|
double percentageRemaining = (double) durability / maxDurability;
|
||||||
|
return pickRandomSalvage(recipeItems, trashSalvage, percentageRemaining);
|
||||||
|
}
|
||||||
|
|
||||||
int totalItems = totalItemAmount(recipeItems);
|
/**
|
||||||
|
* Picks random salvage from the given items
|
||||||
|
*
|
||||||
|
* @param itemsToChooseFrom <p>The salvage to choose from</p>
|
||||||
|
* @param trashSalvage <p>The salvage considered trash</p>
|
||||||
|
* @param percentageRemaining <p>The percentage remaining for the salvaged item (0-1)</p>
|
||||||
|
* @return <p>Random salvage</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static List<ItemStack> pickRandomSalvage(@NotNull List<ItemStack> itemsToChooseFrom,
|
||||||
|
@NotNull Collection<Material> trashSalvage,
|
||||||
|
double percentageRemaining) {
|
||||||
|
// Avoid an infinite loop
|
||||||
|
if (percentageRemaining > 1 || percentageRemaining < 0) {
|
||||||
|
percentageRemaining = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int totalItems = totalItemAmount(itemsToChooseFrom);
|
||||||
//Get the amount of recipe items to be returned
|
//Get the amount of recipe items to be returned
|
||||||
int itemsToReturn = (int) Math.floor(percentageRemaining * totalItems);
|
int itemsToReturn = (int) Math.floor(percentageRemaining * totalItems);
|
||||||
int bound = recipeItems.size();
|
int bound = itemsToChooseFrom.size();
|
||||||
|
|
||||||
List<ItemStack> goodItems = copyItems(recipeItems);
|
List<ItemStack> goodItems = copyItems(itemsToChooseFrom);
|
||||||
goodItems.removeIf((item) -> trashSalvage.contains(item.getType()));
|
goodItems.removeIf((item) -> trashSalvage.contains(item.getType()));
|
||||||
int goodSalvage = totalItemAmount(goodItems);
|
int goodSalvage = totalItemAmount(goodItems);
|
||||||
|
|
||||||
@ -260,7 +279,7 @@ public final class SalvageHelper {
|
|||||||
for (int i = 0; i < itemsToReturn; i++) {
|
for (int i = 0; i < itemsToReturn; i++) {
|
||||||
// Pick random item
|
// Pick random item
|
||||||
int itemIndex = SalvageHelper.random.nextInt(bound);
|
int itemIndex = SalvageHelper.random.nextInt(bound);
|
||||||
ItemStack itemStack = recipeItems.get(itemIndex);
|
ItemStack itemStack = itemsToChooseFrom.get(itemIndex);
|
||||||
|
|
||||||
// The selected item is trash, so skip it
|
// The selected item is trash, so skip it
|
||||||
if (trashSalvage.contains(itemStack.getType()) && i < goodSalvage) {
|
if (trashSalvage.contains(itemStack.getType()) && i < goodSalvage) {
|
||||||
@ -275,7 +294,6 @@ public final class SalvageHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
itemStack.setAmount(itemStack.getAmount() - 1);
|
itemStack.setAmount(itemStack.getAmount() - 1);
|
||||||
|
|
||||||
salvage.add(new ItemStack(itemStack.getType(), 1));
|
salvage.add(new ItemStack(itemStack.getType(), 1));
|
||||||
}
|
}
|
||||||
return salvage;
|
return salvage;
|
||||||
@ -287,7 +305,7 @@ public final class SalvageHelper {
|
|||||||
* @param items <p>The items to get the sum of</p>
|
* @param items <p>The items to get the sum of</p>
|
||||||
* @return <p>The total number of items</p>
|
* @return <p>The total number of items</p>
|
||||||
*/
|
*/
|
||||||
private static int totalItemAmount(@NotNull List<ItemStack> items) {
|
public static int totalItemAmount(@NotNull List<ItemStack> items) {
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
for (ItemStack itemStack : items) {
|
for (ItemStack itemStack : items) {
|
||||||
sum += itemStack.getAmount();
|
sum += itemStack.getAmount();
|
||||||
|
@ -202,6 +202,9 @@ scrapper:
|
|||||||
# The message to display when the scrapper fails to salvage an item
|
# The message to display when the scrapper fails to salvage an item
|
||||||
failSalvageMessage: "&cWhoops! The item broke! Maybe next time?"
|
failSalvageMessage: "&cWhoops! The item broke! Maybe next time?"
|
||||||
|
|
||||||
|
# The message to display when the scrapper fails to salvage an item without durability
|
||||||
|
failExtendedSalvageMessage: "&cWhoops! I was unable to extract much, if any, salvage! Maybe next time?"
|
||||||
|
|
||||||
# The message to display when presenting a different item than the one just evaluated
|
# The message to display when presenting a different item than the one just evaluated
|
||||||
itemChangedMessage: "&cThat's not the item you wanted to salvage before!"
|
itemChangedMessage: "&cThat's not the item you wanted to salvage before!"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user