cn.handyplus.lib.util.ItemStackUtil Maven / Gradle / Ivy
The newest version!
package cn.handyplus.lib.util;
import cn.handyplus.lib.adapter.HandySchedulerUtil;
import cn.handyplus.lib.constants.BaseConstants;
import cn.handyplus.lib.constants.VersionCheckEnum;
import cn.handyplus.lib.core.CollUtil;
import cn.handyplus.lib.core.MapUtil;
import cn.handyplus.lib.core.StrUtil;
import cn.handyplus.lib.expand.XMaterial;
import org.bukkit.Material;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.material.MaterialData;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
/**
* ItemStack工具类
*
* @author handy
* @since 1.1.8
*/
public class ItemStackUtil {
private ItemStackUtil() {
}
/**
* 序列化itemStack为String
*
* @param itemStack 物品
* @return String
*/
public static String itemStackSerialize(ItemStack itemStack) {
YamlConfiguration yml = new YamlConfiguration();
yml.set("item", itemStack);
return yml.saveToString();
}
/**
* 反序列化String为itemStack
*
* @param str 物品str
* @return ItemStack
*/
public static ItemStack itemStackDeserialize(String str) {
return itemStackDeserialize(str, Material.AIR);
}
/**
* 反序列化String为itemStack
*
* @param str 物品str
* @param material 解析异常返回的默认物品
* @return ItemStack
* @since 3.6.9
*/
public static ItemStack itemStackDeserialize(String str, Material material) {
YamlConfiguration yml = new YamlConfiguration();
ItemStack item;
try {
yml.loadFromString(str);
item = yml.getItemStack("item", new ItemStack(material));
} catch (Exception ex) {
item = new ItemStack(material);
}
return item;
}
/**
* 物品生成
*
* @param material 材质
* @return 自定义物品
* @since 2.0.3
*/
public static ItemStack getItemStack(String material) {
return getItemStack(material, null, null);
}
/**
* 物品生成
*
* @param material 材质
* @param displayName 名称
* @return 自定义物品
*/
public static ItemStack getItemStack(String material, String displayName) {
return getItemStack(material, displayName, null);
}
/**
* 物品生成
*
* @param material 材质
* @param displayName 名称
* @param loreList lore
* @return 自定义物品
*/
public static ItemStack getItemStack(String material, String displayName, List loreList) {
return getItemStack(material, displayName, loreList, false);
}
/**
* 物品生成
*
* @param material 材质
* @param displayName 名称
* @param loreList lore
* @param isEnchant 附魔效果
* @return 自定义物品
*/
public static ItemStack getItemStack(String material, String displayName, List loreList, Boolean isEnchant) {
return getItemStack(material, displayName, loreList, isEnchant, 0);
}
/**
* 物品生成
*
* @param material 材质
* @param displayName 名称
* @param loreList lore
* @param isEnchant 附魔效果
* @param customModelData 自定义模型id
* @return 自定义物品
* @since 2.0.3
*/
public static ItemStack getItemStack(String material, String displayName, List loreList, Boolean isEnchant, int customModelData) {
return getItemStack(material, displayName, loreList, isEnchant, customModelData, true);
}
/**
* 物品生成
*
* @param material 材质
* @param displayName 名称
* @param loreList lore
* @param isEnchant 附魔效果
* @param customModelData 自定义模型id
* @param hideFlag 隐藏标签
* @return 自定义物品
* @since 2.1.7
*/
public static ItemStack getItemStack(String material, String displayName, List loreList, Boolean isEnchant, int customModelData, boolean hideFlag) {
return getItemStack(material, displayName, loreList, isEnchant, customModelData, hideFlag, null);
}
/**
* 物品生成
*
* @param material 材质名称
* @param displayName 名称
* @param loreList lore
* @param isEnchant 附魔效果
* @param customModelData 自定义模型id
* @param hideFlag 隐藏标签
* @param replaceMap lore替换map
* @return 自定义物品
* @since 2.3.5
*/
public static ItemStack getItemStack(String material, String displayName, List loreList, Boolean isEnchant, int customModelData, boolean hideFlag, Map replaceMap) {
return getItemStack(material, displayName, loreList, isEnchant, customModelData, hideFlag, replaceMap, true);
}
/**
* 物品生成
*
* @param material 材质
* @param displayName 名称
* @param loreList lore
* @param isEnchant 附魔效果
* @param customModelData 自定义模型id
* @param hideFlag 隐藏标签
* @param replaceMap lore替换map
* @param hideEnchant 隐藏附魔效果
* @return 自定义物品
* @since 2.6.6
*/
public static ItemStack getItemStack(String material, String displayName, List loreList, boolean isEnchant, int customModelData, boolean hideFlag, Map replaceMap, boolean hideEnchant) {
return getItemStack(material, displayName, loreList, isEnchant, customModelData, hideFlag, replaceMap, hideEnchant, null);
}
/**
* 物品生成
*
* @param material 材质
* @param displayName 名称
* @param loreList lore
* @param isEnchant 附魔效果
* @param customModelData 自定义模型id
* @param hideFlag 隐藏标签
* @param replaceMap lore替换map
* @param hideEnchant 隐藏附魔效果
* @param customData 自定义数据
* @return 自定义物品
* @since 3.5.3
*/
public static ItemStack getItemStack(String material, String displayName, List loreList, boolean isEnchant, int customModelData, boolean hideFlag, Map replaceMap, boolean hideEnchant, String customData) {
// 生成item物品
ItemStack itemStack = getItemByMaterial(material);
ItemMeta itemMeta = getItemMeta(itemStack);
if (StrUtil.isNotEmpty(displayName)) {
itemMeta.setDisplayName(BaseUtil.replaceChatColor(displayName));
}
if (CollUtil.isNotEmpty(loreList)) {
itemMeta.setLore(BaseUtil.replaceChatColor(loreReplaceMap(loreList, replaceMap)));
}
// 附魔效果
if (isEnchant) {
ItemMetaUtil.setEnchant(itemMeta);
}
// 隐藏附魔效果
if (hideEnchant) {
ItemMetaUtil.hideEnchant(itemMeta);
}
// 隐藏物品属性
if (hideFlag) {
ItemMetaUtil.hideAttributes(itemMeta);
}
// 设置自定义数据
if (StrUtil.isNotEmpty(customData)) {
ItemMetaUtil.setPersistentData(itemMeta, customData, "system");
}
// 模型效果
if (customModelData > 0) {
ItemMetaUtil.setCustomModelData(itemMeta, customModelData);
}
itemStack.setItemMeta(itemMeta);
return itemStack;
}
/**
* 物品减少计算
*
* @param player 玩家
* @param itemStack 指定物品
* @param amount 数量
* @return 是否成功扣除
* @since 3.10.6
*/
public static Boolean removeItem(Player player, ItemStack itemStack, Integer amount) {
return removeItem(player, itemStack, amount, true);
}
/**
* 物品减少计算
*
* @param player 玩家
* @param itemStack 指定物品
* @param amount 数量
* @param strict 严格模式 true是走原版isSimilar ,false走简单对比
* @return 是否成功扣除
* @since 3.10.6
*/
public static Boolean removeItem(Player player, ItemStack itemStack, Integer amount, boolean strict) {
if (player == null || !player.isOnline()) {
return false;
}
PlayerInventory playerInventory = player.getInventory();
ItemStack[] contents;
if (BaseConstants.VERSION_ID <= VersionCheckEnum.V_1_8_8.getVersionId()) {
contents = playerInventory.getContents();
} else {
contents = playerInventory.getStorageContents();
}
int num = 0;
List items = new ArrayList<>();
for (ItemStack item : contents) {
if (item == null || Material.AIR.equals(item.getType())) {
continue;
}
// 严格模式
if (strict) {
if (!item.isSimilar(itemStack)) {
continue;
}
} else {
if (!isSimilar(item, itemStack)) {
continue;
}
}
num += item.getAmount();
items.add(item);
// 如果数量够了就不继续循环了
if (num >= amount) {
break;
}
}
if (num == amount) {
for (ItemStack item : items) {
playerInventory.removeItem(item);
}
return true;
}
if (num > amount) {
for (ItemStack item : items) {
if (amount == 0) {
return true;
}
if (amount >= item.getAmount()) {
amount = amount - item.getAmount();
playerInventory.removeItem(item);
} else {
item.setAmount(item.getAmount() - amount);
amount = 0;
}
}
return true;
}
return false;
}
/**
* 物品包含判断
*
* @param playerInventory 玩家背包
* @param itemStack 指定物品
* @param amount 数量
* @param strict 严格模式 true是走原版isSimilar ,false走简单对比
* @return true 包含
* @since 3.6.1
*/
public static Boolean containsItem(PlayerInventory playerInventory, ItemStack itemStack, Integer amount, boolean strict) {
ItemStack[] contents;
if (BaseConstants.VERSION_ID <= VersionCheckEnum.V_1_8_8.getVersionId()) {
contents = playerInventory.getContents();
} else {
contents = playerInventory.getStorageContents();
}
int num = 0;
for (ItemStack item : contents) {
if (item == null || Material.AIR.equals(item.getType())) {
continue;
}
// 严格模式
if (strict) {
if (!item.isSimilar(itemStack)) {
continue;
}
} else {
if (!isSimilar(item, itemStack)) {
continue;
}
}
num += item.getAmount();
// 如果数量够了就不继续循环了
if (num >= amount) {
break;
}
}
return num >= amount;
}
/**
* 进行物品发送
*
* @param player 玩家
* @param itemStack 物品
* @param amount 发送数量
* @since 3.5.9
*/
public static boolean addItem(Player player, ItemStack itemStack, int amount) {
return addItem(player, itemStack, amount, null);
}
/**
* 进行物品发送
*
* @param player 玩家
* @param itemStack 物品
* @param amount 发送数量
* @param msg 提醒消息
* @return true 有多余物品掉在地上
* @since 3.5.9
*/
public static boolean addItem(Player player, ItemStack itemStack, int amount, String msg) {
// 给玩家添加物品
Map dropItemMap = addItemReturnDropItemMap(player, itemStack, amount);
if (dropItemMap.isEmpty()) {
return false;
}
// 同步处理背包多余物品掉落在地上
HandySchedulerUtil.runTask(() -> {
for (Integer key : dropItemMap.keySet()) {
player.getWorld().dropItem(player.getLocation(), dropItemMap.get(key));
}
});
MessageUtil.sendMessage(player, msg);
return true;
}
/**
* 进行物品发送
*
* @param player 玩家
* @param itemStack 物品
* @param amount 发送数量
* @since 3.7.9
*/
public static Map addItemReturnDropItemMap(Player player, ItemStack itemStack, int amount) {
PlayerInventory playerInventory = player.getInventory();
Map dropItemMap = MapUtil.of();
int maxStackSize = itemStack.getMaxStackSize();
if (amount > maxStackSize) {
// 如果发送数量大于最大上限
itemStack.setAmount(maxStackSize);
dropItemMap.putAll(playerInventory.addItem(itemStack));
dropItemMap.putAll(addItemReturnDropItemMap(player, itemStack, amount - maxStackSize));
} else {
// 小于等于直接发送
itemStack.setAmount(amount);
dropItemMap.putAll(playerInventory.addItem(itemStack));
}
return dropItemMap;
}
/**
* 获取材质
*
* @param materialStr 材质
* @return Material
*/
public static Material getMaterial(String materialStr) {
return getMaterial(materialStr, Material.STONE);
}
/**
* 获取材质
*
* @param materialStr 材质
* @param defaultMaterial 未找到的的默认材质
* @return Material
*/
public static Material getMaterial(String materialStr, Material defaultMaterial) {
if (StrUtil.isEmpty(materialStr)) {
return defaultMaterial;
}
materialStr = materialStr.toUpperCase(Locale.ROOT);
Material material = Material.getMaterial(materialStr);
if (material != null) {
return material;
}
if (BaseConstants.VERSION_ID > VersionCheckEnum.V_1_12.getVersionId()) {
material = Material.getMaterial("LEGACY_" + materialStr, true);
if (material != null) {
return material;
}
}
// 小于1.8处理
if (BaseConstants.VERSION_ID < VersionCheckEnum.V_1_8.getVersionId()) {
return defaultMaterial;
}
return XMaterial.matchXMaterial(materialStr).orElse(XMaterial.matchXMaterial(defaultMaterial)).parseMaterial();
}
/**
* 获取材质的物品
*
* @param materialStr 材质
* @return ItemStack
* @since 3.5.3
*/
public static ItemStack getItemByMaterial(String materialStr) {
return getItemByMaterial(materialStr, Material.STONE);
}
/**
* 获取对应材质的物品
*
* @param materialStr 材质
* @param defaultMaterial 未找到的的默认材质
* @return ItemStack
* @since 3.5.3
*/
public static ItemStack getItemByMaterial(String materialStr, Material defaultMaterial) {
if (StrUtil.isEmpty(materialStr)) {
return new ItemStack(defaultMaterial);
}
materialStr = materialStr.toUpperCase(Locale.ROOT);
Material material = Material.getMaterial(materialStr);
if (material != null) {
return new ItemStack(material);
}
if (BaseConstants.VERSION_ID > VersionCheckEnum.V_1_12.getVersionId()) {
material = Material.getMaterial("LEGACY_" + materialStr, true);
if (material != null) {
return new ItemStack(material);
}
}
// 小于1.8处理
if (BaseConstants.VERSION_ID < VersionCheckEnum.V_1_8.getVersionId()) {
return new ItemStack(defaultMaterial);
}
return XMaterial.matchXMaterial(materialStr).orElse(XMaterial.matchXMaterial(defaultMaterial)).parseItem();
}
/**
* 正确获取主手物品
*
* @param playerInventory 玩家背包
* @return ItemStack
* @since 1.6.0
*/
@SuppressWarnings("deprecation")
public static ItemStack getItemInMainHand(PlayerInventory playerInventory) {
if (BaseConstants.VERSION_ID < VersionCheckEnum.V_1_9.getVersionId()) {
return playerInventory.getItemInHand();
}
return playerInventory.getItemInMainHand();
}
/**
* 正确获取主手物品
*
* @param playerInventory 玩家背包
* @param itemStack 物品
* @since 3.7.1
*/
@SuppressWarnings("deprecation")
public static void setItemInMainHand(PlayerInventory playerInventory, ItemStack itemStack) {
if (BaseConstants.VERSION_ID < VersionCheckEnum.V_1_9.getVersionId()) {
playerInventory.setItemInHand(itemStack);
return;
}
playerInventory.setItemInMainHand(itemStack);
}
/**
* 获取必定不为空的ItemMeta
*
* @param itemStack ItemStack
* @return ItemMeta
* @since 1.7.0
*/
public static ItemMeta getItemMeta(ItemStack itemStack) {
if (itemStack == null) {
itemStack = new ItemStack(Material.STONE);
}
ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta == null) {
return new ItemStack(Material.STONE).getItemMeta();
}
return itemMeta;
}
/**
* 进行lore的变量替换
*
* @param loreList 原本lore
* @param replaceMap 替换map
* @return 新lore
* @since 2.3.5
*/
public static List loreReplaceMap(List loreList, Map replaceMap) {
List newLoreList = new ArrayList<>();
if (replaceMap != null && !replaceMap.isEmpty() && CollUtil.isNotEmpty(loreList)) {
for (String lore : loreList) {
for (String key : replaceMap.keySet()) {
if (lore.contains("${" + key + "}") && replaceMap.get(key) != null) {
lore = StrUtil.replace(lore, key, replaceMap.get(key));
}
}
newLoreList.add(lore);
}
} else {
newLoreList.addAll(loreList);
}
return newLoreList;
}
/**
* 进行lore的变量批量替换
*
* @param loreList 原本loreList
* @param replaceMap 替换map
* @param def 默认值
* @return 新loreList
* @since 2.3.5
*/
public static List loreBatchReplaceMap(List loreList, Map> replaceMap, String def) {
if (CollUtil.isEmpty(loreList) || replaceMap == null || replaceMap.isEmpty()) {
return loreList;
}
List newLoreList = new ArrayList<>();
for (String lore : loreList) {
newLoreList.addAll(loreBatchReplaceMap(lore, replaceMap, def));
}
return newLoreList;
}
/**
* 进行lore的变量批量替换
*
* @param lore 原本lore
* @param replaceMap 替换map
* @param def 默认值
* @return 新lore
* @since 2.3.5
*/
public static List loreBatchReplaceMap(String lore, Map> replaceMap, String def) {
List loreList = new ArrayList<>();
if (StrUtil.isEmpty(lore)) {
loreList.add(lore);
return loreList;
}
if (replaceMap == null || replaceMap.isEmpty()) {
loreList.add(lore);
return loreList;
}
if (StrUtil.isEmpty(def)) {
def = "";
}
for (String key : replaceMap.keySet()) {
if (lore.contains("${" + key + "}")) {
List replaceList = replaceMap.get(key);
if (CollUtil.isEmpty(replaceList)) {
loreList.add(StrUtil.replace(lore, key, def));
} else {
for (String replaceStr : replaceList) {
loreList.add(StrUtil.replace(lore, key, replaceStr));
}
}
break;
}
}
if (CollUtil.isEmpty(loreList)) {
loreList.add(lore);
}
return loreList;
}
/**
* 设置数据容器
*
* @param itemStack 物品
* @param customData 自定义数据
* @param key key
* @since 3.1.3
*/
public static void setPersistentData(ItemStack itemStack, String customData, String key) {
ItemMeta itemMeta = itemStack.getItemMeta();
// 设置数据
ItemMetaUtil.setPersistentData(itemMeta, customData, key);
// 重新设置回去
itemStack.setItemMeta(itemMeta);
}
/**
* 获取数据
*
* @param itemStack 物品
* @param key key
* @return 自定义数据
* @since 3.1.3
*/
public static Optional getPersistentData(ItemStack itemStack, String key) {
ItemMeta itemMeta = itemStack.getItemMeta();
return ItemMetaUtil.getPersistentData(itemMeta, key);
}
/**
* 简单判断物品是否相等
* 1. 判断null
* 2. 判断物品类型
* 3. 判断物品名称
* 4. 判断物品lore
*
* @param one 物品一
* @param two 物品二
* @return true相等
* @since 3.3.7
*/
public static boolean isSimilar(ItemStack one, ItemStack two) {
if (one == two) {
return true;
}
if (one == null || two == null) {
return false;
}
// 1.判断类型
if (!one.getType().equals(two.getType())) {
return false;
}
// 2. 1.13以下判断物品数据是否相同(针对子ID)
if (BaseConstants.VERSION_ID < VersionCheckEnum.V_1_13.getVersionId()) {
MaterialData oneData = one.getData();
MaterialData twoData = two.getData();
if (oneData != null && twoData != null && oneData.getData() != twoData.getData()) {
return false;
}
}
// 3. 判断元数据是否存在
ItemMeta oneItemMeta = one.getItemMeta();
ItemMeta twoItemMeta = two.getItemMeta();
if (oneItemMeta == twoItemMeta) {
return true;
}
if (oneItemMeta == null || twoItemMeta == null) {
return false;
}
// 4. 判断名称
if (!StrUtil.equals(oneItemMeta.getDisplayName(), twoItemMeta.getDisplayName())) {
return false;
}
// 5.判断lore
return CollUtil.equals(oneItemMeta.getLore(), twoItemMeta.getLore());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy