1
0
mirror of https://e.coding.net/circlecloud/BossShop-re.git synced 2025-11-26 21:46:19 +00:00

2.2.3源码

This commit is contained in:
2016-06-25 23:26:56 +08:00
parent 719ea8a005
commit b6eb7eeff9
97 changed files with 17042 additions and 0 deletions

View File

@@ -0,0 +1,794 @@
package cc.util.bossshop;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
public class ClassHelper{
public static String mTestVersion="v1_7_R4";
/**
* MC版本,请勿直接获取,请使用{@link ClassHelper#getServerVersion()}来获取
*/
@Deprecated
private static String mMCVersion;
/**
* 获取服务的Bukkit版本
*/
public static String getServerVersion(){
if(mMCVersion==null){
if(Bukkit.getServer()!=null){
String className=Bukkit.getServer().getClass().getPackage().getName();
mMCVersion=className.substring(className.lastIndexOf('.')+1);
}else mMCVersion=mTestVersion;
}
return mMCVersion;
}
/**
* 查看指定类名是否加载,不会报错
* @param name 类完整名字
*/
public static boolean isClassLoaded(String name){
try{
Class.forName(name);
return true;
}catch(Throwable e){
return false;
}
}
/**
* 获取org.bukkit.craftbukkit类的全名
* @param pName 短名字
* @return 完整名字
*/
public static String getCBTName(String pName){
return "org.bukkit.craftbukkit."+ClassHelper.getServerVersion()+"."+pName;
}
/**
* 获取NMS类的{@link Class}对象
* @param pClazz NMS类短名字
*/
public static Class<?> getNMSClass(String pClazz){
return ClassHelper.getClass(getNMSName(pClazz));
}
/**
* 获取NMS类的全名
* @param pName 短名字
* @return 完整名字
*/
public static String getNMSName(String pName){
return "net.minecraft.server."+ClassHelper.getServerVersion()+"."+pName;
}
/**
* 获取craftbukkit类的{@link Class}对象
* @param pClazz craftbukkit类短名字,(org.bukkit.craftbukkit.version后的名字)
*/
public static Class<?> getCBTClass(String pClazz){
return ClassHelper.getClass(getCBTName(pClazz));
}
/**
* 取出指定Object中的指定名字的值域
* @param pObj 要取数据的实例
* @param pField 值域名
* @return 值域的值
*/
public static Object getFieldValue(Object pObj,String pField){
Validate.notNull(pObj,"要获取值域的对象不能为null对象");
Class<?> tClazz=pObj.getClass();
Field tField=null;
try{
tField=tClazz.getDeclaredField(pField);
tField.setAccessible(true);
return tField.get(pObj);
}catch(NoSuchFieldException|SecurityException|IllegalArgumentException|IllegalAccessException e){
FBukkit.severe("获取"+tClazz.getName()+"的类的实例对象的值域"+pField+"时发生了错误",e);
}
return null;
}
/**
* 设置指定对象实例的指定名字的值域的值
* @param pObj 对象实例
* @param pField 值域名
* @param pValue 要设置成的值
*/
public static void setFieldValue(Object pObj,String pField,Object pValue){
Validate.notNull(pObj,"要获取值域的对象不能为null对象");
Class<?> tClazz=pObj.getClass();
Field tField=null;
try{
tField=tClazz.getDeclaredField(pField);
tField.setAccessible(true);
tField.set(pObj,pValue);
}catch(NoSuchFieldException|SecurityException|IllegalArgumentException|IllegalAccessException e){
FBukkit.severe("设置"+tClazz.getName()+"的类的实例对象的值域"+pField+"时发生了错误",e);
}
}
/**
* 获取指定对象实例指定值域的值
* @param pObj 对象
* @param pField 值域
*/
public static Object getFieldValue(Object pObj,Field pField){
try{
Validate.notNull(pObj,"要获取值域的对象不能为null对象");
pField.setAccessible(true);
return pField.get(pObj);
}catch(IllegalArgumentException|IllegalAccessException e){
FBukkit.severe("获取"+pObj.getClass().getName()+"的类的实例对象的值域"+pField+"时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 设置指定对象实例的指定名字的值域的值
* @param pObj 对象实例
* @param pField 值域名
* @param pValue 要设置成的值
*/
public static void setFieldValue(Object pObj,Field pField,Object pValue){
try{
pField.setAccessible(true);
pField.set(pObj,pValue);
}catch(IllegalArgumentException|IllegalAccessException e){
FBukkit.severe("设置"+pObj.getClass().getName()+"的类的实例对象的值域"+pField+"时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 获取指定对象实例,指定类型,指定前缀修饰符的值域的值
* @param pObj 对象实例
* @param pFieldType 值域类型
* @param modifier 值域修饰符,如果不限制则为-1
*/
public static <T> T getFieldValue(Object pObj,Class<T> pFieldType,int modifier){
Field tField=ClassHelper.getField(pObj.getClass(),pFieldType,modifier).get(0);
try{
tField.setAccessible(true);
return (T)tField.get(pObj);
}catch(IllegalArgumentException|IllegalAccessException e){
FBukkit.severe("获取"+pObj.getClass().getName()+"的类实例的指定类型"+pFieldType+"值域时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 设置指定对象实例,指定类型,指定前缀修饰符的值域的值
* @param pObj 对象实例
* @param pFieldType 值域类型
* @param pValue 要设置成的值
* @param modifier 值域修饰符,如果不限制则为-1
*/
public static <T> void setFiledValue(Object pObj,Class<T> pFieldType,Object pValue,int modifier){
Field tField=ClassHelper.getField(pObj.getClass(),pFieldType,modifier).get(0);
try{
if(tField!=null){
tField.setAccessible(true);
tField.set(pObj,pValue);
}
}catch(IllegalArgumentException|IllegalAccessException e){
FBukkit.severe("设置"+pObj.getClass().getName()+"的类实例的指定类型"+pFieldType+"值域时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 获取指定对象实例,指定类型,指定前缀修饰符的值域
* @param pClazz 对象实例
* @param pFieldClassShorName 值域类型短名字
* @param modifier 值域修饰符,如果不限制则为-1
*/
public static Field getFieldByClassName(Class<?> pClazz,String pFieldClassShorName,int modifier){
try{
Field[] tFields=pClazz.getDeclaredFields();
for(Field sField : tFields){
if(sField.getType().getSimpleName().equals(pFieldClassShorName)&&(sField.getModifiers()==modifier||modifier<0)) return sField;
}
throw new NoSuchFieldException(""+pClazz.getName()+"不存在值域类型短名字为: "+pFieldClassShorName+",且类型修饰符为: "+modifier+"的值域");
}catch(SecurityException|IllegalArgumentException|NoSuchFieldException e){
FBukkit.severe("获取"+pClazz.getName()+"类的值域类型短名字为"+pFieldClassShorName+"的值域时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 获取指定对象实例,指定类型,指定前缀修饰符的值域
* @param pClazz 对象实例
* @param pFieldName 值域类型短名字
* @param modifier 值域修饰符,如果不限制则为-1
*/
public static Field getFieldByFieldName(Class<?> pClazz,String pFieldName,int modifier){
try{
Field[] tFields=pClazz.getDeclaredFields();
for(Field sField : tFields){
if(sField.getName().equals(pFieldName)&&(sField.getModifiers()==modifier||modifier<0)) return sField;
}
throw new NoSuchFieldException(""+pClazz.getName()+"不存在名字为: "+pFieldName+",且类型修饰符为: "+modifier+"的值域");
}catch(SecurityException|IllegalArgumentException|NoSuchFieldException e){
FBukkit.severe("获取"+pClazz.getName()+"类的值域名字为"+pFieldName+"的值域时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 获取指定对象实例,指定类型,指定前缀修饰符的值域
* @param pClazz 对象实例
* @param pFieldType 值域类型
* @param modifier 值域修饰符,如果不限制则为-1
*/
public static ArrayList<Field> getField(Class<?> pClazz,Class<?> pFieldClazz,int modifier){
try{
ArrayList<Field> findFields=new ArrayList<>();
Field[] tFields=pClazz.getDeclaredFields();
for(Field sField : tFields)
if(isSameClazz(sField.getType(),pFieldClazz)&&(sField.getModifiers()==modifier||modifier<0)) findFields.add(sField);
if(!findFields.isEmpty()) return findFields;
throw new NoSuchFieldException(""+pClazz.getName()+"不存在类型为: "+pFieldClazz.getName()+",且类型修饰符为: "+modifier+"的值域");
}catch(SecurityException|IllegalArgumentException|NoSuchFieldException e){
FBukkit.severe("获取"+pClazz.getName()+"的类的值域"+pFieldClazz+"时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 执行指定对象实例的无参数方法,并返回结果
* @param pObj 对象实例
* @param pMethod 方法名
*/
public static Object invokeMethod(Object pObj,String pMethod){
return invokeMethod(pObj,pMethod,new Class<?>[]{},new Object[]{});
}
/**
* 执行指定实例的单参数方法,并返回结果
* @param pObj 实例对象
* @param pMethod 方法名
* @param pArgClazz 参数类型
* @param pArg 参数
*/
public static Object invokeMethod(Object pObj,String pMethod,Class<?> pArgClazz,Object pArg){
return invokeMethod(pObj,pMethod,new Class<?>[]{pArgClazz},new Object[]{pArg});
}
/**
* 执行指定实例的指定方法,并返回结果
* @param pObj 实例对象
* @param pMethod 方法名
* @param pArgsClazzs 参数类型
* @param pArgs 参数
*/
public static Object invokeMethod(Object pObj,String pMethod,Class<?>[] pArgsClazzs,Object[] pArgs){
if(pObj==null) return null;
if(pMethod==null) return null;
Class<?> tClazz=pObj.getClass();
Method tMethod=null;
try{
if(pArgsClazzs==null||pArgsClazzs.length==0) tMethod=tClazz.getDeclaredMethod(pMethod);
else tMethod=tClazz.getDeclaredMethod(pMethod,pArgsClazzs);
tMethod.setAccessible(true);
return tMethod.invoke(pObj,pArgs);
}catch(IllegalAccessException|IllegalArgumentException|InvocationTargetException|NoSuchMethodException|SecurityException e){
FBukkit.severe("执行"+tClazz.getName()+"的类的方法: "+pMethod+",参数: "+Arrays.asList(pArgsClazzs)+" "+"时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 执行指定对象实例的无参数方法,并返回结果
* @param pObj 对象实例
* @param pMethod 方法
*/
public static Object invokeMethod(Object pObj,Method pMethod){
return invokeMethod(pObj,pMethod,new Object[]{});
}
/**
* 执行指定实例的单参数方法,并返回结果
* @param pObj 实例对象
* @param pMethod 方法
* @param pArgClazz 参数类型
* @param pArg 参数
*/
public static Object invokeMethod(Object pObj,Method pMethod,Object pArg){
return invokeMethod(pObj,pMethod,new Object[]{pArg});
}
/**
* 执行指定实例的指定方法,并返回结果
* @param pObj 实例对象
* @param pMethod 方法
* @param pArgsClazzs 参数类型
* @param pArgs 参数
*/
public static Object invokeMethod(Object pObj,Method pMethod,Object[] pArgs){
if(pObj==null) return null;
if(pMethod==null) return null;
Class<?> tClazz=pObj.getClass();
try{
pMethod.setAccessible(true);
return pMethod.invoke(pObj,pArgs);
}catch(IllegalAccessException|IllegalArgumentException|InvocationTargetException|SecurityException e){
FBukkit.severe("执行"+tClazz.getName()+"的类的方法: "+pMethod+"时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 执行指定实例且返回类型特定的的无参数方法,并返回结果
* @param pObj 实例对象
* @param pMethod 方法名
*/
public static <T> T invokeMethod(Object pObj,Class<T> pReturnType){
return invokeMethod(pObj,pReturnType,new Class<?>[]{},new Object[]{});
}
/**
* 执行指定实例且返回类型特定的单参数方法,并返回结果
* @param pObj 实例对象
* @param pMethod 方法名
* @param pArgClazz 参数类型
* @param pArg 参数
*/
public static <T> T invokeMethod(Object pObj,Class<T> pReturnType,Class<?> pArgClazz,Object pArg){
return invokeMethod(pObj,pReturnType,new Class<?>[]{pArgClazz},new Object[]{pArg});
}
/**
* 执行指定实例的指定方法,并返回结果
* @param pObj 实例对象
* @param pMethod 方法名
* @param pArgsClazzs 参数类型
* @param pArgs 参数
*/
public static <T> T invokeMethod(Object pObj,Class<T> pReturnType,Class<?>[] pArgsClazzs,Object[] pArgs){
Validate.notNull(pObj,"要执行方法的对象不能为null对象");
Class<?> tClazz=pObj.getClass();
try{
Method tMethod=ClassHelper.getUnknowMethod(tClazz,pReturnType,pArgsClazzs).get(0);
tMethod.setAccessible(true);
return (T)tMethod.invoke(pObj,pArgs);
}catch(IllegalAccessException|IllegalArgumentException|InvocationTargetException|SecurityException e){
FBukkit.severe("执行"+tClazz.getName()+"的类的未知方法,返回类型: "+pReturnType.getName()+"[参数: "+pArgsClazzs+"] "+"时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 执行指定对象名指定的无参静态方法,并返回结果
* @param pClazz 对象
* @param pMethod 方法名
*/
public static Object invokeStaticMethod(String pClazz,String pMethod){
return invokeStaticMethod(pClazz,pMethod,new Class<?>[]{},new Object[]{});
}
/**
* 执行指定对象名指定的单参数参静态方法,并返回结果
* @param pClazz 对象
* @param pMethod 方法名
* @param pArgClazz 参数类型
* @param pArg 参数
*/
public static Object invokeStaticMethod(String pClazz,String pMethod,Class<?> pArgClazz,Object pArg){
return invokeStaticMethod(pClazz,pMethod,new Class<?>[]{pArgClazz},new Object[]{pArg});
}
/**
* 执行指定对象名指定的静态方法,并返回结果
* @param pClazz 对象
* @param pMethod 方法名
* @param pArgsClazzs 参数类型
* @param pArgs 参数
*/
public static Object invokeStaticMethod(String pClazz,String pMethod,Class<?>[] pArgsClazzs,Object[] pArgs){
try{
Class<?> tClazz=Class.forName(pClazz);
return ClassHelper.invokeStaticMethod(tClazz,pMethod,pArgsClazzs,pArgs);
}catch(IllegalArgumentException|SecurityException|ClassNotFoundException e){
FBukkit.severe("执行"+pClazz+"的类的方法: "+pMethod+",[参数: "+pArgsClazzs+"] "+"时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 执行指定对象指定的无参静态方法,并返回结果
* @param pClazz 对象
* @param pMethod 方法名
*/
public static Object invokeStaticMethod(Class<?> pClazz,String pMethod){
return invokeStaticMethod(pClazz,pMethod,new Class<?>[]{},new Object[]{});
}
/**
* 执行指定对象名指定的单参数参静态方法,并返回结果
* @param pClazz 对象
* @param pMethod 方法名
* @param pArgClazz 参数类型
* @param pArg 参数
*/
public static Object invokeStaticMethod(Class<?> pClazz,String pMethod,Class<?> pArgClazz,Object pArg){
return invokeStaticMethod(pClazz,pMethod,new Class<?>[]{pArgClazz},new Object[]{pArg});
}
/**
* 执行指定对象名指定的静态方法,并返回结果
* @param pClazz 对象
* @param pMethod 方法名
* @param pArgsClazzs 参数类型
* @param pArgs 参数
*/
public static Object invokeStaticMethod(Class<?> pClazz,String pMethod,Class<?>[] pArgClazz,Object[] pArgs){
Method tMethod=null;
try{
if(pArgClazz==null||pArgClazz.length==0) tMethod=pClazz.getDeclaredMethod(pMethod);
else tMethod=pClazz.getDeclaredMethod(pMethod,pArgClazz);
return invokeStaticMethod(tMethod,pArgs);
}catch(IllegalArgumentException|NoSuchMethodException|SecurityException e){
FBukkit.severe("执行"+pClazz+"的类的方法: +pMethod,[参数: "+pArgClazz+"] "+"时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 执行指定的无参静态方法
* @param pMethod 方法
*/
public static Object invokeStaticMethod(Method pMethod){
try{
pMethod.setAccessible(true);
return pMethod.invoke(null);
}catch(IllegalAccessException|IllegalArgumentException|InvocationTargetException e){
FBukkit.severe("执行方法: "+pMethod+",[参数: 无] "+"时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 执行指定的单参静态方法
* @param pMethod 方法
* @param pArg 参数
*/
public static Object invokeStaticMethod(Method pMethod,Object pArg){
try{
pMethod.setAccessible(true);
return invokeStaticMethod(pMethod,new Object[]{pArg});
}catch(IllegalArgumentException e){
FBukkit.severe("执行方法: "+pMethod+",[参数: "+pArg+"] "+"时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 执行指定的单参静态方法
* @param pMethod 方法
* @param pArgs 参数
*/
public static Object invokeStaticMethod(Method pMethod,Object[] pArgs){
try{
pMethod.setAccessible(true);
return pMethod.invoke(null,pArgs);
}catch(IllegalAccessException|IllegalArgumentException|InvocationTargetException e){
FBukkit.severe("执行方法: "+pMethod+",[参数: "+pArgs+"] "+"时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 执行类的无参构造函数,并返回结果
* @param pClazz 类全名
*/
public static Object getInstance(String pClazz){
return getInstance(pClazz,new Class<?>[]{},new Object[]{});
}
/**
* 执行类的单参构造函数,并返回结果
* @param pClazz 类全名
* @param pArgClazz 参数类型
* @param pArg 参数
*/
public static Object getInstance(String pClazz,Class<?> pArgClazz,Object pArg){
return getInstance(pClazz,new Class<?>[]{pArgClazz},new Object[]{pArg});
}
/**
* 执行类的指定参数构造函数,并返回结果
* @param pClazz 类全名
* @param pArgsClazzs 参数类型
* @param pArgs 参数
*/
public static Object getInstance(String pClazz,Class<?>[] pArgsClazzs,Object[] pArgs){
try{
Class<?> tClazz=Class.forName(pClazz);
return ClassHelper.getInstance(tClazz,pArgsClazzs,pArgs);
}catch(ClassNotFoundException|SecurityException|IllegalArgumentException e){
FBukkit.severe("使用参数"+pArgsClazzs+"实例化类"+pClazz+"时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 执行类的无参构造函数,并返回结果
* @param pClazz 类
*/
public static Object getInstance(Class<?> pClazz){
return getInstance(pClazz,new Class<?>[]{},new Object[]{});
}
/**
* 执行类的单参构造函数,并返回结果
* @param pClazz 类
* @param pArgClazz 参数类型
* @param pArg 参数
*/
public static Object getInstance(Class<?> pClazz,Class<?> pArgsClazzs,Object pArgs){
return getInstance(pClazz,new Class<?>[]{pArgsClazzs},new Object[]{pArgs});
}
/**
* 执行类指定参数的构造函数,并返回结果
* @param pClazz 类全名
* @param pArgsClazzs 参数类型
* @param pArgs 参数
*/
public static Object getInstance(Class<?> pClazz,Class<?>[] pArgsClazzs,Object[] pArgs){
try{
Constructor<?> tcons=null;
if(pArgsClazzs==null||pArgsClazzs.length==0) tcons=pClazz.getConstructor();
else tcons=pClazz.getConstructor(pArgsClazzs);
tcons.setAccessible(true);
return tcons.newInstance(pArgs);
}catch(NoSuchMethodException|SecurityException|InstantiationException|IllegalAccessException|IllegalArgumentException|InvocationTargetException e){
FBukkit.severe("使用参数"+pArgsClazzs+"实例化类"+pClazz+"时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 获取类
* @param pClazz 类全名
*/
public static Class<?> getClass(String pClazz){
try{
return Class.forName(pClazz);
}catch(ClassNotFoundException e){
FBukkit.severe("获取类"+pClazz+"时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 获取类指定名字的无参方法
* @param pClass 类
* @param pMethodName 方法名
*/
public static Method getMethod(Class<?> pClass,String pMethodName){
return getMethod(pClass,pMethodName,new Class<?>[]{});
}
/**
* 获取类指定名字的单参方法
* @param pClass 类
* @param pMethodName 方法名
* @param pArgClass 参数类型
*/
public static Method getMethod(Class<?> pClass,String pMethodName,Class<?> pArgClass){
return getMethod(pClass,pMethodName,new Class<?>[]{pArgClass});
}
/**
* 获取类指定名字的指定参数的方法
* @param pClass 类
* @param pMethodName 方法名
* @param pArgsClass 参数类型
*/
public static Method getMethod(Class<?> pClass,String pMethodName,Class<?>[] pArgsClazzs){
Method tMethod=null;
try{
if(pArgsClazzs==null||pArgsClazzs.length==0) tMethod=pClass.getDeclaredMethod(pMethodName);
else tMethod=pClass.getDeclaredMethod(pMethodName,pArgsClazzs);
return tMethod;
}catch(IllegalArgumentException|NoSuchMethodException|SecurityException e){
FBukkit.severe("获取"+pClass.getName()+"的类的方法: "+pMethodName+",[参数: "+pArgsClazzs+"] "+"时发生了错误",e);
throw new IllegalStateException(e);
}
}
/**
* 根据返回类型的短名字获取指定类的无参数方法
* @param pClass 类
* @param pReturnTypeSimpleName 类短名字
*/
public static ArrayList<Method> getUnknowMethod(Class<?> pClass,String pReturnTypeSimpleName){
return ClassHelper.getUnknowMethod(pClass,pReturnTypeSimpleName,new Class<?>[]{});
}
/**
* 根据返回类型的短名字获取指定类的单参数方法
* @param pClass 类
* @param pReturnTypeSimpleName 类短名字
* @param pArgClazz 参数类型
*/
public static ArrayList<Method> getUnknowMethod(Class<?> pClass,String pReturnTypeSimpleName,Class<?> pArgClazz){
return ClassHelper.getUnknowMethod(pClass,pReturnTypeSimpleName,new Class<?>[]{pArgClazz});
}
/**
* 根据返回类型的短名字和参数类型来获取自定类的多参数方法
* @param pClass 类
* @param pReturnTypeSimpleName 类短名字
* @param pArgsClazzs 参数类型
*/
public static ArrayList<Method> getUnknowMethod(Class<?> pClass,String pReturnTypeSimpleName,Class<?>[] pArgsClazzs){
if(pReturnTypeSimpleName==null||pReturnTypeSimpleName.equals("null")) pReturnTypeSimpleName=void.class.getSimpleName();
Method[] tMethods=pClass.getDeclaredMethods();
ArrayList<Method> findMethodes=new ArrayList<Method>();
for(Method sMethod : tMethods){
Class<?> tReturn=sMethod.getReturnType();
if(tReturn.getSimpleName().equals(pReturnTypeSimpleName)&&isSameClazzs(sMethod.getParameterTypes(),pArgsClazzs)) findMethodes.add(sMethod);
}
if(!findMethodes.isEmpty()) return findMethodes;
String tArgsStr="";
for(int i=0;i<pArgsClazzs.length;i++){
tArgsStr+=pArgsClazzs[i].getSimpleName()+",";
}
if(tArgsStr.length()>0) tArgsStr=tArgsStr.substring(0,tArgsStr.length()-1);
else tArgsStr="";
try{
throw new NoSuchMethodException("未发现类"+pClass.getName()+"返回类型名为: "+pReturnTypeSimpleName+",且参数为: "+tArgsStr+"的方法");
}catch(NoSuchMethodException e){
FBukkit.severe(e.getMessage(),e);
throw new IllegalStateException(e);
}
}
/**
* 根据返回类型来获取指定类的无参数方法
* @param pClass 类
* @param pReturnType 返回类型
* @param pArgClazz 参数类型
*/
public static ArrayList<Method> getUnknowMethod(Class<?> pClass,Class<?> pReturnType){
return getUnknowMethod(pClass,pReturnType,new Class<?>[]{});
}
/**
* 根据返回类型和单参数来获取指定类的单参数方法
* @param pClass 类
* @param pReturnType 返回类型
* @param pArgClazz 参数类型
*/
public static ArrayList<Method> getUnknowMethod(Class<?> pClass,Class<?> pReturnType,Class<?> pArgClazz){
return getUnknowMethod(pClass,pReturnType,new Class<?>[]{pArgClazz});
}
/**
* 根据返回类型和参数来获取指定类的多参数方法
* @param pClass 类
* @param pReturnType 返回类型
* @param pArgsClazzs 参数类型
*/
public static ArrayList<Method> getUnknowMethod(Class<?> pClass,Class<?> pReturnType,Class<?>[] pArgsClazzs){
Method[] tMethods=pClass.getDeclaredMethods();
ArrayList<Method> findMethodes=new ArrayList<Method>();
for(Method sMethod : tMethods){
Class<?> tReturn=sMethod.getReturnType();
if(isSameClazz(tReturn,pReturnType)&&isSameClazzs(sMethod.getParameterTypes(),pArgsClazzs)) findMethodes.add(sMethod);
}
if(!findMethodes.isEmpty()) return findMethodes;
String tArgsStr="";
for(int i=0;i<pArgsClazzs.length;i++){
tArgsStr+=pArgsClazzs[i].getSimpleName()+",";
}
if(tArgsStr.length()>0) tArgsStr=tArgsStr.substring(0,tArgsStr.length()-1);
else tArgsStr="";
try{
throw new NoSuchMethodException("未发现类"+pClass.getName()+"返回类型名为: "+pReturnType+",且参数为: "+tArgsStr+"的方法");
}catch(NoSuchMethodException e){
FBukkit.severe(e.getMessage(),e);
throw new IllegalStateException(e);
}
}
/**
* 根据返回类型和单参数来获取指定类的单参数方法
* @param pClass 类
* @param pReturnType 返回类型
* @param pArgClassShortName 参数类型
*/
public static ArrayList<Method> getUnknowMethod(Class<?> pClass,Class<?> pReturnType,String pArgClassShortName){
return getUnknowMethod(pClass,pReturnType,new String[]{pArgClassShortName});
}
/**
* 根据返回类型和参数来获取指定类的多参数方法
* @param pClass 类
* @param pReturnType 返回类型
* @param pArgsClassShortName 参数短类型名
*/
public static ArrayList<Method> getUnknowMethod(Class<?> pClass,Class<?> pReturnType,String[] pArgsClassShortName){
Method[] tMethods=pClass.getDeclaredMethods();
ArrayList<Method> findMethodes=new ArrayList<Method>();
for(Method sMethod : tMethods){
Class<?> tReturn=sMethod.getReturnType();
if(isSameClazz(tReturn,pReturnType)&&isSameClazzs(sMethod.getParameterTypes(),pArgsClassShortName)) findMethodes.add(sMethod);
}
if(!findMethodes.isEmpty()) return findMethodes;
String tArgsStr="";
for(int i=0;i<pArgsClassShortName.length;i++){
tArgsStr+=pArgsClassShortName[i]+",";
}
if(tArgsStr.length()>0) tArgsStr=tArgsStr.substring(0,tArgsStr.length()-1);
else tArgsStr="";
try{
throw new NoSuchMethodException("未发现类"+pClass.getName()+"返回类型名为: "+pReturnType+",且参数为: "+tArgsStr+"的方法");
}catch(NoSuchMethodException e){
FBukkit.severe(e.getMessage(),e);
throw new IllegalStateException(e);
}
}
/**
* 比较两个类数组是不是包含切顺序相同的类
*/
private static boolean isSameClazzs(Class<?>[] pClazzs1,Class<?>[] pClazzs2){
if(pClazzs1==pClazzs2) return true;
if((pClazzs1==null&&pClazzs2.length==0)||(pClazzs1.length==0&&pClazzs2==null)) return true;
if(pClazzs1==null||pClazzs2==null) return false;
if(pClazzs1.length!=pClazzs2.length) return false;
for(int i=0;i<pClazzs1.length;i++){
if(pClazzs1[i]!=pClazzs2[i]) return false;
}
return true;
}
/**
* 比较两个类数组是不是包含切顺序相同的类
*/
private static boolean isSameClazzs(Class<?>[] pClazzs1,String[] pClazzsShortName){
if(pClazzs1==null&&pClazzsShortName==null) return true;
if((pClazzs1==null&&pClazzsShortName.length==0)||(pClazzs1.length==0&&pClazzsShortName==null)) return true;
if(pClazzs1.length!=pClazzsShortName.length) return false;
for(int i=0;i<pClazzs1.length;i++){
if(!pClazzs1[i].getSimpleName().equals(pClazzsShortName[i])) return false;
}
return true;
}
/**
* 比较两个类是不是包含切顺序相同的类
*/
private static boolean isSameClazz(Class<?> pClazz1,Class<?> pClazz2){
if(pClazz1==pClazz2) return true;
if((pClazz1==void.class&&pClazz2==null)||(pClazz1==null&&pClazz2==void.class)) return true;
return false;
}
/**
* 打印一个类所有的方法
* @param pClass 类
*/
public static void printfMethod(Class<?> pClass){
Method[] tMethods=pClass.getDeclaredMethods();
for(Method sMethod : tMethods){
System.out.println(sMethod);
}
}
}

View File

@@ -0,0 +1,133 @@
package cc.util.bossshop;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.inventory.meta.ItemMeta;
public class FBukkit{
private static String mPrefix="&c[CCLogger]";
public static Player[] getOnlinePlayers(){
Method tMethod=null;
try{
tMethod=Bukkit.class.getDeclaredMethod("getOnlinePlayers");
Object tObject=tMethod.invoke(null);
Player[] tPlayers=null;
if(tObject instanceof Player[]) tPlayers=(Player[])tObject;
else{
Collection<Player> tcPlayers=(Collection<Player>)tObject;
tPlayers=new Player[tcPlayers.size()];
tcPlayers.toArray(tPlayers);
}
return tPlayers;
}catch(Throwable exp){
FBukkit.severe("获取在线玩家列表时发生了错误",exp);
return new Player[0];
}
}
public static ArrayList<String> getOnlinePlayersName(){
ArrayList<String> playerNames=new ArrayList<>();
for(Player sPlayer : FBukkit.getOnlinePlayers())
playerNames.add(sPlayer.getName());
return playerNames;
}
public static OfflinePlayer[] getOfflinePlayers(){
Method tMethod=null;
try{
tMethod=Bukkit.class.getDeclaredMethod("getOfflinePlayers");
Object tObject=tMethod.invoke(null);
OfflinePlayer[] tPlayers=null;
if(tObject instanceof OfflinePlayer[]) tPlayers=(OfflinePlayer[])tObject;
else{
Collection<OfflinePlayer> tcPlayers=(Collection<OfflinePlayer>)tObject;
tPlayers=new OfflinePlayer[tcPlayers.size()];
tcPlayers.toArray(tPlayers);
}
return tPlayers;
}catch(Throwable exp){
FBukkit.severe("获取离线玩家列表时发生了错误",exp);
return new OfflinePlayer[0];
}
}
public static ArrayList<String> getOfflinePlayersName(){
ArrayList<String> playerNames=new ArrayList<>();
for(OfflinePlayer sPlayer : FBukkit.getOfflinePlayers())
playerNames.add(sPlayer.getName());
return playerNames;
}
public static boolean isItemMetaEmpty(ItemMeta pMeat){
Boolean result=(Boolean)ClassHelper.invokeMethod(pMeat,"isEmpty");
if(result==null||result) return true;
return false;
}
/**
* 设置ClassHelper类日志输出前缀
*/
private static void setLogPrefix(String pPrefix){
if(StringUtils.isNotEmpty(pPrefix))
FBukkit.mPrefix=pPrefix;
}
/**
* 在发生异常时用于输出调试信息,或输出警告信息到控制台
* @param pMsg 错误的提示消息
*/
public static void severe(String pMsg){
FBukkit.log(mPrefix+"&c[ERROR]",pMsg);
}
/**
* 输出信息到控制台
* @param pMsg 提示消息
*/
public static void log(String pPrefix,String pMsg){
if(StringUtils.isEmpty(pMsg)) return;
if(StringUtils.isEmpty(pPrefix))
pPrefix=FBukkit.mPrefix;
String sendMessage=ChatColor.translateAlternateColorCodes('&',pPrefix+" "+pMsg);
if(Bukkit.getServer()!=null){
Bukkit.getConsoleSender().sendMessage(sendMessage);
}else Logger.getLogger("minecraft").log(Level.SEVERE,sendMessage);
}
/**
* 在发生异常时用于输出调试信息,或输出警告信息到控制台
* @param msg 错误的提示消息
* @param thrown 要抛出的异常
*/
public static void severe(String msg,Throwable thrown){
FBukkit.severe(mPrefix+"&c[ERROR]",msg,thrown);
}
/**
* 输出调试信息
* @param pPrefix 消息前缀
* @param msg 错误的提示消息
* @param thrown 要抛出的异常
*/
public static void severe(String pPrefix,String msg,Throwable thrown){
if(Bukkit.getServer()!=null){
FBukkit.log(pPrefix,msg);
String[] lines= org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(thrown).split("(\r?\n)+");
for(String sLine : lines)
FBukkit.log(pPrefix,sLine);
}else Logger.getLogger("minecraft").log(Level.SEVERE,pPrefix+msg,thrown);
}
}

View File

@@ -0,0 +1,102 @@
package cc.util.bossshop;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class Function{
/**
* 获取忽略大小写的指定前缀的字符串
* <p>如果指定的前缀为空时将返回全部的目标</p>
* @param pStrs 搜索目标,不能为null
* @param pPrefix 指定的前缀,不能为null
* @param pIgnoreSame 是否忽略相同的字符串
*/
public static Collection<String> getSamePrefixIgnoreCase(Collection<String> pStrs,String pPrefix,boolean pIgnoreSame){
return Function.getSamePrefix(pStrs,pPrefix,true,pIgnoreSame);
}
/**
* 获取指定前缀的字符串<br />
* 相同的字符串不作为拥有该前缀
* <p>如果指定的前缀为空时将返回全部的目标</p>
* @param pStrs 搜索目标,不能为null
* @param pPrefix 指定的前缀,不能为null
* @param pIgnoreCase 是否忽略大小写
* @param pIgnoreSame 是否忽略相同的字符串
*/
public static Collection<String> getSamePrefix(Collection<String> pStrs,String pPrefix,boolean pIgnoreCase,boolean pIgnoreSame){
ArrayList<String> same=new ArrayList<>();
if(pStrs==null||pStrs.isEmpty()) return same;
if(pPrefix==null||pPrefix.isEmpty()) return pStrs;
if(pIgnoreCase){
pPrefix=pPrefix.toLowerCase();
for(String sStr : pStrs){
if(sStr==null) continue;
String lowsStr=sStr.toLowerCase();
if(lowsStr.startsWith(pPrefix)&&(!pIgnoreSame||lowsStr.length()!=pPrefix.length()))
same.add(sStr);
}
}else{
for(String sStr : pStrs){
if(sStr==null) continue;
if(sStr.startsWith(pPrefix)&&(!pIgnoreSame||sStr.length()!=pPrefix.length()))
same.add(sStr);
}
}
return same;
}
/**
* 指定位置是否存在忽略大小的指定字符串
* @param pStrs 目标位置,不能为null
* @param pTarget 要查找的字符串,可以为null
* @return 是否存在
*/
public static boolean containsIgnoreCase(Collection<String> pStrs,String pTarget){
if(pStrs==null) return false;
if(pTarget==null) return pStrs.contains(pTarget);
return Function.getIgnoreCase(pStrs,pTarget)!=null;
}
/**
* 获取忽略大小的指定字符串
* @param pStrs 目标位置,不能为null
* @param pTarget 要查找的字符串,不能为null
* @return 查找到的字符串或者null
*/
public static String getIgnoreCase(Collection<String> pStrs,String pTarget){
if(pStrs==null||pStrs.isEmpty()) return null;
if(pTarget==null) return null;
for(String sStr : pStrs)
if(sStr!=null&&sStr.equalsIgnoreCase(pTarget))
return sStr;
return null;
}
/**
* 打印当前位置的堆栈
*/
public static void printStackTrace(){
StackTraceElement[] elements=Thread.currentThread().getStackTrace();
for(StackTraceElement sElement : elements){
System.out.println(sElement.toString());
}
}
/**
* 将数组转化成List
* @param pArrays 要转换的数组,如果数组为null,将返回空List
* @return 转换后的List,非null
*/
public static <T> List<T> asList(T[] pArrays){
ArrayList<T> newList=new ArrayList<>();
if(pArrays==null||pArrays.length==0) return newList;
for(T t : pArrays)
newList.add(t);
return newList;
}
}

View File

@@ -0,0 +1,351 @@
package cc.util.bossshop;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
public class JsonExtra{
public enum HoverAction{
show_text,show_item,show_achievement
}
public enum ClickAction{
run_command,suggest_command,open_url
}
public enum Color{
black('0'),
dark_aqua('3'),
dark_blue('1'),
dark_gray('8'),
dark_green('2'),
dark_purple('5'),
dark_red('4'),
aqua('b'),
blue('9'),
gold('6'),
gray('7'),
green('a'),
light_purple('d'),
red('c'),
white('f'),
yellow('e');
public static final char COLOR_CHAR='§';
private final char code;
private final String toString;
private Color(char pChar){
this.code=pChar;
this.toString=new String(new char[]{'§',code});
}
@Override
public String toString(){
return this.toString;
}
public static boolean isColor(char c){
return Color.getColor(c)!=null;
}
public static Color getColor(char c){
c=(char)((c&0xDF)+32);
for(Color sColor : Color.values())
if(sColor.code==c) return sColor;
return null;
}
}
public enum Style{
magic('k',null),
bold('l',"bold"),
strikethrough('m',"obfuscated"),
underline('n',"underlined"),
italic('o',"italic"),
reset('r',null);
public static final char FORMAT_CHAR='§';
private final char code;
private final String mLabel;
private final String toString;
private Style(char pChar,String pLabel){
this.code=pChar;
this.mLabel=pLabel;
this.toString=new String(new char[]{'§',code});
}
@Override
public String toString(){
return this.toString;
}
public static boolean isStyle(char c){
return Style.getStyle(c)!=null;
}
public static Style getStyle(char c){
c=(char)((c&0xDF)+32);
for(Style sStyle : Style.values())
if(sStyle.code==c) return sStyle;
return null;
}
/**
* 如果为null代表这个是不是Json使用的节点
*/
public String getJsonLabel(){
return this.mLabel;
}
}
private String mText="";
private Color mTextColor=null;
private JSONObject mHoverEvent=null;
private JSONObject mClickEvent=null;
private boolean mInherit=true;
private static Pattern COLOR_FORMAT=Pattern.compile("§([0123456789AaBbCcDdEeFfKkLlMmNnOoRr])");
private ArrayList<JsonExtra> mExtras=new ArrayList<>();
/**未设置的值的格式默认继承,true或false代表是否启用,不允许put null*/
private HashMap<Style,Boolean> mStyles=new HashMap<>();
public JsonExtra(){
this.mText="";
}
public JsonExtra(String pText){
this.setText(pText);
}
public JsonExtra(String pText,Color pTextColor){
this.setText(pText);
this.setTextColor(pTextColor);
}
/**设置文字*/
public void setText(String pText){
if(pText==null) this.mText="";
pText=ChatColor.translateAlternateColorCodes('&',pText);
Color tcolor=this.mTextColor;
ArrayList<JsonExtra> tChildExtrs=new ArrayList<>();
HashMap<Style,Boolean> tStyles=new HashMap<>();
tStyles.putAll(this.mStyles);
Matcher matcher=COLOR_FORMAT.matcher(pText);
int pos=0;
while(matcher.find()){
char cf=matcher.group(1).charAt(0);
if(matcher.start()!=pos){
JsonExtra te=new JsonExtra();
te.mText=pText.substring(pos,matcher.start());
te.mTextColor=tcolor;
te.mStyles.putAll(tStyles);
te.mInherit=false;
tChildExtrs.add(te);
}
if(Color.isColor(cf)){
tcolor=Color.getColor(cf);
tStyles.clear();
}else if(Style.isStyle(cf)){
if(cf=='r'){
tcolor=null;
tStyles.clear();
}else tStyles.put(Style.getStyle(cf),true);
}
pos=matcher.end();
}
JsonExtra te=new JsonExtra();
te.mText=pText.substring(pos,pText.length());
te.mTextColor=tcolor;
te.mStyles.putAll(tStyles);
te.mInherit=false;
tChildExtrs.add(te);
JsonExtra headExtra=tChildExtrs.remove(0);
this.mText=headExtra.mText;
this.mTextColor=headExtra.mTextColor;
this.mStyles.clear();
this.mStyles.putAll(headExtra.mStyles);
this.mExtras.addAll(0,tChildExtrs);
}
/**设置文字颜色*/
public void setTextColor(Color pTextColor){
if(pTextColor==null) return;
this.mTextColor=pTextColor;
}
/**
* 设置字体样式
*/
public void setStyle(Style...pStyles){
if(pStyles==null) return;
for(Style sStyle : pStyles)
this.mStyles.put(sStyle,true);
}
/**
* 移除字体样式
*/
public void removeStyle(Style...pStyles){
if(pStyles==null) return;
for(Style sStyle : pStyles)
this.mStyles.remove(sStyle);
}
/**
* 清除所有格式
*/
public void clearStyle(){
this.mStyles.clear();
}
/**
* 将所有样式设置为false
*/
public void resetStyle(){
for(Style sStyle : Style.values())
this.mStyles.put(sStyle,false);
this.mStyles.put(Style.reset,true);
}
/**
* 设置是否继承父级的样式
*/
public void setInherit(boolean pInherit){
this.mInherit=pInherit;
}
/**
* 是否继承父级的样式
*/
public boolean isInherit(){
return this.mInherit;
}
/**
* 设置文字点击事件要执行的动作
* @param pAction 动作类型
* @param pValue 值
*/
public void setClickEvent(ClickAction pAction,String pValue){
if(pAction==null||StringUtils.isEmpty(pValue)) return;
this.mClickEvent=new JSONObject();
this.mClickEvent.put("action",pAction.name());
this.mClickEvent.put("value",pValue);
}
/**
* 设置文件在鼠标悬浮式要执行的动作
* @param pAction 动作
* @param pValue 值
*/
public void setHoverEvent(HoverAction pAction,String pValue){
if(pAction==null||StringUtils.isEmpty(pValue)) return;
this.mHoverEvent=new JSONObject();
this.mHoverEvent.put("action",pAction.name());
this.mHoverEvent.put("value",pValue);
}
private JSONObject getJson(){
JSONObject tJson=new JSONObject();
tJson.put("text",this.mText);
for(Style sStyle :Style.values()){
if(sStyle.getJsonLabel()==null) continue;
Boolean hasSet=this.mStyles.get(sStyle);
if(hasSet==null){
if(!this.mInherit) tJson.put(sStyle.getJsonLabel(),false);
}else{
tJson.put(sStyle.getJsonLabel(),hasSet.booleanValue());
}
}
if(this.mTextColor!=null) tJson.put("color",this.mTextColor.name());
if(this.mClickEvent!=null) tJson.put("clickEvent",this.mClickEvent);
if(this.mHoverEvent!=null) tJson.put("hoverEvent",this.mHoverEvent);
if(!this.mExtras.isEmpty()){
JSONArray tJsonArray=new JSONArray();
for(JsonExtra sExtra : this.mExtras){
tJsonArray.add(sExtra.getJson());
}
tJson.put("extra",tJsonArray);
}
return tJson;
}
@Override
public String toString(){
return this.getJson().toJSONString();
}
@Override
public JsonExtra clone(){
JsonExtra clone=new JsonExtra(this.mText,this.mTextColor);
JSONObject jsonObject=null;
if(this.mClickEvent!=null){
jsonObject=new JSONObject();
jsonObject.putAll((Map<?,?>)this.mClickEvent.clone());
clone.mClickEvent=jsonObject;
}
if(this.mHoverEvent!=null){
jsonObject=new JSONObject();
jsonObject.putAll((Map<?,?>)this.mHoverEvent.clone());
clone.mHoverEvent=jsonObject;
}
clone.mInherit=this.mInherit;
clone.mStyles.putAll(this.mStyles);
for(JsonExtra childExtra : this.mExtras){
clone.mExtras.add(childExtra.clone());
}
return clone;
}
public String toSimpleString(){
StringBuilder tStr=new StringBuilder();
if(this.mTextColor!=null) tStr.append(this.mTextColor.toString());
for(Entry<Style,Boolean> entry : this.mStyles.entrySet())
if(entry.getValue()) tStr.append(entry.getKey().toString());
tStr.append(this.mText);
for(JsonExtra sExtra : this.mExtras)
tStr.append(sExtra.toSimpleString());
return tStr.toString();
}
public void addExtra(JsonExtra pExtra){
if(pExtra==null) return;
this.mExtras.add(pExtra);
}
public void addNormalWords(String pWords,boolean pInherit){
if(StringUtils.isEmpty(pWords)) return;
JsonExtra tExtra=new JsonExtra(pWords,Color.white);
if(!pInherit)
tExtra.mInherit=false;
this.addExtra(tExtra);
}
/**
* 将Json消息发送给玩家<br />
* 如果CommandSender不是玩家,将只发送非Json的消息串
*/
public void sendToPlayer(CommandSender pSender){
if(pSender instanceof Player){
Bukkit.dispatchCommand(Bukkit.getConsoleSender(),"tellraw "+((Player)pSender).getName()+" "+this.toString());
}else pSender.sendMessage(this.toSimpleString());
//System.out.println(this.toString());
}
}

View File

@@ -0,0 +1,131 @@
package cc.util.bossshop;
import java.lang.reflect.Method;
import java.util.ArrayList;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import cc.util.bossshop.pluginmodel.ABukkitPlugin;
public class LocalLanguage{
public static final Method method_NMSItemStack_getName;
public static final Method method_NMSItemStack_getUnlocalizedName;
protected final static boolean isFML;
private static Object instance_LanguageRegistry;
private static Method method_LanguageRegistry_getStringLocalization;
protected ABukkitPlugin mPlugin;
static{
//NMS ItemStck
ItemStack tItem=new ItemStack(Material.STONE);
Object tNMSItemStack_mcitem=ClassHelper.invokeStaticMethod(NMSHelper.method_CraftItemStack_asNMSCopy,tItem);
//NMS ItemStack getName
Object tObj_NBTTagCompound=ClassHelper.getInstance(NMSHelper.clazz_NBTTagCompound);
Object tNBTTagCompound_displaye=ClassHelper.getInstance(NMSHelper.clazz_NBTTagCompound);
String displayName="1234567890",unlocalStoneName="tile.stone";
Object tNBTTagString_name=ClassHelper.getInstance(NMSHelper.clazz_NBTTagString,String.class,displayName);
ClassHelper.invokeMethod(tNBTTagCompound_displaye,NMSHelper.method_NBTTagCompound_set,new Object[]{"Name",tNBTTagString_name});
ClassHelper.invokeMethod(tObj_NBTTagCompound,NMSHelper.method_NBTTagCompound_set,new Object[]{"display",tNBTTagCompound_displaye});
ClassHelper.setFieldValue(tNMSItemStack_mcitem,NMSHelper.field_NMSItemStack_tag,tObj_NBTTagCompound);
ArrayList<Method> mayGetNameMethods=ClassHelper.getUnknowMethod(NMSHelper.clazz_NMSItemStack,String.class);
int getNamePos=-1,getUnlocalNamePos=-1;
for(int i=0;i<mayGetNameMethods.size();i++){
String getStr=(String)ClassHelper.invokeMethod(tNMSItemStack_mcitem,mayGetNameMethods.get(i));
//FBukkit.log("NMSItemStack方法返回值: "+getStr);
if(getStr.equals(displayName)) getNamePos=i;
if(getStr.startsWith(unlocalStoneName)) getUnlocalNamePos=i;
}
method_NMSItemStack_getName=mayGetNameMethods.get(getNamePos);
method_NMSItemStack_getUnlocalizedName=mayGetNameMethods.get(getUnlocalNamePos);
//NMS ItemStack getName-end
isFML=ClassHelper.isClassLoaded("cpw.mods.fml.common.registry.LanguageRegistry");
if(isFML){
Class<?> cpwlang=ClassHelper.getClass("cpw.mods.fml.common.registry.LanguageRegistry");
instance_LanguageRegistry=ClassHelper.invokeStaticMethod(cpwlang,"instace");
method_LanguageRegistry_getStringLocalization=ClassHelper.getMethod(cpwlang,"getStringLocalization");
}
}
protected LocalLanguage(ABukkitPlugin pPlugin){
this.mPlugin=pPlugin;
}
/**
* 物品在Lore中是否设置过名字
*/
public boolean hasSetName(ItemStack pItem){
if(pItem==null) return false;
if(pItem.getItemMeta()==null) return false;
return pItem.getItemMeta().hasDisplayName();
}
/**
* 获取由物品ID格式化后的名字
* <p>
* 例如"MINECRAFT_DIRT"将会格式化未"Minecratf Dirt"
* </p>
*/
public String getIDFormatName(ItemStack pItem){
if(pItem==null) return "";
char[] tID=pItem.getType().name().toLowerCase().replace("_"," ").toCharArray();
tID[0]=(char)(tID[0]&(0xDF));
for(int i=0;i<tID.length;i++){
if(tID[i]==' '&&i<tID.length-1){
if(tID[i+1]<'a'||tID[i+1]>'z') continue;
tID[i+1]=(char)(tID[i+1]&(0xDF));
i++;
}
}
return new String(tID);
}
/**
* 获取指定物品指定语言的翻译
* <p>
* 如果物品本身存在显示名字,将返回该名字
* 如果指定的语言不存在,将返回英文
* 如果指定的物品不在翻译列表,将返回物品材料名字
* </p>
* @param pItem 指定的物品
* @param pLang 指定的语言
* @return 物品显示名字
*/
public String getDisplayName(ItemStack pItem,String pLang){
if(pItem==null) return "";
if(this.hasSetName(pItem)) return pItem.getItemMeta().getDisplayName();
String nowName=null;
if(isFML){
String unlocalName=this.getUnlocalizedName(pItem);
nowName=this.getStringLocalization(this.getUnlocalizedName(pItem),pLang);
if(StringUtils.isNotEmpty(nowName)) return nowName;
nowName=this.getStringLocalization(unlocalName+".name",pLang);
if(StringUtils.isNotEmpty(nowName)) return nowName;
}
Object NMSItemStack=ClassHelper.invokeStaticMethod(NMSHelper.method_CraftItemStack_asNMSCopy,pItem);
if(NMSItemStack==null) return this.getIDFormatName(pItem);
return (String)ClassHelper.invokeMethod(NMSItemStack,method_NMSItemStack_getName);
}
/**
* 获取NMS物品未本地化时的语言key
* @param pItemStack 物品
* @return 物品语言key
*/
public String getUnlocalizedName(ItemStack pItemStack){
if(pItemStack==null) return "";
Object NMSItemStack=ClassHelper.invokeStaticMethod(NMSHelper.method_CraftItemStack_asNMSCopy,pItemStack);
if(NMSItemStack==null) return "";
return (String)ClassHelper.invokeMethod(NMSItemStack,method_NMSItemStack_getUnlocalizedName);
}
private String getStringLocalization(String pKey,String pLang){
return (String)ClassHelper.invokeMethod(instance_LanguageRegistry,method_LanguageRegistry_getStringLocalization,new Object[]{pKey,pLang});
}
}

View File

@@ -0,0 +1,254 @@
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<String> getNBTFirstDeepNodeList(ItemStack pItem){
Object nbtTag=getNBTTagCompound(pItem);
if(nbtTag==null) return null;
Map<String,Object> tMap=getNBTTagMapFromTag(nbtTag);
Set<String> 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<String,Object> 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<String,Object> getNBTTagMapFromTag(Object pNBTTagCompound){
if(pNBTTagCompound==null) return new HashMap<>();
return (Map<String,Object>)ClassHelper.getFieldValue(pNBTTagCompound,field_NBTTagCompound_map);
}
/**
* 从NBTTagCompound实例中移除指定的标签
* @param pNBTTagCompound NBTTagCompound实例
* @param pNBTLabel NBT标签
* @return 移除的值或null
*/
public static Object removeFromNBTTagCompound(Object pNBTTagCompound,String pNBTLabel){
Map<String,Object> 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值
* <p>
* 只对NBTTagString的toString方法重写<br />
* 其他方法不变
* </p>
* @param pNBTBase
* @return json字符串
*/
public static String getNBTBaseValue(Object pNBTBase){
if(pNBTBase==null) return "";
if(NMSHelper.clazz_NBTTagCompound.isInstance(pNBTBase)){
Map<String,Object> tNBTContents=(Map<String,Object>)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<Object> tNBTContents=(List<Object>)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();
}
}

View File

@@ -0,0 +1,96 @@
package cc.util.bossshop.config;
import java.util.Map;
import org.apache.commons.lang.Validate;
import org.bukkit.configuration.Configuration;
/**
*
* 支持注释的配置管理器
*
*/
public class CommentedConfiguration extends CommentedSection implements Configuration{
protected CommentedConfiguration mDefaults;
protected CommentedOptions mOptions;
public CommentedConfiguration(){}
/**
* 为节点添加一个默认值,如果值不存在,将会直接设置到配置其中
*/
@Override
public void addDefault(String pPath,Object pValue){
Validate.notNull(pPath,"Path may not be null");
if(mDefaults==null){
mDefaults=new CommentedConfiguration();
}
if(!this.contains(pPath)) this.set(pPath,pValue);
else mDefaults.set(pPath,pValue);
}
public void addDefault(String pPath,Object pValue,String...pComments){
this.addDefault(pPath,pValue);
this.addDefaultComments(pPath,pComments);
}
@Override
public void addDefaults(Map<String,Object> pDefaults){
Validate.notNull(pDefaults,"默认配置不能为空");
for(Map.Entry<String,Object> entry : pDefaults.entrySet()){
this.addDefault(entry.getKey(),entry.getValue());
}
}
@Override
public void addDefaults(Configuration pDefaults){
Validate.notNull(pDefaults,"默认配置不能为空");
this.addDefaults(pDefaults.getValues(true));
}
@Override
public void setDefaults(Configuration pDefaults){
if(pDefaults instanceof CommentedConfiguration){
this.mDefaults=(CommentedConfiguration)pDefaults;
}else{
this.addDefaults(pDefaults.getValues(true));
}
}
@Override
public CommentedConfiguration getDefaults(){
return this.mDefaults;
}
@Override
public CommentedSection getParent(){
return null;
}
@Override
public CommentedOptions options(){
if(mOptions==null){
mOptions=new CommentedOptions(this);
}
return mOptions;
}
/**
* 设置输入路径的分割用字符,默认为"."
* @param value 作为分割路径用的字符
*/
public void pathSeparator(char value){
this.options().pathSeparator(value);
}
/**
* 获取路径分割用字符
* @return 分割路径用的字符
*/
public char pathSeparator(){
return this.options().pathSeparator();
}
}

View File

@@ -0,0 +1,17 @@
package cc.util.bossshop.config;
import org.bukkit.configuration.ConfigurationOptions;
public class CommentedOptions extends ConfigurationOptions{
protected CommentedOptions(CommentedConfiguration configuration){
super(configuration);
}
public String getPathSeparatorRegx(){
char split=this.pathSeparator();
return "(?<!\\"+split+")[\\"+split+"]+(?!\\"+split+")";
}
}

View File

@@ -0,0 +1,835 @@
package cc.util.bossshop.config;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.Validate;
import org.bukkit.Color;
import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.Configuration;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.NumberConversions;
import org.bukkit.util.Vector;
import cc.util.bossshop.Function;
/**
* 支持注释的节点
* @author 聪聪
*
*/
public class CommentedSection implements ConfigurationSection,ICommentedSection{
/**值存放处,类型只能是{@link CommentedValue}*/
protected final Map<String,CommentedValue> map=new LinkedHashMap<>();
private final CommentedConfiguration root;
private final CommentedSection parent;
private final String path;
private final String fullPath;
protected CommentedSection(){
if(!(this instanceof CommentedConfiguration)) throw new IllegalStateException("Cannot construct a root MemorySection when not a Configuration");
this.path="";
this.fullPath="";
this.parent=null;
this.root=(CommentedConfiguration)this;
}
protected CommentedSection(CommentedSection parent,String path){
Validate.notNull(parent,"父节点不能为null");
Validate.notNull(path,"路径不能为null");
this.path=path;
this.parent=parent;
this.root=parent.getRoot();
Validate.notNull(path,"父节点的根节点不能为空");
this.fullPath=createPath(parent,path);
}
@Override
public Set<String> getKeys(boolean deep){
Set<String> result=new LinkedHashSet<String>();
Configuration root=getRoot();
if(root!=null&&root.options().copyDefaults()){
ConfigurationSection defaults=getDefaultSection();
if(defaults!=null){
result.addAll(defaults.getKeys(deep));
}
}
mapChildrenKeys(result,this,deep);
return result;
}
@Override
public Map<String,Object> getValues(boolean deep){
Map<String,Object> result=new LinkedHashMap<String,Object>();
CommentedConfiguration root=getRoot();
if(root!=null&&root.options().copyDefaults()){
ConfigurationSection defaults=getDefaultSection();
if(defaults!=null){
result.putAll(defaults.getValues(deep));
}
}
this.mapChildrenValues(result,this,deep);
return result;
}
@Override
public boolean contains(String path){
return this.get(path)!=null;
}
@Override
public boolean isSet(String path){
return true;
}
public String getCurrentPath(){
return this.fullPath;
}
public String getName(){
return this.path;
}
@Override
public CommentedConfiguration getRoot(){
return this.root;
}
@Override
public CommentedSection getParent(){
return this.parent;
}
@Override
public Object get(String pPath){
Validate.notNull(pPath,"获取值的路径不能为null");
String separator=root.options().getPathSeparatorRegx();
String[] childPathes=pPath.split(separator);
if(childPathes.length==0) return this;
CommentedSection section=this;
for(int i=0;i<childPathes.length-1;i++){
String sChildPath=childPathes[i];
section=section.getConfigurationSection(sChildPath);
if(section==null) return null;
}
String key=childPathes[childPathes.length-1];
CommentedValue result=section.map.get(key);
if(result==null){
return null;
}else{
return result.getValue();
}
}
@Override
public Object get(String pPath,Object pDefaultValue){
Object value=this.get(pPath);
if(value==null) return pDefaultValue;
else return value;
}
public CommentedValue getCommentedValue(String pPath){
Validate.notEmpty(pPath,"获取包装值的路径不能为empty");
String separator=root.options().getPathSeparatorRegx();
String[] childPathes=pPath.split(separator);
Validate.notEmpty(childPathes,"获取包装值的路径不能为empty");
CommentedSection section=this;
for(int i=0;i<childPathes.length-1;i++){
String sChildPath=childPathes[i];
section=section.getConfigurationSection(sChildPath);
if(section==null) return null;
}
String key=childPathes[childPathes.length-1];
return section.map.get(key);
}
public CommentedValue removeCommentedValue(String pPath){
Validate.notEmpty(pPath,"移除包装值的路径不能为empty");
String separator=root.options().getPathSeparatorRegx();
String[] childPathes=pPath.split(separator);
Validate.notEmpty(childPathes,"移除包装值的路径不能为empty");
CommentedSection section=this;
for(int i=0;i<childPathes.length-1;i++){
String sChildPath=childPathes[i];
section=section.getConfigurationSection(sChildPath);
if(section==null) return null;
}
String key=childPathes[childPathes.length-1];
return section.map.remove(key);
}
/**
* 会对值进行包装与转换
* @param pPath
* @param pValue
*/
@Override
public void set(String pPath,Object pValue){
Validate.notEmpty(pPath,"设置值的路径不能为empty ");
String separator=root.options().getPathSeparatorRegx();
String[] childPathes=pPath.split(separator);
Validate.notEmpty(childPathes,"设置值的路径不能为empty ");
CommentedSection section=this,subSection;
for(int i=0;i<childPathes.length-1;i++){
String sChildPath=childPathes[i];
subSection=section.getConfigurationSection(sChildPath);
if(subSection==null){
section=section.createSection(sChildPath);
}else section=subSection;
}
String key=childPathes[childPathes.length-1];
if(pValue==null) section.map.remove(key);
else{
// 为了保留注释,不能直接put
CommentedValue cmtedValue=section.map.get(key);
if(cmtedValue!=null) cmtedValue.setValue(section,pValue);
else section.map.put(key,CommentedValue.wrapperValue(section,pValue));
}
}
@Override
public CommentedSection createSection(String pPath){
Validate.notEmpty(pPath,"不能在empty路径上创建节点");
String separator=root.options().getPathSeparatorRegx();
String[] childPathes=pPath.split(separator);
Validate.notEmpty(childPathes,"不能在empty路径上创建节点");
CommentedSection section=this,subSection;
for(int i=0;i<childPathes.length-1;i++){
String sChildPath=childPathes[i];
subSection=section.getConfigurationSection(sChildPath);
if(subSection==null){
section=section.createSection(sChildPath);
}else section=subSection;
}
String key=childPathes[childPathes.length-1];
CommentedSection putSec=new CommentedSection(section,key);
// 为了保留注释,不能直接put
CommentedValue cmtedValue=this.map.get(key);
if(cmtedValue!=null){
cmtedValue.clearComments();
cmtedValue.setValue(section,putSec);
}else section.map.put(key,CommentedValue.wrapperValue(section,putSec));
return putSec;
}
@Override
public CommentedSection createSection(String pPath,Map<?,?> pMapContents){
CommentedSection section=this.createSection(pPath);
for(Map.Entry<?,?> entry : pMapContents.entrySet()){
if(entry.getValue() instanceof Map){
section.createSection(entry.getKey().toString(),(Map<?,?>)entry.getValue());
}else{
section.set(entry.getKey().toString(),entry.getValue());
}
}
return section;
}
@Override
public String getString(String path){
Object def=this.getDefault(path);
return getString(path,def!=null?def.toString():null);
}
@Override
public String getString(String path,String def){
Object val=this.get(path,def);
return (val!=null)?val.toString():def;
}
@Override
public boolean isString(String path){
Object val=this.get(path);
return val instanceof String;
}
public int getInt(String path){
Object def=getDefault(path);
return getInt(path,(def instanceof Number)?NumberConversions.toInt(def):0);
}
public int getInt(String path,int def){
Object val=get(path,def);
return (val instanceof Number)?NumberConversions.toInt(val):def;
}
public boolean isInt(String path){
Object val=get(path);
return val instanceof Integer;
}
public boolean getBoolean(String path){
Object def=getDefault(path);
return getBoolean(path,(def instanceof Boolean)?(Boolean)def:false);
}
public boolean getBoolean(String path,boolean def){
Object val=get(path,def);
return (val instanceof Boolean)?(Boolean)val:def;
}
public boolean isBoolean(String path){
Object val=get(path);
return val instanceof Boolean;
}
public double getDouble(String path){
Object def=getDefault(path);
return getDouble(path,(def instanceof Number)?NumberConversions.toDouble(def):0);
}
public double getDouble(String path,double def){
Object val=get(path,def);
return (val instanceof Number)?NumberConversions.toDouble(val):def;
}
public boolean isDouble(String path){
Object val=get(path);
return val instanceof Double;
}
public long getLong(String path){
Object def=getDefault(path);
return getLong(path,(def instanceof Number)?NumberConversions.toLong(def):0);
}
public long getLong(String path,long def){
Object val=get(path,def);
return (val instanceof Number)?NumberConversions.toLong(val):def;
}
public boolean isLong(String path){
Object val=get(path);
return val instanceof Long;
}
// Java
public List<?> getList(String path){
Object def=getDefault(path);
return getList(path,(def instanceof List)?(List<?>)def:null);
}
public List<?> getList(String path,List<?> def){
Object val=get(path,def);
return (List<?>)((val instanceof List)?val:def);
}
public List<Map<?,?>> getMapList(String path){
List<?> list=getList(path);
List<Map<?,?>> result=new ArrayList<Map<?,?>>();
if(list==null){
return result;
}
for(Object object : list){
if(object instanceof Map){
result.add((Map<?,?>)object);
}
}
return result;
}
public boolean isList(String path){
Object val=get(path);
return val instanceof List;
}
public List<String> getStringList(String path){
List<?> list=getList(path);
if(list==null){
return new ArrayList<String>(0);
}
List<String> result=new ArrayList<String>();
for(Object object : list){
if((object instanceof String)||(isPrimitiveWrapper(object))){
result.add(String.valueOf(object));
}
}
return result;
}
public List<Integer> getIntegerList(String path){
List<?> list=getList(path);
if(list==null){
return new ArrayList<Integer>(0);
}
List<Integer> result=new ArrayList<Integer>();
for(Object object : list){
if(object instanceof Integer){
result.add((Integer)object);
}else if(object instanceof String){
try{
result.add(Integer.valueOf((String)object));
}catch(Exception ex){}
}else if(object instanceof Character){
result.add((int)((Character)object).charValue());
}else if(object instanceof Number){
result.add(((Number)object).intValue());
}
}
return result;
}
public List<Boolean> getBooleanList(String path){
List<?> list=getList(path);
if(list==null){
return new ArrayList<Boolean>(0);
}
List<Boolean> result=new ArrayList<Boolean>();
for(Object object : list){
if(object instanceof Boolean){
result.add((Boolean)object);
}else if(object instanceof String){
if(Boolean.TRUE.toString().equals(object)){
result.add(true);
}else if(Boolean.FALSE.toString().equals(object)){
result.add(false);
}
}
}
return result;
}
public List<Double> getDoubleList(String path){
List<?> list=getList(path);
if(list==null){
return new ArrayList<Double>(0);
}
List<Double> result=new ArrayList<Double>();
for(Object object : list){
if(object instanceof Double){
result.add((Double)object);
}else if(object instanceof String){
try{
result.add(Double.valueOf((String)object));
}catch(Exception ex){}
}else if(object instanceof Character){
result.add((double)((Character)object).charValue());
}else if(object instanceof Number){
result.add(((Number)object).doubleValue());
}
}
return result;
}
public List<Float> getFloatList(String path){
List<?> list=getList(path);
if(list==null){
return new ArrayList<Float>(0);
}
List<Float> result=new ArrayList<Float>();
for(Object object : list){
if(object instanceof Float){
result.add((Float)object);
}else if(object instanceof String){
try{
result.add(Float.valueOf((String)object));
}catch(Exception ex){}
}else if(object instanceof Character){
result.add((float)((Character)object).charValue());
}else if(object instanceof Number){
result.add(((Number)object).floatValue());
}
}
return result;
}
public List<Long> getLongList(String path){
List<?> list=getList(path);
if(list==null){
return new ArrayList<Long>(0);
}
List<Long> result=new ArrayList<Long>();
for(Object object : list){
if(object instanceof Long){
result.add((Long)object);
}else if(object instanceof String){
try{
result.add(Long.valueOf((String)object));
}catch(Exception ex){}
}else if(object instanceof Character){
result.add((long)((Character)object).charValue());
}else if(object instanceof Number){
result.add(((Number)object).longValue());
}
}
return result;
}
public List<Byte> getByteList(String path){
List<?> list=getList(path);
if(list==null){
return new ArrayList<Byte>(0);
}
List<Byte> result=new ArrayList<Byte>();
for(Object object : list){
if(object instanceof Byte){
result.add((Byte)object);
}else if(object instanceof String){
try{
result.add(Byte.valueOf((String)object));
}catch(Exception ex){}
}else if(object instanceof Character){
result.add((byte)((Character)object).charValue());
}else if(object instanceof Number){
result.add(((Number)object).byteValue());
}
}
return result;
}
public List<Character> getCharacterList(String path){
List<?> list=getList(path);
if(list==null){
return new ArrayList<Character>(0);
}
List<Character> result=new ArrayList<Character>();
for(Object object : list){
if(object instanceof Character){
result.add((Character)object);
}else if(object instanceof String){
String str=(String)object;
if(str.length()==1){
result.add(str.charAt(0));
}
}else if(object instanceof Number){
result.add((char)((Number)object).intValue());
}
}
return result;
}
public List<Short> getShortList(String path){
List<?> list=getList(path);
if(list==null){
return new ArrayList<Short>(0);
}
List<Short> result=new ArrayList<Short>();
for(Object object : list){
if(object instanceof Short){
result.add((Short)object);
}else if(object instanceof String){
try{
result.add(Short.valueOf((String)object));
}catch(Exception ex){}
}else if(object instanceof Character){
result.add((short)((Character)object).charValue());
}else if(object instanceof Number){
result.add(((Number)object).shortValue());
}
}
return result;
}
public Vector getVector(String path){
Object def=getDefault(path);
return getVector(path,(def instanceof Vector)?(Vector)def:null);
}
public Vector getVector(String path,Vector def){
Object val=get(path,def);
return (val instanceof Vector)?(Vector)val:def;
}
public boolean isVector(String path){
Object val=get(path);
return val instanceof Vector;
}
public OfflinePlayer getOfflinePlayer(String path){
Object def=getDefault(path);
return getOfflinePlayer(path,(def instanceof OfflinePlayer)?(OfflinePlayer)def:null);
}
public OfflinePlayer getOfflinePlayer(String path,OfflinePlayer def){
Object val=get(path,def);
return (val instanceof OfflinePlayer)?(OfflinePlayer)val:def;
}
public boolean isOfflinePlayer(String path){
Object val=get(path);
return val instanceof OfflinePlayer;
}
public ItemStack getItemStack(String path){
Object def=getDefault(path);
return getItemStack(path,(def instanceof ItemStack)?(ItemStack)def:null);
}
public ItemStack getItemStack(String path,ItemStack def){
Object val=get(path,def);
return (val instanceof ItemStack)?(ItemStack)val:def;
}
public boolean isItemStack(String path){
Object val=get(path);
return val instanceof ItemStack;
}
public Color getColor(String path){
Object def=getDefault(path);
return getColor(path,(def instanceof Color)?(Color)def:null);
}
public Color getColor(String path,Color def){
Object val=get(path,def);
return (val instanceof Color)?(Color)val:def;
}
public boolean isColor(String path){
Object val=get(path);
return val instanceof Color;
}
@Override
public CommentedSection getConfigurationSection(String path){
Object val=get(path,null);
if(val!=null){
return (val instanceof CommentedSection)?(CommentedSection)val:null;
}
val=get(path,getDefault(path));
return (val instanceof ConfigurationSection)?createSection(path):null;
}
@Override
public boolean isConfigurationSection(String path){
Object val=get(path);
return val instanceof CommentedSection;
}
protected boolean isPrimitiveWrapper(Object input){
return input instanceof Integer||input instanceof Boolean||input instanceof Character||input instanceof Byte||input instanceof Short||input instanceof Double||input instanceof Long||input instanceof Float;
}
@Override
public void addDefault(String path,Object value){
Validate.notNull(path,"要添加默认值的路径不能为null");
if(root==this){
throw new UnsupportedOperationException("不支持的方法addDefault(String, Object)");
}
root.addDefault(createPath(this,path),value);
}
public boolean contains(String arg0,boolean arg1){
return this.get(path)!=null;
}
@Override
public CommentedSection getDefaultSection(){
CommentedConfiguration root=getRoot();
CommentedConfiguration defaults=root==null?null:root.getDefaults();
if(defaults!=null){
if(defaults.isConfigurationSection(getCurrentPath())){
return defaults.getConfigurationSection(getCurrentPath());
}
}
return null;
}
protected Object getDefault(String path){
Validate.notNull(path,"获取默认值的路径不能为null");
CommentedConfiguration root=this.getRoot();
CommentedConfiguration defaults=root==null?null:root.getDefaults();
return (defaults==null)?null:defaults.get(createPath(this,path));
}
protected void mapChildrenKeys(Set<String> output,CommentedSection section,boolean deep){
if(section instanceof CommentedSection){
CommentedSection sec=(CommentedSection)section;
for(Map.Entry<String,CommentedValue> entry : sec.map.entrySet()){
output.add(createPath(section,entry.getKey(),this));
if((deep)&&(entry.getValue().getValue() instanceof CommentedSection)){
CommentedSection subsection=(CommentedSection)entry.getValue().getValue();
mapChildrenKeys(output,subsection,deep);
}
}
}else{
Set<String> keys=section.getKeys(deep);
for(String key : keys){
output.add(createPath(section,key,this));
}
}
}
protected void mapChildrenValues(Map<String,Object> output,CommentedSection section,boolean deep){
if(section instanceof CommentedSection){
CommentedSection sec=(CommentedSection)section;
for(Map.Entry<String,CommentedValue> entry : sec.map.entrySet()){
output.put(createPath(section,entry.getKey(),this),entry.getValue().getValue());
if(entry.getValue().getValue() instanceof CommentedSection){
if(deep){
mapChildrenValues(output,(CommentedSection)entry.getValue().getValue(),deep);
}
}
}
}else{
Map<String,Object> values=section.getValues(deep);
for(Map.Entry<String,Object> entry : values.entrySet()){
output.put(createPath(section,entry.getKey(),this),entry.getValue());
}
}
}
public static String createPath(CommentedSection section,String key){
return createPath(section,key,(section==null)?null:section.getRoot());
}
public static String createPath(CommentedSection section,String key,CommentedSection relativeTo){
Validate.notNull(section,"不能从null节点创建路径");
CommentedConfiguration root=section.getRoot();
char separator=root.options().pathSeparator();
StringBuilder builder=new StringBuilder();
if(section!=null){
for(ConfigurationSection parent=section;(parent!=null)&&(parent!=relativeTo);parent=parent.getParent()){
if(builder.length()>0){
builder.insert(0,separator);
}
builder.insert(0,parent.getName());
}
}
if((key!=null)&&(key.length()>0)){
if(builder.length()>0){
builder.append(separator);
}
builder.append(key);
}
return builder.toString();
}
@Override
public String toString(){
CommentedConfiguration root=this.getRoot();
StringBuilder builder=new StringBuilder("{path='"+getCurrentPath()+"'");
builder.append(", root='").append(root==null?null:root.getClass().getSimpleName());
builder.append(", MapValue=").append(this.map).append("}");
return builder.toString();
}
@Override
public void addComments(String pPath,String...pComments){
CommentedValue tValue=this.getCommentedValue(pPath);
if(tValue!=null) tValue.addComments(pComments);
else this.setComments(pPath,pComments);
}
@Override
public void addDefaultComments(String pPath,String...pComments){
CommentedValue tValue=this.getCommentedValue(pPath);
if(tValue!=null) tValue.addDefaultComments(pComments);
else this.setComments(pPath,pComments);
}
@Override
public void setComments(String pPath,String...pComments){
CommentedValue tValue=this.getCommentedValue(pPath);
if(tValue!=null) tValue.setComments(pComments);
else if(pComments!=null) this.set(pPath,Function.asList(pComments));
}
public void setComments(String pPath,Collection<String> pComments){
CommentedValue tValue=this.getCommentedValue(pPath);
if(tValue!=null) tValue.setComments(pComments);
else if(pComments!=null){
CommentedSection newSec=this.createSection(pPath);
tValue=newSec.getParent().map.get(newSec.path);
tValue.setComments(pComments);
}
}
@Override
public ArrayList<String> getComments(String pPath){
CommentedValue tValue=this.getCommentedValue(pPath);
if(tValue!=null) return tValue.getComments();
else return new ArrayList<>();
}
@Override
public boolean hasComments(String pPath){
CommentedValue tValue=this.getCommentedValue(pPath);
if(tValue!=null) return tValue.hasComments();
else return false;
}
@Override
public ArrayList<String> clearComments(String pPath){
CommentedValue tValue=this.getCommentedValue(pPath);
if(tValue!=null) return tValue.clearComments();
else return new ArrayList<>();
}
}

View File

@@ -0,0 +1,207 @@
package cc.util.bossshop.config;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;
import org.bukkit.configuration.ConfigurationSection;
import cc.util.bossshop.Function;
/**
* 一个值包装类,用来保存注释
* List值会循环嵌套包装
* @author 聪聪
*
*/
public class CommentedValue{
/**注释行匹配器*/
protected final static Pattern COMMENT=Pattern.compile("^([ ]*)# ?(.*?)$");
/**值包装类的真实值,或是List的嵌套*/
private Object mValue;
/**注释,请不要直接操作注释*/
private ArrayList<String> mComments=null;
private CommentedValue(){}
/**
* 构造一个包装类并用指定的值初始化
* @param pParent 该值的父节点,用于值转换时使用
* @param pValue 值,非null
*/
private CommentedValue(CommentedSection pParent,Object pValue){
this.setValue(pParent,pValue);
}
/**
* 设置包装类的值
* @param pParent 该值的父节点,用于值转换时使用
* @param pValue 值,非null
*/
public void setValue(CommentedSection pParent,Object pValue){
if(pValue instanceof CommentedValue){
CommentedValue cvValue=(CommentedValue)pValue;
this.mValue=CommentedValue.convertValue(pParent,cvValue.mValue);
this.setComments(cvValue.getComments());
}
this.mValue=CommentedValue.convertValue(pParent,pValue);
}
/**
* 获取包装的值
*/
public Object getValue(){
return this.mValue;
}
/**
* 添加注释
* @param pComments 注释
*/
public void addComments(String...pComments){
if(pComments==null||pComments.length==0) return;
List<String> addComments=Function.asList(pComments);
addComments.addAll(this.getComments());
this.setComments(addComments);
}
/**
* 添加默认注释
* <p>如果注释已经存在,将忽略</p>
* @param pComments 评论
*/
public void addDefaultComments(String...pComments){
if(pComments==null||pComments.length==0) return;
if(!this.hasComments())
this.setComments(Function.asList(pComments));
}
/**
* 设置注释
* <p>
* 请勿设置null来清空注释<br />
* 如果要清空注释,请使用{@link CommentedValue#clearComments()}
* </p>/
* @param pComments 注释
*/
public void setComments(String...pComments){
this.setComments(Function.asList(pComments));
}
/**
* 添加集合中的注释到指定的路径
* <p>
* 此函数中会对每行注释进行过滤与格式化
* </p>
* @param pComments 注释
*/
protected void setComments(Collection<? extends String> pComments){
if(this.mComments==null) this.mComments=new ArrayList<>();
else this.mComments.clear();
ArrayList<String> addComments=new ArrayList<>();
for(String sLine : pComments){ //过滤null行,格式化注释
if(sLine==null) continue;
java.util.regex.Matcher tMatcher=COMMENT.matcher(sLine);
if(!tMatcher.find()) addComments.add(sLine);
else addComments.add(tMatcher.group(2));
}
this.mComments.addAll(pComments);
}
/**
* 获取指定路径下的注释的拷贝
* @return 非null
*/
public ArrayList<String> getComments(){
ArrayList<String> copyComments=new ArrayList<>();
if(this.mComments!=null){
copyComments.addAll(this.mComments);
}
return copyComments;
}
/**
* 节点是否有注释
*/
public boolean hasComments(){
return !this.getComments().isEmpty();
}
/**
* 清空指定路径下的注释
* @return 清理掉的注释,非null
*/
public ArrayList<String> clearComments(){
ArrayList<String> removedComments=new ArrayList<>();
if(this.mComments!=null){
removedComments.addAll(this.getComments());
this.mComments.clear();
}
return removedComments;
}
/**
* 包装一个值
* @param pParent 该值的父节点
* @param pValue 值内容,非null
* @return 包装后的值
*/
protected static CommentedValue wrapperValue(CommentedSection pParent,Object pValue){
CommentedValue cvValue=null;
if(pValue instanceof CommentedValue){
cvValue=(CommentedValue)pValue;
cvValue.mValue=CommentedValue.convertValue(pParent,cvValue.mValue);
}else{
cvValue=new CommentedValue();
cvValue.mValue=CommentedValue.convertValue(pParent,pValue);
}
return cvValue;
}
/**
* 转换值,同时会调整父子节点结构
* @param pParent 父节点
* @param pValue 值,非null,非CommentedValue
* @return 转换后的值
*/
private static Object convertValue(CommentedSection pParent,Object pValue){
if(pValue==null)
throw new IllegalArgumentException("值包装类不能包装null值");
if(pValue instanceof CommentedValue){
throw new IllegalArgumentException("值包装类不能包装值包装类实例");
}else if(pValue instanceof CommentedSection){
// 此处需要对节点的从属关系进行调整
CommentedSection cmtedSec=(CommentedSection)pValue;
if(cmtedSec.getParent()==pParent) return cmtedSec;
CommentedSection newCmtedSec=pParent.createSection(cmtedSec.getName());
for(String childKey : cmtedSec.map.keySet()){
Object cfgSecValue=cmtedSec.map.get(childKey);
if(cfgSecValue==null) continue;
newCmtedSec.map.put(childKey,CommentedValue.wrapperValue(newCmtedSec,cfgSecValue));
}
return newCmtedSec;
}else if(pValue instanceof ConfigurationSection){
// 转换成CommentedSection
ConfigurationSection cfgSec=(ConfigurationSection)pValue;
CommentedSection newSec=new CommentedSection();
for(String childKey : cfgSec.getKeys(false)){
Object cfgSecValue=cfgSec.get(childKey);
if(cfgSecValue==null) continue;
newSec.map.put(childKey,CommentedValue.wrapperValue(newSec,cfgSecValue));
}
}
return pValue;
}
@Override
public String toString(){
String str="{Comments:";
if(this.mComments!=null) str+=this.mComments;
else str+="[]";
return str+",Value:"+this.mValue+"}";
}
}

View File

@@ -0,0 +1,410 @@
package cc.util.bossshop.config;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConstructor;
import org.bukkit.configuration.file.YamlRepresenter;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.representer.Representer;
import cc.util.bossshop.FBukkit;
import cc.util.bossshop.config.YamlNode.ChildType;
/**
* 支持注释的Yaml文件配置管理器
* @author 聪聪
*
*/
public class CommentedYamlConfig extends CommentedConfiguration{
protected static final String BLANK_CONFIG="{}\n";
protected final static Pattern CFG_NODE=Pattern.compile("^([ ]*)(?!- | |#)(.*?)(?=:):( .*)?$");
protected final static Pattern CFG_VALUE=Pattern.compile("^([ ]*)- (.*?)$");
protected final static Pattern COMMENT=Pattern.compile("^([ ]*)# ?(.*?)$");
protected final Yaml yaml;
protected final DumperOptions dumpOptions;
/**
* 使用指定的消息前缀实例化配置管理器
* @param pLogPrefix 错误消息前缀
*/
public CommentedYamlConfig(){
this.dumpOptions=new DumperOptions();
this.dumpOptions.setIndent(2);
this.dumpOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
this.dumpOptions.setAllowUnicode(true);
if(!this.dumpOptions.isAllowUnicode()){
Class<DumperOptions> clazz=DumperOptions.class;
try{
Field field=clazz.getDeclaredField("allowUnicode");
field.setAccessible(true);
field.setBoolean(dumpOptions,true);
}catch(Exception exp){
this.log("错误,无法设置文件存储为unicode编码",exp);
}
}
Representer yamlRepresenter=new YamlRepresenter();
yamlRepresenter.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
this.yaml=new Yaml(new YamlConstructor(),yamlRepresenter,dumpOptions);
}
/**
* 在发生异常时用于输出调试信息,或输出警告信息到控制台
* @param level 错误等级
* @param msg 错误的提示消息
* @param thrown 要抛出的异常
*/
private void log(String msg,Throwable thrown){
FBukkit.severe(msg,thrown);
}
@Override
public void addDefault(String path,Object value){
if(this.get(path)==null) this.set(path,value);
super.addDefault(path,value);
}
/**
* 将从字符串生成的配置节点数据格式化复制到本实例中
* @param input 格式化后的数据
* @param section 本实例,用于递归
*/
protected void convertMapsToSections(Map<?,?> input,CommentedSection section){
if(input==null) return;
for(Map.Entry<?,?> entry : input.entrySet()){
String key=entry.getKey().toString();
Object value=entry.getValue();
if((value instanceof Map))
convertMapsToSections((Map<?,?>)value,section.createSection(key));
else section.set(key,value);
}
}
/**
* 保存当前配置内存中的数据为字符串
*/
public String saveToString(){
String dump=this.yaml.dump(this.getValues(false));
if(dump.equals(BLANK_CONFIG)) return "";
else return this.injectComments(dump);
}
/**
* 保存指定的数据到指定的文件,如果文件不存在将会自动创建
* <p>保存数据过程中的任何错误都会被记录到控制台然后忽视</p>
* @param pFile 指定的文件
* @return 是否保存成功
*/
public boolean saveToFile(File pFile){
Validate.notNull(pFile,"配置文件不能为null");
FileOutputStream output=null;
try{
this.tryCreateFile(pFile);
output=new FileOutputStream(pFile,false);
output.write(this.saveToString().getBytes("UTF-8"));
}catch(FileNotFoundException ex){
this.log("未找到文件["+pFile+"]",ex);
return false;
}catch(IOException ex){
this.log("无法保存文件["+pFile+"]",ex);
return false;
}finally{
if(output!=null) try{
output.close();
}catch(IOException exp){}
}
return true;
}
/**
* 从字符串中载入配置
*/
public void loadFromString(String pContents) throws InvalidConfigurationException{
Validate.notNull(pContents,"字符串不能为null");
Map<?,?> input=null;
try{
input=(Map<?,?>)this.yaml.load(pContents);
}catch(YAMLException e){
throw new InvalidConfigurationException(e);
}catch(ClassCastException e){
throw new InvalidConfigurationException("配置文件顶级节点不是Map");
}
this.clear();
this.convertMapsToSections(input,this);
this.extractComments(pContents);
}
/**
* 从给定的文件路径中载入数据
* <p>
* 如果文件不存在将会自动创建<br />
* 载入配置文件过程中的任何错误都会被记录到控制台然后忽视<br />
* 如果载入失败,配置管理器内容将不变<br />
* 编码默认使用 UTF-8
* <p>
*
*@return 是否载入成功
* @param pFilename 输入的文件路径
* @throws NullPointerException 如果文件名为空
*/
public boolean loadFromFile(String pFilename){
Validate.notNull(pFilename,"文件名不能为null");
return this.loadFromFile(new File(pFilename));
}
/**
* 从给定的文件中载入数据
* <p>
* 如果文件不存在将会自动创建<br />
* 载入配置文件过程中的任何错误都会被记录到控制台然后忽视<br />
* 如果载入失败,配置管理器内容将不变<br />
* 编码默认使用 UTF-8
* <p>
*
* @param pFile 输入文件
* @return 是否成功加载
* @throws IllegalArgumentException 如果文件为空
*/
public boolean loadFromFile(File pFile){
Validate.notNull(pFile,"文件不能为null");
FileInputStream input=null;
try{
byte[] contents=new byte[(int)pFile.length()];
if(!pFile.isFile()) this.tryCreateFile(pFile);
input=new FileInputStream(pFile);
input.read(contents);
this.loadFromString(new String(contents,"UTF-8"));
}catch(FileNotFoundException ex){
this.log("无法找到文件["+pFile+"]",ex);
return false;
}catch(IOException ex){
this.log("无法加载文件["+pFile+"]",ex);
return false;
}catch(InvalidConfigurationException ex){
this.log("无法加载文件["+pFile+"],配置文件格式错误",ex);
return false;
}finally{
if(input!=null) try{
input.close();
}catch(IOException exp){}
}
return true;
}
/**
* 从给定的流中载入数据,流不会自动关闭
* <p>
* 如果文件不存在将会自动创建<br />
* 载入配置文件过程中的任何错误都会被记录到控制台然后忽视<br />
* 如果载入失败,配置管理器内容将不变<br />
* 编码默认使用 UTF-8
* <p>
*
* @param stream 输入的数据流
* @return 是否载入成功
* @throws IllegalArgumentException 如果输入流为空
*/
public boolean loadFromStream(InputStream stream){
Validate.notNull(stream,"输入流不能为空");
try{
byte[] contents=new byte[stream.available()];
this.loadFromString(new String(contents,"UTF-8"));
}catch(IOException ex){
this.log("无法从输入流加载配置",ex);
return false;
}catch(InvalidConfigurationException ex){
this.log("无法从输入流加载配置",ex);
return false;
}
return true;
}
/**
* 创建一个新文件<br/>
* 如果文件已经存在,将什么都不干
* @param pFile 文件
* @throws IOException 创建文件时发生错误
*/
protected void tryCreateFile(File pFile) throws IOException{
Validate.notNull(pFile,"配置文件不能为null");
if(pFile.exists()&&pFile.isFile()) return;
if(!pFile.getParentFile().isDirectory()) pFile.getParentFile().mkdirs();
pFile.createNewFile();
}
/**
* 设置Yaml文件单极的空格缩进个数
* @param pIndent 缩进
*/
public void setIndent(int pIndent){
this.dumpOptions.setIndent(pIndent);
}
/**
* 获取Yaml文件单极的空格缩进个数
* @param pIndent 缩进
*/
public int getIndent(){
return this.dumpOptions.getIndent();
}
/**
* 清空配置管理器
*/
public void clear(){
this.map.clear();
if(this.mDefaults!=null)
this.mDefaults.map.clear();
}
/**从字符串中导出注释*/
protected void extractComments(String pContent){
if(pContent==null) return;
pContent=pContent.replace("\\t"," ");
ArrayList<String> comments=new ArrayList<>();
YamlNode parent=new YamlNode("",-1,ChildType.NODE);
YamlNode now=new YamlNode("root",0,ChildType.STRING);
now.setParent(parent);
String[] allLines=pContent.split("[\\r]?\n");
Matcher matcher=null;
char tWrapper='\'';
int tIndent=this.getIndent();
for(int i=0;i<allLines.length;i++){
String sLine=allLines[i];
if(StringUtils.isBlank(sLine)) continue;
if((matcher=CommentedYamlConfig.CFG_NODE.matcher(sLine)).find()){ //模糊匹配到这是一个节点
YamlNode tNode=LineAnalyse.analyse(sLine,tWrapper,tIndent);
if(tNode==null) return ; //不是节点,,正则表达式同时约束了不是注释或者值,所以错误
if(tNode.getDeep()==parent.getDeep()+1){ //当前父节点的的直接子节点
if(!parent.setChildType(ChildType.NODE)) return;
}else if(tNode.getDeep()==parent.getDeep()+2){ //当前父节点的的直接孙子节点
if(!now.setChildType(ChildType.NODE)) return; //错误.挂了值的节点不能接配置节点
parent=now;
}else if(tNode.getDeep()<parent.getDeep()+1){ //上级节点的子节点
do{
if((parent=parent.getParent())==null) return; //错误,
}while(tNode.getDeep()<parent.getDeep()+1);
}else return; //错误
tNode.setParent(parent);
now=tNode;
//设置注释,以及判断节点是否闭合
if(!comments.isEmpty()){
this.setComments(tNode.getPath(),comments);
comments=new ArrayList<>();
}
while(!tNode.mClosed){
if(i>=allLines.length-1) return; //读取完毕
if(LineAnalyse.hasCloseMark(allLines[++i],tWrapper)) break;
}
continue;
}
if((matcher=CommentedYamlConfig.CFG_VALUE.matcher(sLine)).find()){//值节点
if(!now.setChildType(ChildType.ARRAY)) return ;
int blackCount=matcher.group(1).length();
if(blackCount!=now.getDeep()*tIndent) return ; //错误,不在同一级
boolean tClose=LineAnalyse.isCloseLine(matcher.group(2),tWrapper);
while(!tClose){
if(i>=allLines.length-1) return; //读取完毕
if(LineAnalyse.hasCloseMark(allLines[++i],tWrapper)) break;
}
if(!comments.isEmpty()) comments.clear(); //防止值注释混合到下个节点
continue;
}
if((matcher=CommentedYamlConfig.COMMENT.matcher(sLine)).find()){//注释节点
comments.add(matcher.group(2));
continue;
}
return; //不认识的节点,或者处理的时候出错了
}
}
/**将注释导入到字符串中*/
protected String injectComments(String pContent){
if(pContent==null) return "";
ArrayList<String> contents=new ArrayList<>();
YamlNode parent=new YamlNode("",-1,ChildType.NODE);
YamlNode now=new YamlNode("root",0,ChildType.STRING);
now.setParent(parent);
String[] allLines=pContent.split("[\\r]?\n");
Matcher matcher=null;
char tWrapper='\'';
int tIndent=this.getIndent();
for(int i=0;i<allLines.length;i++){
String sLine=allLines[i];
if(StringUtils.isBlank(sLine)){
contents.add("# ");
continue;
}
if((matcher=CommentedYamlConfig.CFG_NODE.matcher(sLine)).find()){ //模糊匹配到这是一个节点
YamlNode tNode=LineAnalyse.analyse(sLine,tWrapper,tIndent);
if(tNode==null) return pContent; //不是节点,,正则表达式同时约束了不是注释或者值,所以错误
if(tNode.getDeep()==parent.getDeep()+1){ //当前父节点的的直接子节点
if(!parent.setChildType(ChildType.NODE)) return pContent;
}else if(tNode.getDeep()==parent.getDeep()+2){ //当前父节点的的直接孙子节点
if(!now.setChildType(ChildType.NODE)) return pContent;
parent=now;
}else if(tNode.getDeep()<parent.getDeep()+1){ //上级节点的子节点
do{
if((parent=parent.getParent())==null) return pContent; //错误,
}while(tNode.getDeep()<parent.getDeep()+1);
}else return pContent; //错误
tNode.setParent(parent);
now=tNode;
//设置注释,以及判断节点是否闭合
this.addCommentToContent(contents,tNode.getDeep()*tIndent,this.getComments(tNode.getPath()));;
contents.add(sLine);
while(!tNode.mClosed){
if(i>=allLines.length-1) return pContent; //读取完毕
contents.add(allLines[++i]);
if(LineAnalyse.hasCloseMark(allLines[i],tWrapper)) break;
}
continue;
}
if((matcher=CommentedYamlConfig.CFG_VALUE.matcher(sLine)).find()){//值节点
if(!now.setChildType(ChildType.ARRAY)) return pContent;
int blackCount=matcher.group(1).length();
if(blackCount!=now.getDeep()*tIndent) return pContent; //错误,不在同一级
boolean tClose=LineAnalyse.isCloseLine(matcher.group(2),tWrapper);
contents.add(sLine);
while(!tClose){
if(i>=allLines.length-1) return pContent; //读取完毕,仍然没有关闭
contents.add(allLines[++i]);
if(LineAnalyse.hasCloseMark(allLines[i],tWrapper)) break;
}
continue;
}
return pContent; //不认识的节点,或者处理的时候出错了
}
StringBuilder builder=new StringBuilder();
for(String sStr : contents){
builder.append(sStr);
builder.append(System.getProperty("line.separator", "\n"));
}
return builder.toString();
}
private void addCommentToContent(ArrayList<String> contents,int blackCount,ArrayList<String> comments){
if(comments==null||comments.size()==0) return;
String blackPrefix="";
for(int i=0;i<blackCount;i++) blackPrefix+=" ";
blackPrefix+="# ";
for(String commentLine : comments)
contents.add(blackPrefix+commentLine);
}
}

View File

@@ -0,0 +1,45 @@
package cc.util.bossshop.config;
import java.util.ArrayList;
public interface ICommentedSection{
public void addComments(String pPath,String...pComments);
/**
* 添加默认注释
* <p>如果注释已经存在,将忽略</p>
* @param pComments 评论
*/
public void addDefaultComments(String pPath,String...pComments);
/**
* 设置注释
* <p>
* 请勿设置null来清空注释<br />
* 如果要清空注释,请使用{@link CommentedValue#clearComments()}
* </p>/
* @param pComments 注释
*/
public void setComments(String pPath,String...pComments);
/**
* 获取指定路径下的注释的拷贝
* @return 非null
*/
public ArrayList<String> getComments(String pPath);
/**
* 节点是否有注释
*/
public boolean hasComments(String pPath);
/**
* 清空指定路径下的注释
* @return 清理掉的注释,非null
*/
public ArrayList<String> clearComments(String pPath);
}

View File

@@ -0,0 +1,86 @@
package cc.util.bossshop.config;
import org.apache.commons.lang.StringUtils;
import cc.util.bossshop.config.YamlNode.ChildType;
public class LineAnalyse{
/**
* 分析一个行文本是不是一个节点
* @param pLine 文本
* @param pWrapper Yaml字符串包裹字符
* @return 是返回节点,不是返回null
*/
public static YamlNode analyse(String pLine,char pWrapper,int pIndent){
if(pLine==null||pLine.trim().length()<=2) return null;
int blackCount=0;
char[] arrs=pLine.toCharArray();
int i=0;
for(i=0;i<arrs.length;i++){
if(arrs[i]==' ') blackCount++;
else break;
}
if(blackCount%pIndent!=0) return null;
arrs=pLine.trim().toCharArray();
i=1;
boolean warp=(arrs[0]==pWrapper);
while(i<arrs.length){
char c=arrs[i++];
if(warp){
if(c==pWrapper){
if(i>=arrs.length) break; //没字符了
if(arrs[i]!=pWrapper){
warp=false; //'后面不是单引号,warp到尾部
if(arrs[i]!=':') return null; //单引号闭合后最后必须是冒号
}
else i++; //如果是单引号,跳过这个字符的检查
}
}else{
if(c==':'){
if(i>=arrs.length){ //不带值的节点
int start=0,end=arrs.length-1;
if(arrs[0]==pWrapper){
start++;
end--;
}
if(start==end) return null;//空标签节点
return new YamlNode(new String(arrs,start,end),blackCount/pIndent,null);
}
if(arrs[i]==' '){ //带值的节点,后面肯定有值,因为已经trim过了
i++;
break;
}
}
}
}
if(i>=arrs.length) return null;
int start=0,end=i-2; //去掉冒号加空格
if(arrs[0]==pWrapper){
start++;
end--;
}
if(start==end) return null; //空标签节点
String name=new String(arrs,start,end);
boolean close=true;
if(arrs[i]==pWrapper){
close=LineAnalyse.isCloseLine(new String(arrs,i,arrs.length-i),pWrapper);
}
YamlNode node=new YamlNode(name,blackCount/pIndent,ChildType.STRING);
node.mClosed=close;
return node;
}
public static boolean isCloseLine(String pLine,char pWrapper){
if(StringUtils.isBlank(pLine)) return true;
pLine=pLine.trim();
if(pLine.charAt(0)!=pWrapper) return true;
if(pLine.length()==1) return false;
return pLine.charAt(pLine.length()-1)==pWrapper;
}
public static boolean hasCloseMark(String pLine,char pWrapper){
if(StringUtils.isEmpty(pLine)) return false;
return pLine.charAt(pLine.length()-1)==pWrapper;
}
}

View File

@@ -0,0 +1,73 @@
package cc.util.bossshop.config;
import org.apache.commons.lang.Validate;
public class YamlNode{
enum ChildType{
NODE,STRING,ARRAY
}
/**该行是否已经关闭*/
public boolean mClosed=true;
/**节点深度(空格数+1/2)*/
public final int mDeep;
/**节点名字*/
public final String mName;
/**子节点类型,默认为null,单值为String.class,多值为List.class,节点为Object.class*/
private ChildType mChildType=null;
/**父节点*/
private YamlNode mParent=null;
public YamlNode(String pName,int pDeep,ChildType pType){
if(pName==null) pName="";
this.mName=pName;
this.mDeep=pDeep;
this.mChildType=pType;
}
/**
* 设置节点类型,如果节点类型已经存在并且与设置的节点类型不同,将返回false
* @param pType 节点类型不能为null
* @return 是否设置成功
*/
public boolean setChildType(ChildType pType){
Validate.notNull(pType,"子节点类型不能为null");
if(this.mChildType==null||this.mChildType==pType){
this.mChildType=pType;
return true;
}else return false;
}
/**
* 获取层级
*/
public int getDeep(){
return this.mDeep;
}
public String getPath(){
if(this.mParent==null) return this.mName;
String parentPath=this.mParent.getPath();
if(parentPath.isEmpty()) return this.mName;
else return parentPath+"."+this.mName;
}
public YamlNode setParent(YamlNode pParent){
this.mParent=pParent;
return this;
}
public YamlNode getParent(){
return this.mParent;
}
@Override
public String toString(){
return this.mDeep+"|"+this.getPath();
}
}

View File

@@ -0,0 +1,21 @@
package cc.util.bossshop.config;
import java.util.ArrayList;
public class YamlStack{
private int mDeep=0;
private final ArrayList<String> mStack=new ArrayList<>();
public int push(String pStr){
return this.mDeep++;
}
public String pop(){
return null;
}
}

View File

@@ -0,0 +1,22 @@
package cc.util.bossshop.filemanager;
import cc.util.bossshop.pluginmodel.ABukkitPlugin;
public abstract class AConfigManager extends AFileManager{
public AConfigManager(ABukkitPlugin pPlugin,String pVersion){
super(pPlugin,"config.yml",pVersion);
}
@Override
public void addDefaults(){
super.addDefaults();
this.mConfig.addDefault("debug",true);
this.mConfig.addDefaultComments("debug","是否开启调试模式","如果开启调试模式,插件报错的时候会输出完整的堆栈错误","还可能会输出一些个人设置的调试信息");
}
public boolean isDebug(){
return this.mConfig.getBoolean("debug");
}
}

View File

@@ -0,0 +1,163 @@
package cc.util.bossshop.filemanager;
import java.io.File;
import org.apache.commons.lang.Validate;
import cc.util.bossshop.config.CommentedYamlConfig;
import cc.util.bossshop.pluginmodel.ABukkitPlugin;
public abstract class AFileManager{
// 静态全局变量
/**
* 配置文件版本节点
*/
public static final String SEC_CFG_VERSION="version";
// 普通变量
/**
* 主插件
*/
protected final ABukkitPlugin mPlugin;
/**
* 管理器依赖的文件名
*/
protected final String mFileName;
/**
* 管理器依赖的文件
*/
protected File mFile;
protected CommentedYamlConfig mConfig=new CommentedYamlConfig();
/**
* 配置文件版本
*/
protected String mVersion="1.0";
/**
* 构造一个基于文件的管理器
* @param pPlugin 主插件
* @param pFileName 数据文件的相对路径
*/
public AFileManager(ABukkitPlugin pPlugin,String pFileName,String pVersion){
Validate.notNull(pFileName,"配置文件不能为空");
this.mPlugin=pPlugin;
this.mFileName=pFileName;
this.mVersion=pVersion;
this.mFile=new File(mPlugin.getDataFolder().getAbsolutePath(),mFileName);
}
/**
* 重载配置文件
* <p>
* 如果文件不存在,自动创建文件<br />
* 所有可能发生的错误都会被捕捉并显示在控制台<br />
* </p>
* @return 是否载入成功
*/
public boolean reloadConfig(){
if(!this.mConfig.loadFromFile(this.mFile)){
this.severe("从文件"+this.mFileName+"载入配置失败,内存中配置未变化,目标文件未改动");
return false;
}
return true;
}
/**
* 保存config中的数据到到文件
* <p>如果存在注释头部,将会同时保存注释头部</p>
*/
public boolean saveConfig(){
if(!this.mConfig.saveToFile(mFile)){
this.severe("保存配置"+this.mFileName+"到文件失败,目标文件未改动");
return false;
}
return true;
}
/**
* 添加配置文件的默认值
* <p>
* 默认添加了版本<br />
* 不应该在该函数中保存配置
* </p>
*/
protected void addDefaults(){
this.mConfig.addDefault(AFileManager.SEC_CFG_VERSION,this.mVersion);
this.mConfig.addDefaultComments(AFileManager.SEC_CFG_VERSION,"配置文件版本,重要,请勿修改","插件升级配置的时候需要用到");
}
/**
* 检查配置文件版本是否需要更新,如果是则返回true
* <p>请在实现类中的该方法中对文件进行更新操作</p>
*/
protected boolean checkUpdate(){
String tVersion=this.mConfig.getString(SEC_CFG_VERSION,"1.0");
if(this.mVersion.compareToIgnoreCase(tVersion)<=0) return false;
return true;
}
/**
* 获取语言节点
* @param pNode 节点名
*/
protected String C(String pNode){
return this.mPlugin.getLangManager().getNode(pNode);
}
/**
* 获取该文件管理器的配置器
*/
public CommentedYamlConfig getConfig(){
return this.mConfig;
}
/**
* 获取该文件管理器的文件名
* @return
*/
public String getConfigFilename(){
return this.mFileName;
}
/**
* 发送普通消息到控制台
*/
public void info(String pMsg){
this.mPlugin.info(pMsg);
}
/**
* 发送消息到控制题啊
* 添加消息到bug日志
*/
public void warn(String pMsg){
this.mPlugin.warn(pMsg);
}
/**
* 输出错误消息到控制台
* @param pMsg
*/
public void severe(String pMsg){
this.mPlugin.severe(pMsg);
}
/**
* 输出调试信息
* <p>如果配置文件中未启用调试,将不会输出信息</p>
*/
public void debug(String message){
this.mPlugin.debug(message);
}
/**
* 输出错误消息到控制台,如果配置文件中启用调试模式,将会同时输出错误堆栈信息
* @param pMsg 错误的消息
* @param pExp 异常
*/
public void severe(String pMsg,Exception pExp){
this.mPlugin.severe(pMsg,pExp);
}
}

View File

@@ -0,0 +1,28 @@
package cc.util.bossshop.filemanager;
import org.bukkit.ChatColor;
import cc.util.bossshop.pluginmodel.ABukkitPlugin;
public abstract class ALangManager extends AFileManager{
public ALangManager(ABukkitPlugin pPlugin,String pFileName,String pVersion){
super(pPlugin,pFileName,pVersion);
}
/**
* 获取指定消息节点的翻译,大小写敏感
* @param pNode 消息节点名
* @return 翻译后的消息
*/
public String getNode(String pNode){
String tMsg=this.mConfig.getString(pNode);
if(tMsg!=null) return ChatColor.translateAlternateColorCodes('&',tMsg);
else{
this.mPlugin.warn("missing language node ["+pNode+"]");
this.mPlugin.warn("丢失语言节点 ["+pNode+"]");
return pNode;
}
}
}

View File

@@ -0,0 +1,278 @@
package cc.util.bossshop.pluginmodel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import cc.util.bossshop.filemanager.AConfigManager;
import cc.util.bossshop.filemanager.ALangManager;
import me.clip.placeholderapi.PlaceholderAPI;
public abstract class ABukkitPlugin extends JavaPlugin{
/**
* 插件消息前缀
*/
protected String prefix="§c[§7Templet§c]§b";
/**
* 插件日志前缀
*/
protected String logpre="[Templet]";
/**
* 插件实例
*/
protected static ABukkitPlugin mInstance;
protected String mPluginName;
/**
* 可重置状态模块实例列表
*/
protected ArrayList<IClearAble> mClearModel=new ArrayList<>();
/**
* 需要重新读取配置的模块列表,此列表模块将在配置文件重载后调用重载方法
*/
protected ArrayList<INeedConfig> mConfigModels=new ArrayList<>();
/**
* 需要重载的模块列表,此列表模块将在配置文件重载后调用重载方法
*/
protected ArrayList<INeedReload> mReloadModels=new ArrayList<>();
/**
* 配置管理器,需要初始化
*/
protected AConfigManager mConfigManager;
/**
* 语言管理器,需要初始化
*/
protected ALangManager mLangManager;
/**
* 新建一个插件实例
* <p>
* 同时会设置静态mInstance变量的值<br />
* 实例化该对象后,请注意同时实例化语言文件和配置文件
* </p>
*/
public ABukkitPlugin(String pPluginName){
ABukkitPlugin.mInstance=this;
this.mPluginName=pPluginName;
this.logpre="["+pPluginName+"]";
this.prefix="§c[§7"+pPluginName+"§c]§b";
}
/**
* 获取插件实例<br />
* 不建议在static模块中初始化的时候调用此方法
*/
private static ABukkitPlugin getInstance(){
return ABukkitPlugin.mInstance;
}
/**
* 获取语言翻译
*/
public String C(String pNode){
return this.mLangManager.getNode(pNode);
}
/**
* 获取插件名字,用于构造命令,权限等
*/
public String getPluginName(){
return this.mPluginName;
}
/**
* 聊天前缀
*/
public String getChatPrefix(){
return this.prefix;
}
/**
* log日志前缀
*/
public String getLogPrefix(){
return this.logpre;
}
/**
* 请使用{@link ABukkitPlugin#getConfigManager()#getConfig()}<br />
* 调用此方法将抛出异常
*
*/
@Deprecated
public FileConfiguration getConfig(){
throw new IllegalAccessError("请不不要调用此方法");
}
/**
* 获取插件配置管理器
*/
public AConfigManager getConfigManager(){
return this.mConfigManager;
}
/**
* 获取插件语言管理器
*/
public ALangManager getLangManager(){
return this.mLangManager;
}
/**
* 重载插件
*/
public abstract void reloadPlugin();
/**
* 清理插件可清理模块列表
* @return 清理的模块数量
*/
public int clearModelStatus(){
int tCount=0;
for(IClearAble sClearModel : this.mClearModel){
if(sClearModel.clearStatus()) tCount++;
}
return tCount;
}
/**
* 注册可清理状态模块列表
*/
public void registerClearModel(IClearAble pClearModel){
if(this.mClearModel.contains(pClearModel)) return;
this.mClearModel.add(pClearModel);
}
/**
* 注册需要重载配置的模块列表,此列表只用于非重要实例使用
*/
public void registerConfigModel(INeedConfig pNeedConfig){
if(this.mConfigModels.contains(pNeedConfig)) return;
this.mConfigModels.add(pNeedConfig);
}
/**
* 注册需要重载配置的模块列表,此列表只用于非重要实例使用
*/
public void registerReloadModel(INeedReload pNeedReload){
if(this.mReloadModels.contains(pNeedReload)) return;
this.mReloadModels.add(pNeedReload);
}
/**
* 移除可清理状态模块列表
* @return 如果存在并移除返回true,不存在返回false
*/
public boolean unregisterClearModel(IClearAble pClearModel){
return this.mClearModel.remove(pClearModel);
}
/**
* 移除可重载模块列表
* @return 如果存在并移除返回true,不存在返回false
*/
public boolean unregisterReloadModel(INeedConfig pReloadModel){
return this.mConfigModels.remove(pReloadModel);
}
/**
* 禁用此方法,请使用{@link ABukkitPlugin #reloadPlugin()}方法重载插件
*/
@Deprecated
@Override
public void reloadConfig(){}
/**
* 发送消息到指定玩家
* @param pSender 发送给谁
* @param pMsg 消息,不需要加前缀
* @return true
*/
public boolean send(CommandSender pSender,String pMsg){
return this.send(pSender,pMsg,prefix);
}
/**
* 发送普通的Console消息
* @param pMsg 消息,不需要加前缀
*/
public void info(String pMsg){
this.send(Bukkit.getConsoleSender(),pMsg,prefix);
}
/**
* 发送警告的Console消息,暗红色消息
* @param pMsg 消息,不需要加前缀
*/
public void warn(String pMsg){
this.send(Bukkit.getConsoleSender(),pMsg,prefix+ChatColor.DARK_RED+"[WARN]");
}
/**
* 发送错误的Console消息,暗红色消息
* @param pMsg 消息,不需要加前缀
*/
public void severe(String pMsg){
this.send(Bukkit.getConsoleSender(),pMsg,prefix+ChatColor.RED+"[ERROR]");
}
/**
* 输出错误信息到Console
* <p>如果配置文件启用调试模式,会同时发送错误堆栈</p>
* @param pMsg 消息
* @param pExp 异常
*/
public void severe(String pMsg,Throwable pExp){
this.send(Bukkit.getConsoleSender(),pMsg,prefix+ChatColor.RED+"[ERROR]");
if(!this.getConfigManager().isDebug()){
this.severe("配置文件启用调试模式以看到更多错误消息");
return;
}
String[] lines= org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(pExp).split("(\r?\n)+");
for(String sLine : lines)
this.debug(sLine);
}
/**
* 输出调试信息到,红色
* @param pMsg 消息
*/
public void debug(String pMsg){
if(!this.getConfigManager().isDebug()) return;
send(Bukkit.getConsoleSender(),pMsg,prefix+ChatColor.RED+"[DEBUG]");
}
/**
* 向用户发送消息
* @param pSender 目标
* @param pMsg 消息
* @param pPrefix 消息前缀
* @return true
*/
public boolean send(CommandSender pSender,String pMsg,String pPrefix){
if(StringUtils.isBlank(pMsg)) return true;
if(pSender==null) pSender=Bukkit.getConsoleSender();
pMsg=ChatColor.translateAlternateColorCodes('&',pMsg);
pPrefix=ChatColor.translateAlternateColorCodes('&',pPrefix);
if(pSender instanceof Player&&Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")){
pMsg=PlaceholderAPI.setPlaceholders((Player)pSender,pMsg);
pPrefix=PlaceholderAPI.setPlaceholders((Player)pSender,pPrefix);
}
List<String> tMsgs=Arrays.asList(pMsg.split("\n+"));
for(String sMsg : tMsgs)
pSender.sendMessage(pPrefix+" "+sMsg);
return true;
}
}

View File

@@ -0,0 +1,17 @@
package cc.util.bossshop.pluginmodel;
/**
* 可清除内存临时数据
* @author 聪聪
*
*/
public interface IClearAble{
/**
* 清理内存数据
* @return 是否成功
*/
public boolean clearStatus();
}

View File

@@ -0,0 +1,23 @@
package cc.util.bossshop.pluginmodel;
/**
* 一个用于非重要实例对象在插件主配置重载后调用的接口
* <p>
* 如果实例没有变量存储,但又需要读取配置,可以集成该接口<br />
* 该接口的对象的重载操作将在最后调用<br />
* </p>
*
* @author 聪聪
*
*/
public interface INeedConfig{
/**
* 重载一个实例
* 确保在重载了配置文件之后重载<br />
* 最好只在此函数中做和配置变动相关的操作
*/
public void setConfig();
}

View File

@@ -0,0 +1,12 @@
package cc.util.bossshop.pluginmodel;
/**
* 如果实例需要在插件重载的时候重新加载除配置以外的内容可以实现该接口
* @author 聪聪
*
*/
public interface INeedReload{
public boolean reloadConfig();
}

View File

@@ -0,0 +1,10 @@
package cc.util.bossshop.pluginmodel;
public enum ReloadPriority{
LOW,
NORMAL,
HIGH
}