ExcellentEnchants-spigot/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/EnchantUtils.java

384 lines
15 KiB
Java

package su.nightexpress.excellentenchants.enchantment.util;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.event.block.BlockDropItemEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.metadata.FixedMetadataValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import su.nexmedia.engine.lang.LangManager;
import su.nexmedia.engine.utils.EntityUtil;
import su.nexmedia.engine.utils.ItemUtil;
import su.nexmedia.engine.utils.PDCUtil;
import su.nightexpress.excellentenchants.ExcellentEnchantsAPI;
import su.nightexpress.excellentenchants.api.enchantment.IEnchantment;
import su.nightexpress.excellentenchants.config.Config;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.registry.EnchantRegistry;
import java.util.*;
import java.util.stream.Stream;
public class EnchantUtils {
public static final NamespacedKey KEY_LORE_SIZE = new NamespacedKey(ExcellentEnchantsAPI.PLUGIN, "lore_size");
private static final String META_PROJECTILE_WEAPON = "sourceWeapon";
private static boolean busyBreak = false;
public static void popResource(@NotNull BlockDropItemEvent event, @NotNull ItemStack itemStack) {
Item item = ExcellentEnchantsAPI.PLUGIN.getEnchantNMS().popResource(event.getBlock(), itemStack);
event.getItems().add(item);
}
public static boolean isBusyByOthers() {
return false;
}
public static boolean isBusyByEnchant() {
return busyBreak;
}
public static boolean isBusy() {
return isBusyByEnchant() || isBusyByOthers();
}
public static void busyBreak(@NotNull Player player, @NotNull Block block) {
busyBreak = true;
player.breakBlock(block);
busyBreak = false;
}
public static void safeBusyBreak(@NotNull Player player, @NotNull Block block) {
if (!isBusy()) {
busyBreak(player, block);
}
}
@NotNull
public static NamespacedKey createKey(@NotNull String id) {
return NamespacedKey.minecraft(id.toLowerCase());
}
@Nullable
public static String getLocalized(@NotNull String keyRaw) {
Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(keyRaw));
return enchantment == null ? null : getLocalized(enchantment);
}
@NotNull
public static String getLocalized(@NotNull Enchantment enchantment) {
if (enchantment instanceof ExcellentEnchant excellentEnchant) {
return excellentEnchant.getDisplayName();
}
return LangManager.getEnchantment(enchantment);
}
public static boolean isEnchantable(@NotNull ItemStack item) {
if (item.getType().isAir()) return false;
return item.getType() == Material.ENCHANTED_BOOK || Stream.of(EnchantmentTarget.values()).anyMatch(target -> target.includes(item));
}
public static boolean add(@NotNull ItemStack item, @NotNull Enchantment enchantment, int level, boolean force) {
if (!force && !enchantment.canEnchantItem(item)) return false;
remove(item, enchantment);
ItemMeta meta = item.getItemMeta();
if (meta == null) return false;
if (meta instanceof EnchantmentStorageMeta storageMeta) {
if (!storageMeta.addStoredEnchant(enchantment, level, true)) return false;
}
else {
if (!meta.addEnchant(enchantment, level, true)) return false;
}
item.setItemMeta(meta);
return true;
}
public static void remove(@NotNull ItemStack item, @NotNull Enchantment enchantment) {
ItemMeta meta = item.getItemMeta();
if (meta instanceof EnchantmentStorageMeta storageMeta) {
storageMeta.removeStoredEnchant(enchantment);
}
else {
meta.removeEnchant(enchantment);
}
item.setItemMeta(meta);
}
public static void updateChargesDisplay(@NotNull ItemStack item) {
if (Config.ENCHANTMENTS_CHARGES_ENABLED.get()) {
updateDisplay(item);
}
}
public static boolean updateDisplay(@NotNull ItemStack item) {
if (Config.ENCHANTMENTS_DISPLAY_MODE.get() != 1) return false;
ItemMeta meta = item.getItemMeta();
if (meta == null) return false;
if (!isEnchantable(item)) {
PDCUtil.remove(item, KEY_LORE_SIZE);
return false;
}
Map<ExcellentEnchant, Integer> enchants = getExcellents(item);
int sizeCached = PDCUtil.getInt(item, KEY_LORE_SIZE).orElse(0);
int sizeReal = enchants.size();
if (sizeCached == 0 && sizeReal == 0) return false;
List<String> lore = meta.getLore() == null ? new ArrayList<>() : meta.getLore();
for (int index = 0; index < sizeCached && !lore.isEmpty(); index++) {
lore.remove(0);
}
//lore.removeIf(str -> enchants.keySet().stream().anyMatch(enchant -> str.contains(enchant.getDisplayName())));
if (!meta.hasItemFlag(ItemFlag.HIDE_ENCHANTS)) {
if (Config.ENCHANTMENTS_DESCRIPTION_ENABLED.get()) {
enchants.forEach((enchant, level) -> {
lore.addAll(0, enchant.formatDescription(level));
});
sizeReal += enchants.keySet().stream().map(ExcellentEnchant::getDescription).mapToInt(List::size).sum();
}
enchants.forEach((enchant, level) -> {
lore.add(0, enchant.getNameFormatted(level, getCharges(meta, enchant)));
});
}
else sizeReal = 0;
meta.setLore(lore);
if (sizeReal > 0) {
PDCUtil.set(meta, KEY_LORE_SIZE, sizeReal);
}
else PDCUtil.remove(meta, KEY_LORE_SIZE);
item.setItemMeta(meta);
return true;
}
@Nullable
public static ItemStack getFishingRod(@NotNull Player player) {
ItemStack main = player.getInventory().getItem(EquipmentSlot.HAND);
if (main != null && main.getType() == Material.FISHING_ROD) return main;
ItemStack off = player.getInventory().getItem(EquipmentSlot.OFF_HAND);
if (off != null && off.getType() == Material.FISHING_ROD) return off;
return null;
}
@NotNull
public static Map<Enchantment, Integer> getAll(@NotNull ItemStack item) {
ItemMeta meta = item.getItemMeta();
return meta == null ? Collections.emptyMap() : getAll(meta);
}
@NotNull
public static Map<Enchantment, Integer> getAll(@NotNull ItemMeta meta) {
return (meta instanceof EnchantmentStorageMeta meta2) ? meta2.getStoredEnchants() : meta.getEnchants();
}
public static int getAmount(@NotNull ItemStack item) {
return getAll(item).size();
}
public static boolean contains(@NotNull ItemStack item, @NotNull String id) {
ExcellentEnchant enchant = EnchantRegistry.getById(id);
if (enchant == null) return false;
return contains(item, enchant);
}
public static boolean contains(@NotNull ItemStack item, @NotNull Enchantment enchantment) {
return getLevel(item, enchantment) > 0;
}
public static int getLevel(@NotNull ItemStack item, @NotNull Enchantment enchant) {
return getAll(item).getOrDefault(enchant, 0);
}
public static int getCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant) {
return enchant.isChargesEnabled() ? PDCUtil.getInt(item, enchant.getChargesKey()).orElse(0) : -1;
}
public static int getCharges(@NotNull ItemMeta meta, @NotNull ExcellentEnchant enchant) {
return enchant.isChargesEnabled() ? PDCUtil.getInt(meta, enchant.getChargesKey()).orElse(0) : -1;
}
public static boolean isOutOfCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant) {
return enchant.isChargesEnabled() && getCharges(item, enchant) == 0;
}
public static boolean isFullOfCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant) {
if (!enchant.isChargesEnabled()) return true;
int level = getLevel(item, enchant);
int max = enchant.getChargesMax(level);
return getCharges(item, enchant) == max;
}
public static void consumeCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant, int level) {
int has = getCharges(item, enchant);
int use = enchant.getChargesConsumeAmount(level);
setCharges(item, enchant, level, has < use ? 0 : has - use);
}
/*public static void restoreCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant) {
int level = getLevel(item, enchant);
restoreCharges(item, enchant, level);
}*/
public static void restoreCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant, int level) {
setCharges(item, enchant, level, Integer.MAX_VALUE);
}
public static void rechargeCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant, int level) {
//if (!enchant.isChargesEnabled()) return;
//int level = getLevel(item, enchant);
int recharge = enchant.getChargesRechargeAmount(level);
int has = getCharges(item, enchant);
int set = has + recharge;
setCharges(item, enchant, level, set);
}
/*public static void setCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant, int charges) {
int level = getLevel(item, enchant);
setCharges(item, enchant, level, charges);
}*/
public static void setCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant, int level, int charges) {
if (!enchant.isChargesEnabled()) return;
int max = enchant.getChargesMax(level);
int set = Math.min(Math.abs(charges), max);
PDCUtil.set(item, enchant.getChargesKey(), set);
}
public static int getExcellentAmount(@NotNull ItemStack item) {
return getExcellents(item).size();
}
@NotNull
public static Map<ExcellentEnchant, Integer> getExcellents(@NotNull ItemStack item) {
return getExcellents(getAll(item));
}
@NotNull
public static Map<ExcellentEnchant, Integer> getExcellents(@NotNull ItemMeta meta) {
return getExcellents(getAll(meta));
}
@NotNull
private static Map<ExcellentEnchant, Integer> getExcellents(@NotNull Map<Enchantment, Integer> enchants) {
Map<ExcellentEnchant, Integer> map = new HashMap<>();
enchants.forEach((enchantment, level) -> {
ExcellentEnchant excellent = EnchantRegistry.getByKey(enchantment.getKey());
if (excellent != null) {
map.put(excellent, level);
}
});
return map;
}
@NotNull
public static <T extends IEnchantment> Map<T, Integer> getExcellents(@NotNull ItemStack item, @NotNull Class<T> clazz) {
Map<T, Integer> map = new HashMap<>();
getAll(item).forEach((enchantment, level) -> {
ExcellentEnchant excellent = EnchantRegistry.getByKey(enchantment.getKey());
if (excellent == null || !clazz.isAssignableFrom(excellent.getClass())) return;
map.put(clazz.cast(excellent), level);
});
return map;//CollectionsUtil.sort(map, Comparator.comparing(p -> p.getKey().getPriority(), Comparator.reverseOrder()));
}
@NotNull
public static Map<EquipmentSlot, ItemStack> getEnchantedEquipment(@NotNull LivingEntity entity) {
return getEnchantedEquipment(entity, EquipmentSlot.values());
}
@NotNull
public static Map<EquipmentSlot, ItemStack> getEnchantedEquipment(@NotNull LivingEntity entity, @NotNull EquipmentSlot... slots) {
Map<EquipmentSlot, ItemStack> equipment = EntityUtil.getEquippedItems(entity, slots);
equipment.entrySet().removeIf(entry -> {
ItemStack item = entry.getValue();
EquipmentSlot slot = entry.getKey();
if (item == null || item.getType().isAir() || item.getType() == Material.ENCHANTED_BOOK) return true;
if ((slot == EquipmentSlot.HAND || slot == EquipmentSlot.OFF_HAND) && ItemUtil.isArmor(item)) return true;
return !item.hasItemMeta();
});
return equipment;
}
@NotNull
public static Map<ItemStack, Map<ExcellentEnchant, Integer>> getEquipped(@NotNull LivingEntity entity) {
Map<ItemStack, Map<ExcellentEnchant, Integer>> map = new HashMap<>();
getEnchantedEquipment(entity).values().forEach(item -> {
map.computeIfAbsent(item, k -> new LinkedHashMap<>()).putAll(getExcellents(item));
});
return map;
}
@NotNull
public static <T extends IEnchantment> Map<ItemStack, Map<T, Integer>> getEquipped(@NotNull LivingEntity entity,
@NotNull Class<T> clazz) {
return getEquipped(entity, clazz, EquipmentSlot.values());
}
@NotNull
public static <T extends IEnchantment> Map<ItemStack, Map<T, Integer>> getEquipped(@NotNull LivingEntity entity,
@NotNull Class<T> clazz,
@NotNull EquipmentSlot... slots) {
Map<ItemStack, Map<T, Integer>> map = new HashMap<>();
getEnchantedEquipment(entity, slots).values().forEach(item -> {
map.computeIfAbsent(item, k -> new LinkedHashMap<>()).putAll(getExcellents(item, clazz));
});
return map;
}
@NotNull
public static Map<ItemStack, Integer> getEquipped(@NotNull LivingEntity entity, @NotNull ExcellentEnchant enchantment) {
Map<ItemStack, Integer> map = new HashMap<>();
getEnchantedEquipment(entity).values().forEach(item -> {
int level = getLevel(item, enchantment);
if (level > 0) {
map.put(item, level);
}
});
return map;
}
public static void setSourceWeapon(@NotNull Projectile projectile, @Nullable ItemStack item) {
if (item == null) return;
projectile.setMetadata(META_PROJECTILE_WEAPON, new FixedMetadataValue(ExcellentEnchantsAPI.PLUGIN, item));
}
@Nullable
public static ItemStack getSourceWeapon(@NotNull Projectile projectile) {
return projectile.hasMetadata(META_PROJECTILE_WEAPON) ? (ItemStack) projectile.getMetadata(META_PROJECTILE_WEAPON).get(0).value() : null;
}
public static void removeSourceWeapon(@NotNull Projectile projectile) {
projectile.removeMetadata(META_PROJECTILE_WEAPON, ExcellentEnchantsAPI.PLUGIN);
}
}