EpicKnarvik97 81c15b6600
All checks were successful
EpicKnarvik97/Blacksmith/pipeline/head This commit looks good
Adds information about the appropriate crafting station in ActionStartEvent
2024-08-03 16:32:44 +02:00

185 lines
7.2 KiB
Java

package net.knarcraft.blacksmith.trait;
import net.citizensnpcs.api.npc.NPC;
import net.knarcraft.blacksmith.BlacksmithPlugin;
import net.knarcraft.blacksmith.config.scrapper.ScrapperNPCSettings;
import net.knarcraft.blacksmith.event.ScrapperSalvageFailEvent;
import net.knarcraft.blacksmith.event.ScrapperSalvageSucceedEvent;
import net.knarcraft.blacksmith.manager.EconomyManager;
import net.knarcraft.blacksmith.property.SalvageMethod;
import net.knarcraft.blacksmith.util.ItemHelper;
import net.knarcraft.blacksmith.util.SalvageHelper;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import static net.knarcraft.blacksmith.formatting.BlacksmithStringFormatter.sendNPCMessage;
/**
* A representation of the session between a player and a scrapper
*/
public class SalvageSession extends Session implements Runnable {
private final ScrapperTrait scrapperTrait;
private final ItemStack itemToSalvage;
private final ScrapperNPCSettings config;
private final List<ItemStack> salvage;
private final int itemsConsumed;
private final int enchantmentLevels;
protected final SalvageMethod salvageMethod;
private static final Random random = new Random();
/**
* Instantiates a new session
*
* @param scrapperTrait <p>A reference to the scrapper trait</p>
* @param player <p>The player initiating 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 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>
*/
public SalvageSession(@NotNull ScrapperTrait scrapperTrait, @NotNull Player player, @NotNull NPC npc,
@NotNull ScrapperNPCSettings config, @NotNull List<ItemStack> salvage,
@NotNull SalvageMethod salvageMethod, int itemsConsumed) {
super(player, npc);
this.scrapperTrait = scrapperTrait;
this.itemToSalvage = player.getInventory().getItemInMainHand().clone();
this.config = config;
this.salvage = salvage;
this.enchantmentLevels = SalvageHelper.getTotalEnchantmentLevels(this.itemToSalvage);
this.salvageMethod = salvageMethod;
this.itemsConsumed = itemsConsumed;
}
@Override
public boolean isSessionInvalid() {
// Prevent player from switching items during session
ItemStack itemInHand = this.player.getInventory().getItemInMainHand();
if (!itemToSalvage.equals(itemInHand)) {
sendNPCMessage(this.npc, this.player, this.config.getItemChangedMessage());
return true;
}
if (EconomyManager.cannotPayForSalvage(this.player, this.salvageMethod)) {
sendNPCMessage(this.npc, this.player, this.config.getInsufficientFundsMessage());
return true;
}
return false;
}
@Override
protected int getActionDelay() {
if (this.config.getMaxSalvageDelay() > 0) {
//Finish the salvaging after a random delay between the max and min
return new Random().nextInt(this.config.getMaxSalvageDelay()) + this.config.getMinSalvageDelay();
} else {
//Finish the salvaging as soon as possible
return 0;
}
}
@Override
protected @NotNull Material getCraftingStation() {
return switch (this.salvageMethod) {
case EXTENDED_SALVAGE -> Material.CRAFTING_TABLE;
case SALVAGE -> Material.ANVIL;
case NETHERITE, ARMOR_TRIM -> Material.SMITHING_TABLE;
};
}
/**
* Runs the actual salvage which fixes the item and gives it back to the player
*/
@Override
public void run() {
salvageItem();
//Stop the reforged item from displaying in the scrapper's hand
if (this.npc.getEntity() instanceof Player) {
((Player) this.npc.getEntity()).getInventory().setItemInMainHand(null);
} else {
Objects.requireNonNull(((LivingEntity) this.npc.getEntity()).getEquipment()).setItemInMainHand(null);
}
//Mark this scrapper as available
this.scrapperTrait.unsetSession();
// Start cool-down
Calendar wait = Calendar.getInstance();
wait.add(Calendar.SECOND, this.config.getSalvageCoolDown());
this.scrapperTrait.addCoolDown(this.player.getUniqueId(), wait);
}
/**
* Gets the number of items consumed in order to perform the salvage
*
* @return <p>The number of items consumed as part of this salvage</p>
*/
public int getItemsConsumed() {
return this.itemsConsumed;
}
/**
* Trues to salvage an item, and gives the return item
*/
private void salvageItem() {
if (random.nextInt(100) < this.config.getFailChance()) {
playSound(Sound.ENTITY_VILLAGER_NO);
failSalvage();
BlacksmithPlugin.getInstance().callEvent(new ScrapperSalvageFailEvent(this.npc, this.player));
} else {
playSound(Sound.BLOCK_ANVIL_USE);
giveSalvage();
BlacksmithPlugin.getInstance().callEvent(new ScrapperSalvageSucceedEvent(this.npc, this.player));
sendNPCMessage(this.npc, this.player, this.config.getSuccessMessage());
}
}
/**
* The method to run when a crapper fails salvaging an item
*/
private void failSalvage() {
// Make sure the given amount is the same amount taken for salvage to avoid duplication
this.itemToSalvage.setAmount(itemsConsumed);
if (ItemHelper.getMaxDurability(this.itemToSalvage) > 0) {
//Damage the item if possible
damageItemRandomly(this.itemToSalvage);
giveResultingItem(this.config.getMaxSalvageDelay() > 0, this.config.getDropItem(), this.npc,
this.itemToSalvage);
sendNPCMessage(this.npc, this.player, this.config.getFailSalvageMessage());
} else {
// 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());
}
}
/**
* Gives the player the calculated salvage
*/
private void giveSalvage() {
// TODO: Find a better calculation than 1 enchantment level = 1 exp level
// Gives the player back some of the EXP used on an item
this.player.giveExpLevels(this.enchantmentLevels);
BlacksmithPlugin.debug("Giving salvage " + this.salvage);
for (ItemStack item : this.salvage) {
giveResultingItem(this.config.getMaxSalvageDelay() > 0, this.config.getDropItem(), this.npc, item);
}
}
}