All checks were successful
EpicKnarvik97/Blacksmith/pipeline/head This commit looks good
300 lines
10 KiB
Java
300 lines
10 KiB
Java
package net.knarcraft.blacksmith.util;
|
|
|
|
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
|
import net.knarcraft.blacksmith.config.SmithPreset;
|
|
import org.bukkit.Material;
|
|
import org.bukkit.Server;
|
|
import org.bukkit.inventory.CraftingRecipe;
|
|
import org.bukkit.inventory.Inventory;
|
|
import org.bukkit.inventory.ItemStack;
|
|
import org.bukkit.inventory.Recipe;
|
|
import org.bukkit.inventory.meta.Damageable;
|
|
import org.bukkit.inventory.meta.ItemMeta;
|
|
import org.jetbrains.annotations.NotNull;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.logging.Level;
|
|
|
|
/**
|
|
* A helper class for getting information about items
|
|
*/
|
|
public final class ItemHelper {
|
|
|
|
private ItemHelper() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets whether the given item is repairable
|
|
*
|
|
* @param item <p>The item to check</p>
|
|
* @return <p>True if the item is repairable</p>
|
|
*/
|
|
public static boolean isRepairable(@NotNull ItemStack item) {
|
|
return item.getItemMeta() instanceof Damageable && getMaxDurability(item) > 0;
|
|
}
|
|
|
|
/**
|
|
* Gets the max durability of an item
|
|
*
|
|
* @param itemStack <p>The item to get the durability of</p>
|
|
* @return <p>The max durability of the item</p>
|
|
*/
|
|
public static short getMaxDurability(@NotNull ItemStack itemStack) {
|
|
if (itemStack.getItemMeta() instanceof Damageable) {
|
|
return itemStack.getType().getMaxDurability();
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the current durability of the given item
|
|
*
|
|
* @param itemStack <p>The item to get the durability of</p>
|
|
* @return <p>The durability of the item</p>
|
|
*/
|
|
public static short getDurability(@NotNull ItemStack itemStack) {
|
|
if (itemStack.getItemMeta() instanceof Damageable damageable) {
|
|
int maxDurability = getMaxDurability(itemStack);
|
|
return (short) (maxDurability - damageable.getDamage());
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the damage done to the given item
|
|
*
|
|
* @param itemStack <p>The damage done to the item</p>
|
|
* @return <p>The damage done to the item</p>
|
|
*/
|
|
public static short getDamage(@NotNull ItemStack itemStack) {
|
|
if (itemStack.getItemMeta() instanceof Damageable damageable) {
|
|
return (short) damageable.getDamage();
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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>
|
|
* @return <p>True if the damage was updated. False if not damageable.</p>
|
|
*/
|
|
public static boolean updateDamage(@NotNull ItemStack item, int newDamage) {
|
|
ItemMeta meta = item.getItemMeta();
|
|
if (!(meta instanceof Damageable damageable)) {
|
|
return false;
|
|
}
|
|
damageable.setDamage(newDamage);
|
|
item.setItemMeta(meta);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Gets a complete list of all reforge-able materials
|
|
*
|
|
* <p>Note: As this loops through all materials, the result should be cached</p>
|
|
*
|
|
* @return <p>A complete list of reforge-able materials</p>
|
|
*/
|
|
public static @NotNull Set<Material> getAllReforgeAbleMaterials() {
|
|
Set<Material> reforgeAbleMaterials = new HashSet<>();
|
|
for (Material material : Material.values()) {
|
|
ItemStack item = new ItemStack(material);
|
|
if (isRepairable(item)) {
|
|
reforgeAbleMaterials.add(material);
|
|
}
|
|
}
|
|
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(@NotNull 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);
|
|
}
|
|
|
|
/**
|
|
* Checks whether the given inventory is able to fit the given item
|
|
*
|
|
* @param inventory <p>The inventory to check</p>
|
|
* @param item <p>The item to check</p>
|
|
* @return <p>True if the inventory can fit the item</p>
|
|
*/
|
|
public static boolean canFitItem(@NotNull Inventory inventory, @NotNull ItemStack item) {
|
|
// If a slot is available, there is no problem
|
|
if (inventory.firstEmpty() != -1) {
|
|
return true;
|
|
}
|
|
|
|
// If the inventory doesn't contain the correct type of item, stacking is impossible
|
|
if (!inventory.contains(item.getType())) {
|
|
return false;
|
|
}
|
|
|
|
// Check if the item stack can fit in the inventory if stacked with existing items
|
|
int availableSlots = 0;
|
|
for (ItemStack itemStack : inventory.getStorageContents()) {
|
|
ItemMeta itemMeta = itemStack.getItemMeta();
|
|
ItemMeta targetMeta = item.getItemMeta();
|
|
// Skip items of a different type, or with metadata that would prevent stacking
|
|
if (itemStack.getType() != item.getType() ||
|
|
(itemMeta != null && targetMeta != null && !itemMeta.equals(targetMeta))) {
|
|
continue;
|
|
}
|
|
|
|
availableSlots += itemStack.getMaxStackSize() - itemStack.getAmount();
|
|
|
|
if (availableSlots < item.getAmount()) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Checks whether the given item can be salvaged, assuming no restrictions apply
|
|
*
|
|
* @param server <p>The server to get recipes from</p>
|
|
* @param item <p>The item to check</p>
|
|
* @return <p>True if the item can be salvaged</p>
|
|
*/
|
|
public static boolean isSalvageable(@NotNull Server server, @NotNull ItemStack item) {
|
|
for (Recipe recipe : server.getRecipesFor(new ItemStack(item.getType(), item.getAmount()))) {
|
|
// Only crafting recipes are allowed.
|
|
if ((recipe instanceof CraftingRecipe) && item.getAmount() >= recipe.getResult().getAmount()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Gets the amount of an item that's required to salvage that item
|
|
*
|
|
* @param server <p>The server to get recipes from</p>
|
|
* @param item <p>The item to check</p>
|
|
* @return <p>The number of items required for salvage, or -1 if the recipe was not found</p>
|
|
*/
|
|
public static int getRequiredAmountForSalvage(@NotNull Server server, @NotNull ItemStack item) {
|
|
for (Recipe recipe : server.getRecipesFor(new ItemStack(item.getType(), item.getAmount()))) {
|
|
// Only crafting recipes are allowed.
|
|
if (recipe instanceof CraftingRecipe) {
|
|
return recipe.getResult().getAmount();
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Gets all materials matching the given material wildcard
|
|
*
|
|
* @param materialName <p>The material name or material wildcard to match</p>
|
|
* @param extended <p>Whether to use an extended match, allowing any material</p>
|
|
* @return <p>The matched material(s)</p>
|
|
*/
|
|
public static @NotNull Set<Material> getWildcardMatch(@NotNull String materialName, boolean extended) {
|
|
String search = InputParsingHelper.regExIfy(materialName);
|
|
Set<Material> materials = new HashSet<>();
|
|
Set<Material> all;
|
|
if (extended) {
|
|
all = Set.of(Material.values());
|
|
} else {
|
|
all = ItemHelper.getAllReforgeAbleMaterials();
|
|
}
|
|
for (Material material : all) {
|
|
if (material.name().matches(search)) {
|
|
materials.add(material);
|
|
}
|
|
}
|
|
return materials;
|
|
}
|
|
|
|
/**
|
|
* Gets a list of the items described in the given item list
|
|
*
|
|
* @param itemList <p>The list of items defined by the user</p>
|
|
* @param requireRepairable <p>Whether a material must be repairable to be valid.</p>
|
|
* @return <p>The materials contained in the item list</p>
|
|
*/
|
|
public static List<Material> getItems(@Nullable List<String> itemList, boolean requireRepairable) {
|
|
List<Material> items = new ArrayList<>();
|
|
if (itemList == null) {
|
|
return null;
|
|
}
|
|
|
|
//Convert any presets with a list of materials
|
|
itemList = replacePresets(itemList);
|
|
|
|
Set<Material> blacklisted = new HashSet<>();
|
|
//Parse every material, and add to reforgeAble items
|
|
for (String item : itemList) {
|
|
//Ignore ",,"
|
|
if (InputParsingHelper.isEmpty(item) || item.matches("\\[]")) {
|
|
continue;
|
|
}
|
|
|
|
boolean blacklist = false;
|
|
if (item.startsWith("-")) {
|
|
blacklist = true;
|
|
item = item.substring(1);
|
|
}
|
|
|
|
Material material = InputParsingHelper.matchMaterial(item);
|
|
if (material != null && (!requireRepairable || ItemHelper.isRepairable(new ItemStack(material, 1)))) {
|
|
if (!blacklist) {
|
|
items.add(material);
|
|
} else {
|
|
blacklisted.add(material);
|
|
}
|
|
} else {
|
|
BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING, "Unable to verify " + item +
|
|
" as a valid repairable item");
|
|
}
|
|
}
|
|
|
|
//Remove any blacklisted materials at the end to make sure order of arguments won't matter
|
|
items.removeAll(blacklisted);
|
|
return items;
|
|
}
|
|
|
|
/**
|
|
* Replaces smith presets in the given list of strings
|
|
*
|
|
* @param stringList <p>The value specified by a user</p>
|
|
* @return <p>The value with smith presets replaced</p>
|
|
*/
|
|
private static @NotNull List<String> replacePresets(@NotNull List<String> stringList) {
|
|
List<String> newStrings = new ArrayList<>();
|
|
for (String item : stringList) {
|
|
if (item == null) {
|
|
continue;
|
|
}
|
|
String replaced = SmithPreset.replacePreset(item);
|
|
if (!replaced.equals(item)) {
|
|
newStrings.addAll(List.of(replaced.split(",")));
|
|
} else {
|
|
newStrings.add(item);
|
|
}
|
|
}
|
|
return newStrings;
|
|
}
|
|
|
|
}
|