package net.knarcraft.blacksmith.container; import net.knarcraft.blacksmith.BlacksmithPlugin; import net.knarcraft.blacksmith.manager.EconomyManager; import net.md_5.bungee.api.ChatColor; import org.bukkit.NamespacedKey; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.serialization.ConfigurationSerializable; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; /** * The cost of performing an action * * @param monetaryCost
The monetary cost of the action
* @param expCostThe experience cost of the action
* @param itemCostThe item-based cost of the action
* @param requiredPermissionsThe permission required for the action
*/ public record ActionCost(double monetaryCost, int expCost, @Nullable ItemStack itemCost, @NotNull SetThe new monetary cost
* @returnThe resulting action cost
*/ public ActionCost changeMonetaryCost(double monetaryCost) { return new ActionCost(monetaryCost, this.expCost, this.itemCost, this.requiredPermissions); } /** * Changes the experience cost of this action * * @param expCostThe new experience cost
* @returnThe resulting action cost
*/ public ActionCost changeExpCost(int expCost) { return new ActionCost(this.monetaryCost, expCost, this.itemCost, this.requiredPermissions); } /** * Changes the item cost of this action * * @param itemCostThe new item cost
* @returnThe resulting action cost
*/ public ActionCost changeItemCost(@Nullable ItemStack itemCost) { return new ActionCost(this.monetaryCost, this.expCost, itemCost, this.requiredPermissions); } /** * Changes the permission cost of this action * * @param requiredPermissionsThe new permission cost
* @returnThe resulting action cost
*/ public ActionCost changePermissionCost(@NotNull SetThe player to calculate the cost for
* @returnThe string representation of this action cost
*/ @NotNull public String displayCost(@NotNull Player player) { StringBuilder builder = new StringBuilder(); if (monetaryCost > 0) { builder.append(EconomyManager.format(monetaryCost)).append(", ").append("\n"); } if (expCost > 0) { builder.append(expCost).append("exp, ").append("\n"); } if (itemCost != null) { NamespacedKey itemName = itemCost.getType().getKeyOrNull(); if (itemName != null) { builder.append(itemCost.getAmount()).append(" x ").append(itemName); ItemMeta itemMeta = itemCost.getItemMeta(); if (itemMeta != null && itemMeta.hasDisplayName()) { builder.append("(").append(itemMeta.getDisplayName()).append(")"); } if (itemMeta != null && itemMeta.hasLore() && itemMeta.getLore() != null) { for (String lore : itemMeta.getLore()) { builder.append("\n").append(lore); } } builder.append("\n"); } } if (!requiredPermissions().isEmpty()) { for (String permission : requiredPermissions()) { if (player.hasPermission(permission)) { builder.append(ChatColor.DARK_GREEN).append("O ").append(permission).append("\n"); } else { builder.append(ChatColor.DARK_RED).append("X ").append(permission).append("\n"); } } } return builder.toString(); } /** * Checks whether the given player is able to pay this action cost * * @param playerThe player to check
* @returnTrue if the player is able to pay
*/ public boolean canPay(@NotNull Player player) { for (String permission : this.requiredPermissions) { if (!player.hasPermission(permission)) { return false; } } if (player.getExp() < this.expCost || !EconomyManager.hasEnough(player, this.monetaryCost)) { return false; } return hasEnoughValidItemsInInventory(player); } /** * Takes exp, money and items from the player, according to this cost * * @param playerThe player to take the payment from
*/ public void takePayment(@NotNull Player player) { player.giveExp(-expCost); EconomyManager.withdraw(player, monetaryCost); takeItemCost(player); } /** * Checks whether the given player has enough items specified as the item cost * * @param playerThe player to check
* @returnTrue if the player has enough items in their inventory
*/ private boolean hasEnoughValidItemsInInventory(@NotNull Player player) { if (this.itemCost == null) { return true; } int amountInInventory = 0; for (Map.EntryThe player to get valid items for
* @returnAll valid items in the format: Inventory id -> Amount
*/ @NotNull private MapThe player to take the items from
*/ private void takeItemCost(@NotNull Player player) { if (this.itemCost == null) { return; } int clearedAmount = 0; for (Map.EntryThe configuration section to load from
* @param keyThe key of the cost to load
* @returnThe loaded cost
*/ private static ActionCost loadActionCost(@NotNull ConfigurationSection configurationSection, @NotNull String key) { double cost = configurationSection.getDouble(key, Double.MIN_VALUE); if (cost != Double.MIN_VALUE) { return new ActionCost(cost, 0, null, Set.of()); } else { return (ActionCost) configurationSection.get(key); } } /** * Deserializes an action cost * * @param serializedThe serialized action cost
* @returnThe deserialized action cost
*/ @SuppressWarnings({"unused", "unchecked"}) public static ActionCost deserialize(Map