package net.knarcraft.blacksmith.trait; import net.citizensnpcs.api.npc.NPC; import net.knarcraft.blacksmith.BlacksmithPlugin; import net.knarcraft.blacksmith.config.NPCSettings; import net.knarcraft.blacksmith.manager.EconomyManager; import net.knarcraft.blacksmith.util.ItemHelper; import org.bukkit.NamespacedKey; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.Damageable; import org.bukkit.inventory.meta.ItemMeta; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Objects; import java.util.Random; import java.util.logging.Level; import static net.knarcraft.blacksmith.formatting.StringFormatter.sendNPCMessage; /** * A representation of the session between a player and a blacksmith */ public class ReforgeSession implements Runnable { private final BlacksmithTrait blacksmithTrait; private final Player player; private final NPC npc; private final ItemStack itemToReforge; private int taskId; private final NPCSettings config; private static final String[] enchantments = new String[Enchantment.values().length]; private static final Random random = new Random(); /** * Instantiates a new session * * @param blacksmithTrait
A reference to the blacksmith trait
* @param playerThe player initiating the session
* @param npcThe Blacksmith NPC involved in the session
* @param configThe config to use for the session
*/ ReforgeSession(BlacksmithTrait blacksmithTrait, Player player, NPC npc, NPCSettings config) { this.blacksmithTrait = blacksmithTrait; this.player = player; this.npc = npc; itemToReforge = player.getInventory().getItemInMainHand(); this.config = config; int i = 0; for (Enchantment enchantment : Enchantment.values()) { enchantments[i++] = enchantment.getKey().toString(); } } /** * Runs the actual reforge which fixes the item and gives it back to the player */ @Override public void run() { sendNPCMessage(this.npc, player, reforgeItem() ? config.getSuccessMessage() : config.getFailMessage()); //Stop the reforged item from displaying in the blacksmith's hand if (npc.getEntity() instanceof Player) { ((Player) npc.getEntity()).getInventory().setItemInMainHand(null); } else { Objects.requireNonNull(((LivingEntity) npc.getEntity()).getEquipment()).setItemInMainHand(null); } //Give the item back to the player if (!config.getDisableDelay()) { //If the player isn't online, or the player cannot fit the item, drop the item to prevent it from disappearing if (config.getDropItem() || !player.isOnline() || player.getInventory().firstEmpty() == -1) { player.getWorld().dropItemNaturally(npc.getEntity().getLocation(), itemToReforge); } else { player.getInventory().addItem(itemToReforge); } } else { //It can be assumed as this happens instantly, that the player still has the item's previous slot selected player.getInventory().setItemInMainHand(itemToReforge); } //Mark this blacksmith as available blacksmithTrait.unsetSession(); // Start cool-down Calendar wait = Calendar.getInstance(); wait.add(Calendar.SECOND, config.getReforgeCoolDown()); blacksmithTrait.addCoolDown(player.getUniqueId(), wait); } /** * Performs the actual reforge where the item's damage is reduced * * @returnWhether the reforge was successful. False if the blacksmith failed to fully repair the item.
*/ private boolean reforgeItem() { if (random.nextInt(100) < config.getFailChance()) { failReforge(); return false; } else { succeedReforge(); return true; } } /** * The method to run when a blacksmith successfully reforges an item */ private void succeedReforge() { // Remove any damage done to the item updateDamage(itemToReforge, 0); // Add random enchantments int roll = random.nextInt(100); if (!(roll < config.getExtraEnchantmentChance() && itemToReforge.getEnchantments().keySet().size() < config.getMaxEnchantments())) { // Abort if randomness isn't on our side, or if max enchantments has been reached return; } //Find usable enchantments first ListThe item to update damage for
* @param newDamageThe new damage done
*/ private void updateDamage(ItemStack item, int newDamage) { ItemMeta meta = item.getItemMeta(); Damageable damageable = (Damageable) meta; if (damageable != null) { damageable.setDamage(newDamage); } else { BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING, "Unable to change damage of " + item); } item.setItemMeta(meta); } /** * Gets whether to end the current session * *If the player has switched their item, or the player cannot pay, this returns true.
* * @returnTrue if the current session should end
*/ public boolean endSession() { // Prevent player from switching items during session ItemStack itemInHand = player.getInventory().getItemInMainHand(); if (!itemToReforge.equals(itemInHand)) { sendNPCMessage(this.npc, player, config.getItemChangedMessage()); return true; } // The player is unable to pay if (!EconomyManager.canPay(player)) { sendNPCMessage(this.npc, player, config.getInsufficientFundsMessage()); return true; } return false; } /** * Gets whether the current session is still running * * @returnTrue if the current session is still running
*/ public boolean isRunning() { return BlacksmithPlugin.getInstance().getServer().getScheduler().isQueued(taskId); } /** * Gets whether the given player is currently in a reforging session * * @param otherThe player to check if is in session
* @returnTrue if the given player is in a reforge session
*/ public boolean isInSession(Player other) { return player.getName().equals(other.getName()); } /** * Begins the actual item reforging */ public void beginReforge() { if (!config.getDisableCoolDown()) { //Finish the reforging after a random delay between the max and min taskId = BlacksmithPlugin.getInstance().getServer().getScheduler().scheduleSyncDelayedTask( BlacksmithPlugin.getInstance(), this, (new Random().nextInt(config.getMaxReforgeDelay()) + config.getMinReforgeDelay()) * 20L); } else { //Finish the reforging as soon as possible taskId = BlacksmithPlugin.getInstance().getServer().getScheduler().scheduleSyncDelayedTask( BlacksmithPlugin.getInstance(), this, 0); } } /** * Gets the player currently in this reforge session * * @returnThe player currently in this reforge session
*/ public Player getPlayer() { return player; } }