package cc.util.bossshop; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; /** * 一个用于获取NMS类的类 * @author 聪聪 * */ public class NMSHelper{ /** * NMS类 */ public static final Class clazz_EntityPlayerMP; public static final Class clazz_EntityPlayer; public static final Class clazz_NMSItemStack; public static final Class clazz_NMSWorld; public static final Class clazz_IInventory; public static final Class clazz_NBTBase; public static final Class clazz_NBTTagByte; public static final Class clazz_NBTTagShort; public static final Class clazz_NBTTagInt; public static final Class clazz_NBTTagLong; public static final Class clazz_NBTTagFloat; public static final Class clazz_NBTTagDouble; public static final Class clazz_NBTTagByteArray; public static final Class clazz_NBTTagString; public static final Class clazz_NBTTagIntArray; public static final Class clazz_NBTTagList; public static final Class clazz_NBTTagCompound; public static final Method method_CraftItemStack_asNMSCopy; public static final Method method_CraftItemStack_asCraftMirror; public static final Method method_CraftPlayer_getHandle; public static final Method method_NMSItemStack_getTag; //public static final Method method_NMSItemStack_setTag;//此方法歧义较大不建议启用 public static final Method method_NBTTagCompound_isEmpty; public static final Method method_NBTTagCompound_clone; public static final Method method_NBTTagCompound_set; public static final Method method_NBTTagList_add; public static final Field field_NBTTagString_value; public static final Field field_NBTTagByte_value; public static final Field field_NBTTagShort_value; public static final Field field_NBTTagInt_value; public static final Field field_NBTTagFloat_value; public static final Field field_NBTTagDouble_value; public static final Field field_NBTTagLong_value; public static final Field field_NBTTagList_value; public static final Field field_NBTTagCompound_map; public static final Field field_NMSItemStack_tag; /** * CraftBukkit类 */ public static final Class clazz_CraftItemStack; public static final Class clazz_CraftInventory; public static final Class clazz_CraftPlayer; static{ String packetPath=""; clazz_CraftItemStack=ClassHelper.getCBTClass("inventory.CraftItemStack"); clazz_CraftInventory=ClassHelper.getCBTClass("inventory.CraftInventory"); Method method_CraftInventory_getInventory=ClassHelper.getMethod(clazz_CraftInventory,"getInventory"); clazz_IInventory=method_CraftInventory_getInventory.getReturnType(); clazz_CraftPlayer=ClassHelper.getCBTClass("entity.CraftPlayer"); method_CraftPlayer_getHandle=ClassHelper.getMethod(clazz_CraftPlayer,"getHandle"); clazz_EntityPlayerMP=method_CraftPlayer_getHandle.getReturnType(); clazz_EntityPlayer=clazz_EntityPlayerMP.getSuperclass(); clazz_NMSWorld=clazz_EntityPlayer.getDeclaredConstructors()[0].getParameterTypes()[0]; //NMS ItemStck ItemStack tItem=new ItemStack(Material.STONE); method_CraftItemStack_asNMSCopy=ClassHelper.getMethod(clazz_CraftItemStack,"asNMSCopy",ItemStack.class); Object tNMSItemStack_mcitem=ClassHelper.invokeStaticMethod(method_CraftItemStack_asNMSCopy,tItem); clazz_NMSItemStack=tNMSItemStack_mcitem.getClass(); method_NMSItemStack_getTag=ClassHelper.getUnknowMethod(clazz_NMSItemStack,"NBTTagCompound").get(0); //NBT clazz_NBTTagCompound=method_NMSItemStack_getTag.getReturnType(); packetPath=NMSHelper.getClassPrefix(clazz_NBTTagCompound.getName()); clazz_NBTBase=ClassHelper.getClass(packetPath+"NBTBase"); clazz_NBTTagByte=ClassHelper.getClass(packetPath+"NBTTagByte"); clazz_NBTTagShort=ClassHelper.getClass(packetPath+"NBTTagShort"); clazz_NBTTagInt=ClassHelper.getClass(packetPath+"NBTTagInt"); clazz_NBTTagLong=ClassHelper.getClass(packetPath+"NBTTagLong"); clazz_NBTTagFloat=ClassHelper.getClass(packetPath+"NBTTagFloat"); clazz_NBTTagDouble=ClassHelper.getClass(packetPath+"NBTTagDouble"); clazz_NBTTagByteArray=ClassHelper.getClass(packetPath+"NBTTagByteArray"); clazz_NBTTagString=ClassHelper.getClass(packetPath+"NBTTagString"); clazz_NBTTagIntArray=ClassHelper.getClass(packetPath+"NBTTagIntArray"); clazz_NBTTagList=ClassHelper.getClass(packetPath+"NBTTagList"); method_NBTTagCompound_isEmpty=ClassHelper.getUnknowMethod(clazz_NBTTagCompound,boolean.class).get(0); method_NBTTagCompound_clone=ClassHelper.getUnknowMethod(clazz_NBTTagCompound,clazz_NBTBase).get(0); method_NBTTagCompound_set=ClassHelper.getUnknowMethod(clazz_NBTTagCompound,void.class,new Class[]{String.class,clazz_NBTBase}).get(0); method_CraftItemStack_asCraftMirror=ClassHelper.getMethod(clazz_CraftItemStack,"asCraftMirror",clazz_NMSItemStack); method_NBTTagList_add=ClassHelper.getUnknowMethod(clazz_NBTTagList,void.class,clazz_NBTBase).get(0); field_NBTTagByte_value=ClassHelper.getField(clazz_NBTTagByte,byte.class,-1).get(0); field_NBTTagShort_value=ClassHelper.getField(clazz_NBTTagShort,short.class,-1).get(0); field_NBTTagInt_value=ClassHelper.getField(clazz_NBTTagInt,int.class,-1).get(0); field_NBTTagFloat_value=ClassHelper.getField(clazz_NBTTagFloat,float.class,-1).get(0); field_NBTTagDouble_value=ClassHelper.getField(clazz_NBTTagDouble,double.class,-1).get(0); field_NBTTagLong_value=ClassHelper.getField(clazz_NBTTagLong,long.class,-1).get(0); field_NBTTagString_value=ClassHelper.getField(clazz_NBTTagString,String.class,Modifier.PRIVATE).get(0); field_NBTTagList_value=ClassHelper.getField(clazz_NBTTagList,List.class,-1).get(0); field_NBTTagCompound_map=ClassHelper.getField(clazz_NBTTagCompound,Map.class,-1).get(0); field_NMSItemStack_tag=ClassHelper.getField(clazz_NMSItemStack,clazz_NBTTagCompound,-1).get(0); } /** * 获取类全名的前段字符串 * @param classFullName * @return */ public static String getClassPrefix(String classFullName){ String packetPath=""; int pos=-1; if((pos=classFullName.lastIndexOf("."))!=-1) packetPath=classFullName.substring(0,pos+1); return packetPath; } public static Set getNBTFirstDeepNodeList(ItemStack pItem){ Object nbtTag=getNBTTagCompound(pItem); if(nbtTag==null) return null; Map tMap=getNBTTagMapFromTag(nbtTag); Set rSet=new HashSet<>(); for(String skey : tMap.keySet()) rSet.add(skey); return rSet; } /** * 获取Bukkit物品的NBT标签 * @param pItem Bukkit物品实例 * @return NBTTagCompound实例或者null */ public static Object getNBTTagCompound(ItemStack pItem){ Object nmsItem=NMSHelper.getNMSItem(pItem); if(nmsItem==null) return null; return ClassHelper.invokeMethod(nmsItem,method_NMSItemStack_getTag); } /** * 获取物品的NBT的的值域Map * @param pItem 物品,可以为null * @return 可能为null */ public static Map getNBTTagMapFromItem(ItemStack pItem){ return getNBTTagMapFromTag(getNBTTagCompound(pItem)); } /** * 获取Bukkit物品对应的MC物品 * @param pItem Bukkit物品实例 * @return NBTTagCompound实例或者null */ public static Object getNMSItem(ItemStack pItem){ if(pItem==null||pItem.getType()==Material.AIR) return null; return ClassHelper.invokeStaticMethod(method_CraftItemStack_asNMSCopy,pItem); } /** * 获取类类型为NBTTagCompound的值域Map * @param pNBTTagCompound 实例,类型必须为NBTTagCompound,可以为null * @return 可能为非null */ public static Map getNBTTagMapFromTag(Object pNBTTagCompound){ if(pNBTTagCompound==null) return new HashMap<>(); return (Map)ClassHelper.getFieldValue(pNBTTagCompound,field_NBTTagCompound_map); } /** * 从NBTTagCompound实例中移除指定的标签 * @param pNBTTagCompound NBTTagCompound实例 * @param pNBTLabel NBT标签 * @return 移除的值或null */ public static Object removeFromNBTTagCompound(Object pNBTTagCompound,String pNBTLabel){ Map tMap=NMSHelper.getNBTTagMapFromTag(pNBTTagCompound); if(tMap==null) return null; return tMap.remove(pNBTLabel); } /** * 获取获取物品的Json字符串 */ public static String getItemJson(ItemStack pItem){ if(pItem==null||pItem.getType()==Material.AIR) return "{}"; String itemJson="{"; itemJson+="id:"+pItem.getTypeId(); itemJson+=",Damage:"+pItem.getDurability(); Object tagNBTTagCompound=getNBTTagCompound(pItem); if(tagNBTTagCompound!=null) itemJson+=",tag:"+getNBTBaseValue(tagNBTTagCompound); itemJson+="}"; return itemJson; } /** * 获取NBTBase的子类的Json值 *

* 只对NBTTagString的toString方法重写
* 其他方法不变 *

* @param pNBTBase * @return json字符串 */ public static String getNBTBaseValue(Object pNBTBase){ if(pNBTBase==null) return ""; if(NMSHelper.clazz_NBTTagCompound.isInstance(pNBTBase)){ Map tNBTContents=(Map)ClassHelper.getFieldValue(pNBTBase,NMSHelper.field_NBTTagCompound_map); if(tNBTContents==null||tNBTContents.isEmpty()) return "{}"; String contentJson = "{"; for (String sKey : tNBTContents.keySet()) { Object tContentNode=tNBTContents.get(sKey); if(tContentNode==null) continue; contentJson+=sKey+':'+getNBTBaseValue(tContentNode)+','; } if(contentJson.lastIndexOf(",")!=-1) contentJson=contentJson.substring(0,contentJson.length()-1); return contentJson + "}"; }else if(NMSHelper.clazz_NBTTagList.isInstance(pNBTBase)){ List tNBTContents=(List)ClassHelper.getFieldValue(pNBTBase,NMSHelper.field_NBTTagList_value); if(tNBTContents==null||tNBTContents.isEmpty()) return "[]"; String contentJson = "["; int i=0; for(Object tContentNode : tNBTContents){ if(tContentNode==null) continue; contentJson+=i+":"+getNBTBaseValue(tContentNode).toString()+','; i++; } if(contentJson.lastIndexOf(",")!=-1) contentJson=contentJson.substring(0,contentJson.length()-1); return contentJson+"]"; }else if(NMSHelper.clazz_NBTTagString.isInstance(pNBTBase)){ String value=(String)ClassHelper.getFieldValue(pNBTBase,NMSHelper.field_NBTTagString_value); value=value.replace("\"","\\\""); return "\""+value+"\""; }else return pNBTBase.toString(); } }