1
0
mirror of https://e.coding.net/circlecloud/BossShop-re.git synced 2024-12-29 07:38:47 +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

9
src/main/java/Test.java Normal file
View File

@ -0,0 +1,9 @@
public class Test{
public static void main(String[] args){
System.out.println(System.class.getPackage().getSpecificationVersion());
}
}

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
}

View File

@ -0,0 +1,214 @@
package org.black_ixx.bossshop;
import java.util.HashMap;
import org.black_ixx.bossshop.api.BossShopAPI;
import org.black_ixx.bossshop.command.CommandExc;
import org.black_ixx.bossshop.core.BSShopHolder;
import org.black_ixx.bossshop.core.BSShopManager;
import org.black_ixx.bossshop.events.BSReloadedEvent;
import org.black_ixx.bossshop.listeners.InventoryListener;
import org.black_ixx.bossshop.listeners.PlayerListener;
import org.black_ixx.bossshop.listeners.SignListener;
import org.black_ixx.bossshop.lottery.LotteryManager;
import org.black_ixx.bossshop.mail.MailManager;
import org.black_ixx.bossshop.managers.BuyItemHandler;
import org.black_ixx.bossshop.managers.ConfigManager;
import org.black_ixx.bossshop.managers.ItemNameManager;
import org.black_ixx.bossshop.managers.ItemStackCreator;
import org.black_ixx.bossshop.managers.LangManager;
import org.black_ixx.bossshop.managers.MultiplierHandler;
import org.black_ixx.bossshop.managers.RecordManager;
import org.black_ixx.bossshop.managers.ShopCustomizer;
import org.black_ixx.bossshop.managers.TimeHandler;
import org.black_ixx.bossshop.managers.TransactionLog;
import org.black_ixx.bossshop.managers.VaultHandler;
import org.black_ixx.bossshop.managers.WorthHandler;
import org.black_ixx.bossshop.nbt.NBTEditManager;
import org.black_ixx.bossshop.points.PointsManager;
import org.black_ixx.bossshop.sale.SaleListener;
import org.black_ixx.bossshop.sale.SaleManager;
import org.black_ixx.bossshop.util.AttributeRemover;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import cc.util.bossshop.FBukkit;
import cc.util.bossshop.config.CommentedYamlConfig;
import cc.util.bossshop.pluginmodel.ABukkitPlugin;
import cc.util.bossshop.pluginmodel.IClearAble;
import cc.util.bossshop.pluginmodel.INeedConfig;
import cc.util.bossshop.pluginmodel.INeedReload;
import me.clip.placeholderapi.PlaceholderAPI;
public class BossShop extends ABukkitPlugin{
private static BossShop instance;
public static boolean RE=false;
private CommandExc mCommander;
private SaleListener mSaleLis;
private static long mLastNoticeTime=0;
private BossShopAPI mAPI;
@Deprecated
private final HashMap<Class<?>,Object> mManager=new HashMap<>();
public BossShop(){
super("BossShop");
}
@Override
public void onEnable(){
AttributeRemover.init();
BossShop.instance=this;
this.info("开始初始化");
this.mCommander=new CommandExc(this);
// 监听器
new InventoryListener(this);
new SignListener(this);
new PlayerListener(this);
this.mSaleLis=new SaleListener(this);
new LotteryManager(this);
this.mAPI=new BossShopAPI(this);
// 实例化管理器
this.mConfigManager=new ConfigManager(this);
this.mManager.put(ConfigManager.class,this.mConfigManager);
this.mLangManager=new LangManager(this);
//此处注册管理器模块,注意注册的顺序
this.registerManager(LangManager.class,this.mLangManager);
//邮件和商店需要用到NBT,在他们之前注册NBT管理器
this.registerManager(NBTEditManager.class,new NBTEditManager(this));
this.registerManager(BSShopManager.class,new BSShopManager(this));
this.registerManager(MailManager.class,new MailManager(this));
this.registerManager(BuyItemHandler.class,new BuyItemHandler(this));
this.registerManager(ItemStackCreator.class,new ItemStackCreator(this));
this.registerManager(MultiplierHandler.class,new MultiplierHandler(this));
this.registerManager(PointsManager.class,new PointsManager(this));
this.registerManager(RecordManager.class,new RecordManager(this));
this.registerManager(SaleManager.class,new SaleManager(this));
this.registerManager(ShopCustomizer.class,new ShopCustomizer(this));
this.registerManager(TimeHandler.class,new TimeHandler(this));
this.registerManager(TransactionLog.class,new TransactionLog(this));
this.registerManager(VaultHandler.class,new VaultHandler(this));
this.registerManager(WorthHandler.class,new WorthHandler(this));
this.registerManager(ItemNameManager.class,new ItemNameManager(this));
// 载入配置
this.reloadPlugin();
}
@Override
public void onDisable(){
for(Player sPlayer : FBukkit.getOnlinePlayers()){
Inventory inv=sPlayer.getOpenInventory().getTopInventory();
if(inv.getHolder() instanceof BSShopHolder){
inv.clear();
sPlayer.closeInventory();
}
}
}
protected <T> void registerManager(Class<? extends T> clazz,T pManager){
this.mManager.put(clazz,pManager);
}
public <T> T getManager(Class<? extends T> clazz){
if(clazz==null) return null;
T tt=null;
try{
tt=(T)this.mManager.get(clazz);
}catch(Exception exp){
this.severe("获取模块并进行强制转换时发生了错误:"+exp.getMessage(),exp);
return null;
}
if(tt==null) throw new IllegalStateException("管理器类"+clazz.getName()+"没有实例化对象");
return tt;
}
public static BossShop getInstance(){
return (BossShop)mInstance;
}
public BossShopAPI getAPI(){
return this.mAPI;
}
public CommandExc getCommandExc(){
return this.mCommander;
}
public ConfigManager getConfigManager(){
return (ConfigManager)this.mConfigManager;
}
public LangManager getLangManager(){
return (LangManager)this.mLangManager;
}
public SaleListener getSaleListener(){
return this.mSaleLis;
}
@Override
public void reloadConfig(){
this.mConfigManager.reloadConfig();
CommentedYamlConfig tConfig=this.mConfigManager.getConfig();
this.logpre=ChatColor.translateAlternateColorCodes('&',tConfig.getString("LogPrefix","[BossShop]"));
this.prefix=ChatColor.translateAlternateColorCodes('&',tConfig.getString("MsgPrefix","§c[§7BossShop§c]§b"));
for(INeedConfig sConfig : this.mConfigModels)
sConfig.setConfig();
}
public void reloadPlugin(){
BossShop.isEnablePlaceholderAPI();
//首先将语言和配置读入,并且模块也读入配置
this.mLangManager.reloadConfig();
//主配置的重载
this.reloadConfig();
//调用模块的reloadConfig()
for(INeedReload sReload : this.mReloadModels)
sReload.reloadConfig();
BSReloadedEvent event=new BSReloadedEvent(this);
Bukkit.getPluginManager().callEvent(event);
}
public int clearMemoryRecord(){
int count=0;
for(IClearAble sClearAble : this.mClearModel)
if(sClearAble.clearStatus()) count++;
mLastNoticeTime=0;
return count++;
}
/**
* 替换占位符为实际字符串
* @param str
* @return
*/
public static String replaceParam(Player pPlayer,String pStr){
if(!BossShop.isEnablePlaceholderAPI()) return ChatColor.translateAlternateColorCodes('&',pStr);
try{
pStr=PlaceholderAPI.setPlaceholders(pPlayer,pStr);
}catch(Throwable exp){
if(mInstance!=null) mInstance.severe("在调用PlaceHolderAPI是发生了异常,请确保你的插件和PlaceHolderAPI模块版本匹配: "+exp.getMessage(),exp);
}
return pStr;
}
private static boolean isEnablePlaceholderAPI(){
if(BossShop.RE) return true;
if(!Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")){
if(mLastNoticeTime+600000<System.currentTimeMillis()&&mInstance!=null){
mInstance.info("未发现PlaceholderAPI插件,BossShop插件可能需要该插件来完善功能");
mInstance.info("请前往https://www.spigotmc.org/resources/placeholderapi.6245 下载");
mLastNoticeTime=System.currentTimeMillis();
}
return false;
}else{
BossShop.RE=true;
return true;
}
}
}

View File

@ -0,0 +1,62 @@
package org.black_ixx.bossshop.api;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin;
public class BSAddonConfig{
private Plugin plugin;
private File file;
private YamlConfiguration config;
boolean isSaving=false;
public BSAddonConfig(Plugin plugin,String file_name){
this.plugin=plugin;
file=new File(plugin.getDataFolder().getAbsolutePath()+"/"+file_name+".yml");
config=YamlConfiguration.loadConfiguration(file);
}
public void save(){
if(isSaving) return;
isSaving=true;
try{
config.save(file);
}catch(IOException e1){
plugin.getLogger().warning("File I/O Exception on saving "+file.getName());
e1.printStackTrace();
}
isSaving=false;
}
public void saveAsync(){
plugin.getServer().getScheduler().runTaskAsynchronously(plugin,new Runnable(){
@Override
public void run(){
save();
}
});
}
public void reload(){
try{
config.load(file);
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}catch(InvalidConfigurationException e){
e.printStackTrace();
}
}
public FileConfiguration getConfig(){
return config;
}
}

View File

@ -0,0 +1,109 @@
package org.black_ixx.bossshop.api;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSBuy;
import org.black_ixx.bossshop.core.BSShop;
import org.black_ixx.bossshop.core.BSShopHolder;
import org.black_ixx.bossshop.core.BSShopManager;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
public class BossShopAPI{
private BossShop mPlugin;
private List<BossShopAddon> enabled_addons;
public BossShopAPI(BossShop plugin){
this.mPlugin=plugin;
}
// For Single Shop
public boolean isValidShop(Inventory i){
return (i.getHolder() instanceof BSShopHolder&&this.mPlugin.getManager(BSShopManager.class).getShop(i.getName())!=null);
}
public BSShop getShop(String name){
return this.mPlugin.getManager(BSShopManager.class).getShop(name.toLowerCase());
}
public void openShop(Player p,String name){
BSShop shop=getShop(name);
if(shop==null){
this.mPlugin.warn("尝试打开不存在的商店["+name+"]");
return;
}
openShop(p,shop);
}
public void openShop(Player p,BSShop shop){
this.mPlugin.getManager(BSShopManager.class).openShop(p,shop);
}
// Get Managers
public BSShopManager getShopHandler(){
return this.mPlugin.getManager(BSShopManager.class);
}
// Modify Shop/Shops
public void addItemToShop(ItemStack menu_item,BSBuy shop_item,BSShop shop){
shop.addShopItem(shop_item,menu_item);
}
public void finishedAddingItemsToShop(BSShop shop){
shop.finishedAddingItems();
}
// Get Shop Items
public HashMap<BSShop,List<BSBuy>> getAllShopItems(){
HashMap<BSShop,List<BSBuy>> all=new HashMap<BSShop,List<BSBuy>>();
for(BSShop shop : this.mPlugin.getManager(BSShopManager.class).getShops().values()){
List<BSBuy> items=new ArrayList<BSBuy>();
for(Integer pos : shop.getItems().keySet()){
BSBuy buy=shop.getItems().get(pos);
if(pos==null||buy==null) continue;
items.add(buy);
}
all.put(shop,items);
}
return all;
}
public HashMap<BSShop,List<BSBuy>> getAllShopItems(String config_option){
HashMap<BSShop,List<BSBuy>> all=new HashMap<BSShop,List<BSBuy>>();
for(BSShop shop : this.mPlugin.getManager(BSShopManager.class).getShops().values()){
List<BSBuy> items=new ArrayList<BSBuy>();
for(Integer pos : shop.getItems().keySet()){
BSBuy buy=shop.getItems().get(pos);
if(pos==null||buy==null) continue;
if(buy.getConfigurationSection().getBoolean(config_option)==false&&buy.getConfigurationSection().getInt(config_option)==0){
continue;
}
items.add(buy);
}
all.put(shop,items);
}
return all;
}
// Addon API
protected void addEnabledAddon(BossShopAddon addon){
Plugin addonplugin=Bukkit.getPluginManager().getPlugin(addon.getAddonName());
if(addonplugin==null){ return; }
if(enabled_addons==null){
enabled_addons=new ArrayList<BossShopAddon>();
}
if(enabled_addons.contains(addon)){ return; }
enabled_addons.add(addon);
}
public List<BossShopAddon> getEnabledAddons(){
return enabled_addons;
}
}

View File

@ -0,0 +1,93 @@
package org.black_ixx.bossshop.api;
import org.black_ixx.bossshop.BossShop;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
public abstract class BossShopAddon extends JavaPlugin{
private BossShop bs;
private boolean b=false;
@Override
public void onEnable(){
b=false;
Plugin plugin=Bukkit.getPluginManager().getPlugin("BossShop");
if(plugin==null){
printSevere("BossShop 未找到... 你需要它来运行 "+getAddonName()+"! Get it here: http://dev.bukkit.org/bukkit-plugins/bossshop/. Version v"+getRequiredBossShopVersion()+" or newer is required!");
printInfo("关闭附属...");
b=true;
Bukkit.getPluginManager().disablePlugin(this);
return;
}
bs=(BossShop)plugin;
double bs_worth=getWorth(bs.getDescription().getVersion());
double ao_worth=getWorth(getRequiredBossShopVersion());
if(bs_worth<ao_worth){
printSevere("BossShop was found but it seems to be outdated... you need v"+getRequiredBossShopVersion()+" or newer in order to run "+getAddonName()+"! Get it here: http://dev.bukkit.org/bukkit-plugins/bossshop/");
printInfo("Disabling Addon...");
b=true;
Bukkit.getPluginManager().disablePlugin(this);
return;
}
bs.getAPI().addEnabledAddon(this);
Bukkit.getLogger().info("[BossShop] Enabling Addon "+getAddonName());
enableAddon();
}
@Override
public void onDisable(){
if(b){ return; }
Bukkit.getLogger().info("[BossShop] Disabling Addon "+getAddonName());
disableAddon();
}
public void printSevere(String msg){
Bukkit.getLogger().severe("["+getAddonName()+"] "+msg);
}
public void printWarning(String msg){
Bukkit.getLogger().warning("["+getAddonName()+"] "+msg);
}
public void printInfo(String msg){
Bukkit.getLogger().info("["+getAddonName()+"] "+msg);
}
public final BossShop getBossShop(){
return bs;
}
protected double getWorth(String s){
try{
if(s==null||s==""||s.length()<1){ return 0; }
double x=0;
String[] parts=s.replace(".",":").split(":");
x+=Integer.parseInt(parts[0].trim());
if(parts.length==2){
x+=0.1*Integer.parseInt(parts[1].trim());
}
if(parts.length==3){
x+=0.1*Integer.parseInt(parts[1].trim());
x+=0.01*Integer.parseInt(parts[2].trim());
}
return x;
}catch(Exception e){
printWarning("Was not able to get the version of "+s);
return 1.00;
}
}
public abstract String getAddonName();
public abstract String getRequiredBossShopVersion();
public abstract void enableAddon();
public abstract void disableAddon();
public abstract void bossShopReloaded(CommandSender sender);
}

View File

@ -0,0 +1,181 @@
package org.black_ixx.bossshop.command;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.black_ixx.bossshop.BossShop;
import org.bukkit.command.CommandSender;
import cc.util.bossshop.Function;
/**
* @author 聪聪
*
*/
public abstract class ACommandBase{
public final static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm");
/**命令执行器*/
protected CommandExc mExector;
/**主插件*/
protected BossShop mPlugin;
/**主命令,包括斜杠*/
protected String mMainCmdLabel;
/**插件名,用于权限节点的生成*/
protected String mPluginName;
public ACommandBase(CommandExc pExector){
this.mExector=pExector;
this.mPlugin=pExector.getPlugin();
this.mMainCmdLabel=pExector.getLabel();
this.mPluginName=this.mPlugin.getPluginName();
}
/**
* 给玩家发送一条消息
* @return true
*/
public boolean send(CommandSender pSender,String pMsg){
this.mPlugin.send(pSender,pMsg);
return true;
}
/**
* 给玩家发送多条消息
* @return true
*/
public boolean send(CommandSender pSender,List<String> pMsgs){
for(String sMsg : pMsgs)
this.mPlugin.send(pSender,sMsg);
return true;
}
/**
* 翻译一个语言节点
*/
public String C(String node){
return this.mPlugin.getLangManager().getNode(node);
}
/**
* 发送该命令的帮助到指定的用户
* @param pSender 需要获取帮助的用户
* @return 永远为true
*/
public boolean help(CommandSender pSender){
ArrayList<String> chelp=getHelp(pSender,false);
if(chelp==null||chelp.isEmpty()){
send(pSender,this.C("Cmd.UnknowCommand"));
}else for(String ccc : chelp){
send(pSender,ccc);
}
return true;
}
/**
* 如果命令无法处理其子命令时调用,命令类名字的格式必须是Command***
* <p>
* 调用此函数的命令需要支持命令的子命令help<br />
* 最好在子命令条数大于2条或者帮助行数>=4行数调用此函数
* </p>
* @param pSender 命令发送者
* @param pLabel 未知的子命令标签,可以为null
* @return true
*/
public boolean unKnowChildCommand(CommandSender pSender,String pLabel){
ArrayList<String> helpList=this.getHelp(pSender,false);
if(helpList==null||helpList.isEmpty())
return send(pSender,this.C("Cmd.UnknowCommand"));
String cmdLabel=this.getClass().getSimpleName().substring(7).toLowerCase();
if(pLabel==null) pLabel="";
else pLabel="["+pLabel+"]";
return send(pSender,C("Cmd.unknowChildCommand")+pLabel+","+C("Word.Input")+"/BS "+cmdLabel+" help "+C("Cmd.GetHelp"));
}
public boolean noPermit(CommandSender sender){
return this.send(sender,this.C("Cmd.NoPermission"));
}
public boolean consoleNotAllow(CommandSender pSender){
return this.send(pSender,this.C("Cmd.ConsoleNotAllow"));
}
/**
* 获取该命令的标签
* <p>
* 默认使用类名第7位开始的小写字符串<br />
* 如果类名不足七位,将截取全部的小写字符串
* </p>
*/
public String getCommandLabel(){
String className=this.getClass().getSimpleName().toLowerCase();
if(className.length()>7) return className.substring(7);
else return className;
}
/**
* 默认为空,请确保不为null
* @param pArgs 玩家Tab的文字参数
*/
public ArrayList<String> getSubCommand(CommandSender pSender,String[] pArgs){
return new ArrayList<>();
}
/**
* 在按下Tab时,完成子命令提示
* <p>
* 此函数默认只处理子命令参数为1位的情况,如需处理多位,请重写方法
* </p>
* @param pSender Tab请求用户
* @param pArgs 已有的参数
*/
public ArrayList<String> onTabComplete(CommandSender pSender,String[] pArgs){
if(pArgs==null) return new ArrayList<>();
ArrayList<String> subLabels=this.getSubCommand(pSender, pArgs);
String lastParam=pArgs[pArgs.length-1];
if(StringUtils.isEmpty(lastParam)) return subLabels;
ArrayList<String> findTabs=new ArrayList<>();
Collection<String> findLabels=Function.getSamePrefixIgnoreCase(subLabels,lastParam,true);
if(findLabels.size()==0){
String findLabel=Function.getIgnoreCase(subLabels,lastParam);
if(findLabel!=null){
if(this.getMaxArgumentLength()>pArgs.length) findTabs.add(findLabel+" ");
else findTabs.add(findLabel);
}
}else if(findLabels.size()==1){
String findLabel=findLabels.toArray()[0].toString();
if(this.getMaxArgumentLength()>pArgs.length) findTabs.add(findLabel+" ");
else findTabs.add(findLabel);
}else findTabs.addAll(findLabels);
return findTabs;
}
/**
* 获取除去子命令自身的参数最大长度
* @return >=0
*/
public int getMaxArgumentLength(){
return 0;
}
/**
* 执行该命令
* @param pSender 命令的执行者
* @param pArgs 参数
* @return 执行成功与否(默认为true)
*/
public abstract boolean execute(CommandSender pSender,String[] pArgs);
/**
* 获取该命令的帮助的文本
* @param pAll true帮扩help帮助命令,false则排除
* @return 帮助文本的合集,如果没有帮助指令,集合为Empty
*/
public abstract ArrayList<String> getHelp(CommandSender pSender,boolean pAll);
}

View File

@ -0,0 +1,32 @@
package org.black_ixx.bossshop.command;
import java.util.ArrayList;
import org.bukkit.command.CommandSender;
public class CommandClear extends ACommandBase{
public CommandClear(CommandExc exector){
super(exector);
}
@Override
public boolean execute(CommandSender pSender,String[] pArgs){
if(pArgs.length!=1) return false;
if(!pSender.hasPermission(this.mPluginName+".status.clear")) return false;
int count=this.mExector.getPlugin().clearMemoryRecord();
return send(pSender,C("Cmd.ClearedModelStatus").replace("%numb%",count+""));
}
@Override
public ArrayList<String> getHelp(CommandSender pSender,boolean pAll){
ArrayList<String> tList=new ArrayList<>();
if(pSender.hasPermission(this.mPluginName+".status.clear")){
tList.add(this.mMainCmdLabel+" clear");
tList.add(C("Help.ClearModelStatus"));
}
return tList;
}
}

View File

@ -0,0 +1,57 @@
package org.black_ixx.bossshop.command;
import java.util.ArrayList;
import org.black_ixx.bossshop.core.BSShopHolder;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import cc.util.bossshop.FBukkit;
public class CommandClose extends ACommandBase{
public CommandClose(CommandExc exector){
super(exector);
}
@Override
public boolean execute(CommandSender pSender,String[] pArgs){
//bs close <player>
if(!pSender.hasPermission(this.mPluginName+".close.other")) return noPermit(pSender);
if(pArgs.length!=1) return help(pSender);
Player tPlayer=Bukkit.getPlayer(pArgs[0]);
if(tPlayer==null)
return send(pSender,C("Main.NoPlayerFound"));
if(!tPlayer.isOnline())
return send(pSender,C("Main.PlayerOffline"));
Inventory inv=tPlayer.getOpenInventory().getTopInventory();
if(!(inv.getHolder() instanceof BSShopHolder))
return send(pSender,C("Main.PlayerNotOpenBSShop"));
tPlayer.closeInventory();
return send(pSender,C("Main.AlreadyClosePlayerShop"));
}
@Override
public ArrayList<String> getHelp(CommandSender pSender,boolean pAll){
ArrayList<String> list=new ArrayList<>();
if(pSender.hasPermission(this.mPluginName+".close.other")){
list.add(this.mMainCmdLabel+" close <"+C("Word.PlayerName")+">");
list.add(C("Help.ClosePlayerShop"));
}
return list;
}
@Override
public ArrayList<String> getSubCommand(CommandSender pSender,String[] pArgs){
return FBukkit.getOnlinePlayersName();
}
@Override
public int getMaxArgumentLength(){
return 1;
}
}

View File

@ -0,0 +1,181 @@
package org.black_ixx.bossshop.command;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.apache.commons.lang.StringUtils;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSShopManager;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.TabCompleter;
import cc.util.bossshop.Function;
public class CommandExc implements CommandExecutor,TabCompleter{
private final Map<String,ACommandBase> mCommands=new LinkedHashMap<>();
private final String mPluginCmdLabel="/shop";
private BossShop mPlugin;
/**
* 必须在配置文件启用后才能调用此方法
* @param pPlugin
*/
public CommandExc(BossShop pPlugin){
this.mPlugin=pPlugin;
//绑定执行器
PluginCommand tCmd=null;
for(String sMainCmd : this.mPlugin.getDescription().getCommands().keySet()){
if((tCmd=this.mPlugin.getCommand(sMainCmd))!=null){
tCmd.setExecutor(this);
tCmd.setTabCompleter(this);
}
}
//注册子命令
this.register("clear",new CommandClear(this));
this.register("close",new CommandClose(this));
this.register("help",new CommandHelp(this));
this.register("name",new CommandName(this));
this.register("mail",new CommandMail(this));
this.register("nbt",new CommandNBT(this));
this.register("open",new CommandOpen(this));
this.register("reload",new CommandReload(this));
this.register("sale",new CommandSale(this));
this.register("unsale",new CommandUnsale(this));
}
/**获取主插件实例*/
public BossShop getPlugin(){
return this.mPlugin;
}
/**获取主命令标签,包括斜杠*/
public String getLabel(){
return this.mPluginCmdLabel;
}
/**获取命令标签Set集合的拷贝*/
public Set<String> keySet(){
HashSet<String> cmdLabels=new HashSet<>();
cmdLabels.addAll(this.mCommands.keySet());
return cmdLabels;
}
/**
* 根据标签名获取子命令,忽略标签大小写
*/
public ACommandBase getCommand(String pLabel){
for(Entry<String,ACommandBase> sEntry : this.mCommands.entrySet()){
if(sEntry.getKey().equalsIgnoreCase(pLabel)) return sEntry.getValue();
}
return null;
}
/**
* 根据标类获取子命令
*/
public ACommandBase getCommand(Class<? extends ACommandBase> pClazz){
for(ACommandBase scmd : this.mCommands.values()){
if(scmd.getClass()==pClazz) return scmd;
}
return null;
}
/**
* 注册指令到指令列表中
* @param pLabel 指令标签
* @param pCmd 指令实例
*/
public ACommandBase register(String pLabel,ACommandBase pCmd){
return this.mCommands.put(pLabel==null?null:pLabel.toLowerCase(),pCmd);
}
/**
* 更改命令模块的标签名
* @param pCmdClazz 命令模块类
* @param pNewLabel 新的名字
* @return 是否成功
*/
@Deprecated
public boolean replaceLabel(Class<? extends ACommandBase> pCmdClazz,String pNewLabel){
if(StringUtils.isBlank(pNewLabel)) return false;
pNewLabel=pNewLabel.toLowerCase();
if(this.mCommands.get(pNewLabel)!=null) return false;
for(Map.Entry<String,ACommandBase> tCmdEntry : this.mCommands.entrySet()){
if(pCmdClazz.isInstance(tCmdEntry.getValue())){
this.mCommands.put(pNewLabel,this.mCommands.remove(tCmdEntry.getKey()));
return true;
}
}
return false;
}
@Override
public boolean onCommand(CommandSender pSender,Command command,String pLabel,String[] pArgs){
try{
String cmdLabel=this.mPlugin.getConfigManager().getMainShop();
if(pArgs.length>0) cmdLabel=pArgs[0];
ACommandBase cmd=this.getCommand(cmdLabel);
if(cmd!=null){
if(pArgs.length>0) pArgs=Arrays.copyOfRange(pArgs,1,pArgs.length);
return cmd.execute(pSender,pArgs);
}else{
if(this.mPlugin.getManager(BSShopManager.class).getShop(cmdLabel)!=null)
this.getCommand(CommandOpen.class).execute(pSender,new String[]{cmdLabel});
else return this.mPlugin.send(pSender,this.mPlugin.C("Cmd.UnknowCommand"));
}
}catch(Throwable exp){
this.mPlugin.severe(this.mPlugin.C("Cmd.ErrorHappedWhenHandlerCmd")+exp.getMessage(),exp);
this.mPlugin.send(pSender,this.mPlugin.C("Main.ErrorHappend"));
}
return true;
}
/**
* Tab命令自动补全
* <p>
* 会首先检查 插件名.cmdcomplete权限,如果不存在直接返回</br>
* </p>
* @return
*/
public List<String> onTabComplete(CommandSender pSender,Command pCmd,String pStr,String[] pArgs){
if(!pSender.hasPermission(this.mPlugin.getPluginName()+".cmdcomplete")) return null;
ArrayList<String> list=new ArrayList<>();
if(pArgs.length==0){
list.addAll(this.mCommands.keySet());
}else if(pArgs.length==1){
Collection<String> samePrefixTabs=Function.getSamePrefixIgnoreCase(this.mCommands.keySet(),pArgs[0],true);
if(samePrefixTabs.size()==0){
String findTab=Function.getIgnoreCase(this.mCommands.keySet(),pArgs[0]);
if(findTab!=null){
if(this.getCommand(findTab).getMaxArgumentLength()>0) list.add(findTab+" ");
else list.add(findTab);
}
}else if(samePrefixTabs.size()==1){
String findTab=samePrefixTabs.toArray()[0].toString();
if(this.getCommand(findTab).getMaxArgumentLength()>0) list.add(findTab+" ");
else list.add(findTab);
}else list.addAll(samePrefixTabs);
}else{
ACommandBase tCmd=this.getCommand(pArgs[0]);
if(tCmd!=null&&tCmd.getMaxArgumentLength()>0) list.addAll(tCmd.onTabComplete(pSender,Arrays.copyOfRange(pArgs,1,pArgs.length)));
}
// this.mPlugin.send(pSender,"Tab输入:"+Function.asList(pArgs));
// this.mPlugin.send(pSender,"Tab返回:"+list);
return list;
}
public void reload(){}
}

View File

@ -0,0 +1,55 @@
package org.black_ixx.bossshop.command;
import java.util.ArrayList;
import org.bukkit.command.CommandSender;
public class CommandHelp extends ACommandBase{
public CommandHelp(CommandExc exector){
super(exector);
}
@Override
public boolean execute(CommandSender sender,String[] args){
if(!sender.hasPermission(this.mPluginName+".help")) return noPermit(sender);
int page=1;
if(args.length==1){
try{
page=Integer.parseInt(args[0]);
}catch(NumberFormatException nfexp){
page=1;
}
}
ArrayList<String> tt=this.getHelp(sender,true);
int page_numb=tt.size()%10==0?tt.size()/10:tt.size()/10+1;
if(page<1||page>page_numb) page=1;
send(sender,"================("+page+"/"+page_numb+")===============");
for(int i=(page-1)*10;(i<(page*10))&&(i<tt.size());i++){
send(sender,tt.get(i));
}
return true;
}
@Override
public boolean help(CommandSender sender){
return true;
}
@Override
public ArrayList<String> getHelp(CommandSender sender,boolean pAll){
ArrayList<String> list=new ArrayList<>();
if(sender.hasPermission(this.mPluginName+".help")){
for(String label : this.mExector.keySet()){
ACommandBase cmd=this.mExector.getCommand(label);
if(cmd==this) continue;
ArrayList<String> helplist=cmd.getHelp(sender,true);
if(helplist==null) throw new IllegalArgumentException("命令模块的帮助结果为null,请联系作者完善代码");
list.addAll(helplist);
}
}
return list;
}
}

View File

@ -0,0 +1,147 @@
package org.black_ixx.bossshop.command;
import java.util.ArrayList;
import org.black_ixx.bossshop.mail.MailManager;
import org.black_ixx.bossshop.managers.WorthHandler;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public class CommandMail extends ACommandBase{
private MailManager mMailMan;
private final ArrayList<String> mSubCommand=new ArrayList<>();
public CommandMail(CommandExc exector){
super(exector);
this.mSubCommand.add("check");
this.mSubCommand.add("help");
this.mSubCommand.add("recive");
this.mSubCommand.add("send");
}
@Override
public boolean execute(CommandSender pSender,String[] pArgs){
if(!(pSender instanceof Player))
return consoleNotAllow(pSender);
Player tPlayer=(Player)pSender;
String cmdLabel="help";
if(pArgs.length>0) cmdLabel=pArgs[0];
if(cmdLabel.equalsIgnoreCase("check")){
if(!tPlayer.hasPermission(this.mPluginName+".mail.check"))
return noPermit(pSender);
return this.checkMail(tPlayer,pArgs);
}else if(cmdLabel.equalsIgnoreCase("recive")){
if(!tPlayer.hasPermission(this.mPluginName+".mail.recive"))
return noPermit(pSender);
return this.reciveMial(tPlayer,pArgs);
}else if(cmdLabel.equalsIgnoreCase("send")){
if(!tPlayer.hasPermission(this.mPluginName+".mail.send"))
return noPermit(pSender);
return this.sendMail(tPlayer,pArgs);
}
// else if(cmdLabel.equalsIgnoreCase("undo")){
// if(!tPlayer.hasPermission("BossShop.mail.undo"))
// return noPermit(pSender);
// return this.undoMail(tPlayer,pArgs);
// }
else if(cmdLabel.equalsIgnoreCase("help")){
if(!tPlayer.hasPermission("BossShop.mail.help"))
return noPermit(pSender);
return help(pSender);
}else return unKnowChildCommand(pSender,cmdLabel);
}
private MailManager getMailManager(){
if(this.mMailMan==null)
this.mMailMan=this.mPlugin.getManager(MailManager.class);
return this.mMailMan;
}
public boolean checkMail(Player tPlayer,String[] pArgs){
ArrayList<String> list=this.getMailManager().checkMail(tPlayer.getUniqueId());
for(String smsg : list) send(tPlayer,smsg);
return true;
}
public boolean reciveMial(Player tPlayer,String[] pArgs){
if(this.getMailManager().getMailCount(tPlayer.getUniqueId())<=0)
return send(tPlayer,C("Mail.YouHaveNoMail"));
this.getMailManager().reciveMail(tPlayer);
return true;
}
public boolean undoMail(Player tPlayer,String[] pArgs){
return false;
}
public boolean sendMail(Player tPlayer,String[] pArgs){
// if(pArgs.length!=2) return help(tPlayer);
// ArrayList<Player> tBeSernders=new ArrayList<>();
// if(pArgs[1].equals("*")){
// if(!tPlayer.hasPermission("BossShop.mail.send.all")) return noPermit(tPlayer);
// for(Player sPlayer : FBukkit.getOnlinePlayers()){
//
// }
// }
// String[] tTargets=pArgs[1].split(",");
Player tTarget=Bukkit.getPlayer(pArgs[1]);
if(tTarget==null)
return send(tPlayer,C("Main.NoPlayerFound")+"["+pArgs[1]+"]");
if(pArgs[1].equalsIgnoreCase(tPlayer.getName())&&!tPlayer.isOp())
return send(tPlayer,C("Mail.YouCannotSendMailToYouSelf"));
MailManager tMailM=this.getMailManager();
if(tMailM.isMailFull(tTarget.getUniqueId()))
return send(tPlayer,C("Mail.PlayerMailIsFull").replace("%player%",tTarget.getName()));
ItemStack tItem=tPlayer.getItemInHand();
if(tItem==null||tItem.getType()==Material.AIR)
return send(tPlayer,C("Cmd.YouShouldTakeItemInHand"));
int tCost=tMailM.getMailSendCost();
WorthHandler wHandler=this.mPlugin.getManager(WorthHandler.class);
if(tCost>0){
if(!wHandler.hasMoney(tPlayer,tCost))
return send(tPlayer,C("YouNeed%%MoneyToSendMail").replace("%numb%",tCost+""));
else wHandler.takeMoney(tPlayer,tCost);
}
tMailM.addMail(tPlayer,tTarget,tItem);
tPlayer.setItemInHand(null);
return send(tPlayer,C("Mail.MailHasSend"));
}
@Override
public ArrayList<String> getHelp(CommandSender pSender,boolean pAll){
ArrayList<String> list=new ArrayList<>();
if(pAll&&pSender.hasPermission("BossShop.mail.help")){
list.add(this.mMainCmdLabel+" mail [help]");
list.add(C("Help.MailHelp"));
}
if(pSender.hasPermission("BossShop.mail.check")){
list.add(this.mMainCmdLabel+" mail check");
list.add(C("Help.MailCheck"));
}
if(pSender.hasPermission("BossShop.mail.recive")){
list.add(this.mMainCmdLabel+" mail recive");
list.add(C("Help.MailRevice"));
}
if(pSender.hasPermission("BossShop.mail.send")){
list.add(this.mMainCmdLabel+" mail send <"+C("Word.PlayerName")+">");
list.add(C("Help.MailSend"));
}
return list;
}
@Override
public ArrayList<String> getSubCommand(CommandSender pSender,String[] pArgs){
return this.mSubCommand;
}
@Override
public int getMaxArgumentLength(){
return 1;
}
}

View File

@ -0,0 +1,98 @@
package org.black_ixx.bossshop.command;
import java.util.ArrayList;
import org.black_ixx.bossshop.nbt.NBT;
import org.black_ixx.bossshop.nbt.NBTEditManager;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public class CommandNBT extends ACommandBase{
private final ArrayList<String> mSubCommand=new ArrayList<>();
public CommandNBT(CommandExc exector){
super(exector);
this.mSubCommand.add("add");
this.mSubCommand.add("clear");
this.mSubCommand.add("help");
}
@Override
public boolean execute(CommandSender pSender,String[] pArgs){
String label="help";
if(pArgs.length>0) label=pArgs[0];
if(label.equalsIgnoreCase("add")){
if(!pSender.hasPermission(this.mPluginName+".nbt.add"))
return noPermit(pSender);
if(!(pSender instanceof Player))
return this.consoleNotAllow(pSender);
return this.add((Player)pSender,pArgs);
}else if(label.equalsIgnoreCase("clear")){
if(!pSender.hasPermission(this.mPluginName+".nbt.clear"))
return noPermit(pSender);
return this.clear(pSender,pArgs);
}else if(label.equalsIgnoreCase("help")){
if(!pSender.hasPermission(this.mPluginName+".nbt.help"))
return noPermit(pSender);
return help(pSender);
}else return unKnowChildCommand(pSender,label);
}
@Override
public ArrayList<String> getHelp(CommandSender sender,boolean pAll){
ArrayList<String> list=new ArrayList<>();
if(pAll&&sender.hasPermission(this.mPluginName+".nbt.help")){
list.add(this.mMainCmdLabel+" nbt [help]");
list.add(this.C("Help.NBTHelp"));
}
if(sender.hasPermission(this.mPluginName+".nbt.add")){
list.add(this.mMainCmdLabel+" nbt add");
list.add(this.C("Help.NBTAdd"));
}
if(sender.hasPermission(this.mPluginName+".nbt.clear")){
list.add(this.mMainCmdLabel+" nbt clear");
list.add(this.C("Help.NBTClear"));
}
return list;
}
private boolean add(Player pPlayer,String args[]){
if(args.length!=1) return this.help(pPlayer);
ItemStack item=pPlayer.getItemInHand();
if(item==null||item.getType()==Material.AIR){
this.send(pPlayer,this.C("Cmd.YouShouldTakeItemInHand"));
return true;
}
NBTEditManager NBTMan=this.mPlugin.getManager(NBTEditManager.class);
NBT tNBT=NBTMan.getNBTByItem(item);
if(tNBT!=null){
this.send(pPlayer,this.C("Cmd.NBTHasExistInStockAndItsID")+tNBT.mLabel);
return true;
}
String label=NBTMan.addItemNBTToStock(item,false);
if(label==null) this.send(pPlayer,this.C("Cmd.ItemMayDonotHaveNBT"));
else this.send(pPlayer,this.C("Cmd.NBTHaveAddAndItsID")+label);
return true;
}
private boolean clear(CommandSender sender,String args[]){
if(args.length!=1) return this.help(sender);
int count=this.mPlugin.getManager(NBTEditManager.class).clearNBT();
return this.send(sender,this.C("Cmd.ClearedNoUsefulNBT").replace("%numb%",count+""));
}
@Override
public ArrayList<String> getSubCommand(CommandSender pSender,String[] pArgs){
return this.mSubCommand;
}
@Override
public int getMaxArgumentLength(){
return 1;
}
}

View File

@ -0,0 +1,52 @@
package org.black_ixx.bossshop.command;
import java.util.ArrayList;
import org.black_ixx.bossshop.managers.ItemNameManager;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public class CommandName extends ACommandBase{
private final ArrayList<String> mSubCommand=new ArrayList<>();
public CommandName(CommandExc exector){
super(exector);
this.mSubCommand.add("key");
}
@Override
public boolean execute(CommandSender pSender,String[] pArgs){
if(!pSender.isOp()) return true;
if(!(pSender instanceof Player))
return consoleNotAllow(pSender);
Player tPlayer=(Player)pSender;
ItemStack inHandItem=tPlayer.getItemInHand();
if(inHandItem==null||inHandItem.getType()==Material.AIR)
return send(pSender,this.C("Cmd.YouShouldTakeItemInHand"));
if(pArgs.length==0)
return send(pSender,">"+this.mPlugin.getManager(ItemNameManager.class).getDisPlayName(inHandItem));
else if(pArgs[0].equalsIgnoreCase("key"))
return send(pSender,">"+this.mPlugin.getManager(ItemNameManager.class).getUnlocalizedName(inHandItem));
else return true;
}
@Override
public ArrayList<String> getHelp(CommandSender pSender,boolean pAll){
return new ArrayList<>();
}
@Override
public ArrayList<String> getSubCommand(CommandSender pSender,String[] pArgs){
return this.mSubCommand;
}
@Override
public int getMaxArgumentLength(){
return 1;
}
}

View File

@ -0,0 +1,110 @@
package org.black_ixx.bossshop.command;
import java.util.ArrayList;
import org.black_ixx.bossshop.core.BSShop;
import org.black_ixx.bossshop.core.BSShopManager;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import cc.util.bossshop.FBukkit;
public class CommandOpen extends ACommandBase{
public CommandOpen(CommandExc exector){
super(exector);
}
@Override
public boolean execute(CommandSender pSender,String[] args){
BSShopManager shopMan=this.mPlugin.getManager(BSShopManager.class);
if(args.length==1){
if(args[0].equalsIgnoreCase("help")){
if(!pSender.hasPermission(this.mPluginName+".open.help"))
return noPermit(pSender);
return help(pSender);
}
if(!pSender.hasPermission(this.mPluginName+".open.command"))
return this.noPermit(pSender);
if(!(pSender instanceof Player))
return this.consoleNotAllow(pSender);
Player tPlayer=(Player)pSender;
BSShop tshop=shopMan.getShop(args[0]);
if(tshop==null) return this.send(pSender,this.C("Cmd.NoShopFound")+" ["+args[0]+"]");
this.openShop(tPlayer,tshop);
}else if(args.length==2){
Player tPlayer=Bukkit.getPlayer(args[0]);
if(tPlayer==null)
return this.send(pSender,this.C("Cmd.NoPlayerFound")+" ["+args[0]+"]");
boolean self=pSender.getName().equalsIgnoreCase(args[0]);
if(!self&&!pSender.hasPermission("BossShop.open.other"))
return this.noPermit(pSender);
if(!pSender.hasPermission(this.mPluginName+".open.command"))
return this.noPermit(pSender);
BSShop tshop=shopMan.getShop(args[1]);
if(tshop==null)
return this.send(pSender,this.C("Cmd.NoShopFound")+" ["+args[1]+"]");
this.openShop(tPlayer,tshop);
if(!self) this.send(pSender,this.C("Cmd.OpenShopForPlayer").replace("%player%",tPlayer.getName().replace("%shop%",tshop.getShopName())));
}
else return unKnowChildCommand(pSender,null);
return true;
}
@Override
public ArrayList<String> getHelp(CommandSender sender,boolean pAll){
ArrayList<String> list=new ArrayList<>();
if(pAll&&sender.hasPermission(this.mPluginName+".open.help")){
list.add(this.mMainCmdLabel+" open [help]");
list.add(this.C("Help.HelpOpen"));
}
if(sender.hasPermission(this.mPluginName+".open.command")){
list.add(this.mMainCmdLabel+" [open] ["+C("Word.ShopName")+"]");
list.add(this.C("Help.OpenShop"));
}
if(sender.hasPermission(this.mPluginName+".open.other")){
list.add(this.mMainCmdLabel+" open <"+C("Word.PlayerName")+"> <"+C("Word.ShopName")+">");
list.add(this.C("Help.OpenOtherShop"));
}
return list;
}
private void openShop(final Player pPlayer,final BSShop pShop){
int tDelay=this.mPlugin.getConfigManager().getShopOpenDelay();
final BSShopManager shopMan=this.mPlugin.getManager(BSShopManager.class);
if(tDelay<=0){
shopMan.openShop(pPlayer,pShop);
}
else Bukkit.getScheduler().scheduleSyncDelayedTask(this.mPlugin,new Runnable(){
@Override
public void run(){
shopMan.openShop(pPlayer,pShop);
}
},tDelay);
}
@Override
public ArrayList<String> getSubCommand(CommandSender pSender,String[] pArgs){
ArrayList<String> mayCmd=new ArrayList<>();
switch(pArgs.length){
case 1:
mayCmd.addAll(this.mPlugin.getManager(BSShopManager.class).getShops().keySet());
mayCmd.addAll(FBukkit.getOnlinePlayersName());
return mayCmd;
case 2:
mayCmd.addAll(this.mPlugin.getManager(BSShopManager.class).getShops().keySet());
return mayCmd;
}
return super.getSubCommand(pSender, pArgs);
}
@Override
public int getMaxArgumentLength(){
return 2;
}
}

View File

@ -0,0 +1,104 @@
package org.black_ixx.bossshop.command;
import java.util.ArrayList;
import org.black_ixx.bossshop.core.BSShop;
import org.black_ixx.bossshop.core.BSShopManager;
import org.bukkit.command.CommandSender;
public class CommandReload extends ACommandBase{
private final ArrayList<String> mSubCommand=new ArrayList<>();
public CommandReload(CommandExc exector){
super(exector);
this.mSubCommand.add("all");
this.mSubCommand.add("config");
this.mSubCommand.add("help");
this.mSubCommand.add("lang");
this.mSubCommand.add("shop");
}
@Override
public boolean execute(CommandSender pSender,String[] pArgs){
String cmdLabel="all";
if(pArgs.length>0) cmdLabel=pArgs[0];
if(cmdLabel.equalsIgnoreCase("all")){
if(!pSender.hasPermission(this.mPluginName+".reload.all"))
return noPermit(pSender);
this.mPlugin.reloadPlugin();
return send(pSender,this.C("Cmd.PluginReloaded"));
}else if(cmdLabel.equalsIgnoreCase("config")){
if(!pSender.hasPermission(this.mPluginName+".reload.config"))
return noPermit(pSender);
this.mPlugin.reloadConfig();
return send(pSender,this.C("Cmd.ConfigReloacded"));
}else if(cmdLabel.equalsIgnoreCase("help")){
if(!pSender.hasPermission(this.mPluginName+".reload.help"))
return noPermit(pSender);
return help(pSender);
}else if(cmdLabel.equalsIgnoreCase("lang")){
if(!pSender.hasPermission(this.mPluginName+".reload.lang"))
return noPermit(pSender);
this.mPlugin.getLangManager().reloadConfig();
return send(pSender,this.C("Cmd.LangReloacded"));
}if(cmdLabel.equalsIgnoreCase("shop")){
if(!pSender.hasPermission(this.mPluginName+".reload.shop"))
return noPermit(pSender);
return this.reloadShop(pSender,pArgs);
}else return unKnowChildCommand(pSender,cmdLabel);
}
@Override
public ArrayList<String> getHelp(CommandSender sender,boolean pAll){
ArrayList<String> list=new ArrayList<>();
if(pAll&&sender.hasPermission(this.mPluginName+".reload.help")){
list.add(this.mMainCmdLabel+" reload help");
list.add(this.C("Help.ReloadHelp"));
}
if(sender.hasPermission(this.mPluginName+".reload.all")){
list.add(this.mMainCmdLabel+" reload [all]");
list.add(this.C("Help.Reload"));
}
if(sender.hasPermission(this.mPluginName+".reload.config")){
list.add(this.mMainCmdLabel+" reload config");
list.add(this.C("Help.ReloadConfig"));
}
if(sender.hasPermission(this.mPluginName+".reload.lang")){
list.add(this.mMainCmdLabel+" reload lang");
list.add(this.C("Help.ReloadLang"));
}
if(sender.hasPermission(this.mPluginName+".reload.shop")){
list.add(this.mMainCmdLabel+" reload shop ["+C("Word.ShopName")+"]");
list.add(this.C("Help.ReloadShop"));
}
return list;
}
private boolean reloadShop(CommandSender pSender,String[] pArgs){
BSShopManager shopMan=this.mPlugin.getManager(BSShopManager.class);
if(pArgs.length==1){
shopMan.reloadConfig();
return send(pSender,C("Cmd.AlreadyReloadShop").replace("%shop%",C("Word.All")));
}else if(pArgs.length==2){
BSShop tShop=shopMan.getShop(pArgs[1]);
if(tShop==null)
return send(pSender,C("Cmd.NoShopFound")+"["+pArgs[1]+"]");
if(!tShop.reloadShop())
shopMan.removeShop(tShop);
tShop.updateAllInventory();
return send(pSender,C("Cmd.AlreadyReloadShop").replace("%shop%",tShop.getShopName()));
}else return help(pSender);
}
@Override
public ArrayList<String> getSubCommand(CommandSender pSender,String[] pArgs){
return this.mSubCommand;
}
@Override
public int getMaxArgumentLength(){
return 1;
}
}

View File

@ -0,0 +1,103 @@
package org.black_ixx.bossshop.command;
import java.util.ArrayList;
import org.black_ixx.bossshop.sale.SaleManager;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class CommandSale extends ACommandBase{
private final ArrayList<String> mSubCommand=new ArrayList<>();
public CommandSale(CommandExc exector){
super(exector);
this.mSubCommand.add("start");
this.mSubCommand.add("stop");
this.mSubCommand.add("item");
this.mSubCommand.add("money");
this.mSubCommand.add("points");
}
@Override
public boolean execute(CommandSender pSender,String[] pArgs){
if(!pSender.hasPermission(this.mPluginName+".sale.forsale"))
return noPermit(pSender);
if(!(pSender instanceof Player))
return this.consoleNotAllow(pSender);
Player tPlayer=(Player)pSender;
if(pArgs.length<=1){
String label="help";
if(pArgs.length==1) label=pArgs[0];
if(label.equalsIgnoreCase("help"))
return help(pSender);
else if(label.equalsIgnoreCase("start")){
this.mPlugin.getSaleListener().startSaleListenrer(tPlayer);
return true;
}else if(label.equalsIgnoreCase("stop")){
this.mPlugin.getSaleListener().stopSaleListenrer(tPlayer);
return true;
}else return unKnowChildCommand(pSender,label);
}
else if(pArgs.length==5){
this.mPlugin.getManager(SaleManager.class).sale((Player)pSender,pArgs);
return true;
}
return this.help(pSender);
}
@Override
public ArrayList<String> getHelp(CommandSender sender,boolean pAll){
ArrayList<String> list=new ArrayList<>();
if(sender.hasPermission(this.mPluginName+".sale.forsale")){
if(pAll){
list.add("/BossShop sale [help]");
list.add(this.C("Help.SaleHelp"));
}
// /BossShop sale start
list.add(this.mMainCmdLabel+" sale start");
list.add(this.C("Help.StartSaleWithChat"));
// /BossShop sale start
list.add(this.mMainCmdLabel+" sale stop");
list.add(this.C("Help.StopSaleWithChat"));
// /BossShop sale <售卖类型> <单次数量> <份数> <价格类型> <价格>
list.add(this.mMainCmdLabel+" sale <"+C("Word.SellType")+"> <"+C("Word.SigleNumb")+"> <"+C("Word.PartNumb")+"> <"+C("Word.PriceType")+"> <"+C("Word.Price")+">");
list.add(this.C("Help.SaleForsale"));
list.add(this.C("Help.SaleSellType"));
list.add(this.C("Help.SalePriceType"));
list.add(this.C("Help.SaleOther"));
}
return list;
}
@Override
public ArrayList<String> getSubCommand(CommandSender pSender,String[] pArgs){
ArrayList<String> mayCmd=new ArrayList<>();
switch(pArgs.length){
case 1:
return this.mSubCommand;
case 2:
mayCmd.add("1");
mayCmd.add("10");
mayCmd.add("64");
return mayCmd;
case 3:
mayCmd.add("1");
mayCmd.add("10");
return mayCmd;
case 4:
mayCmd.add("money");
mayCmd.add("points");
return mayCmd;
case 5:
return mayCmd;
}
return this.mSubCommand;
}
@Override
public int getMaxArgumentLength(){
return 5;
}
}

View File

@ -0,0 +1,81 @@
package org.black_ixx.bossshop.command;
import java.util.ArrayList;
import org.black_ixx.bossshop.core.BSBuy;
import org.black_ixx.bossshop.mail.MailManager;
import org.black_ixx.bossshop.managers.RecordManager;
import org.black_ixx.bossshop.managers.WorthHandler;
import org.black_ixx.bossshop.sale.SaleManager;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class CommandUnsale extends ACommandBase{
public CommandUnsale(CommandExc exector){
super(exector);
}
@Override
public boolean execute(CommandSender pSender,String[] pArgs){
if(!pSender.hasPermission(this.mPluginName+".unsale.user"))
return noPermit(pSender);
if(pArgs.length!=1) return help(pSender);
SaleManager tSaleM=this.mPlugin.getManager(SaleManager.class);
BSBuy tBuy=tSaleM.getSaleItem(pArgs[0]);
if(tBuy==null)
return send(pSender,C("Main.NoSaleItemFound")+"["+pArgs[0]+"]");
boolean op=pSender.hasPermission(this.mPluginName+".unsale.admin");
if(pSender instanceof Player){
Player tPlayer=(Player)pSender;
if(!tBuy.getOwner().equals(tPlayer.getUniqueId())&&!op)
return send(pSender,C("Main.YouCannotUnsaleOther"));
if(!op){
RecordManager recordMan=this.mPlugin.getManager(RecordManager.class);
int tCount=recordMan.getUnsaleRecord(tPlayer.getUniqueId());
int tMaxCount=tSaleM.getUnsaleCount();
if(tCount>=tMaxCount)
return send(pSender,C("Main.YouTodayCannotUnsaleMore"));
int tCost=tSaleM.getUnSaleCost();
WorthHandler wHandler=this.mPlugin.getManager(WorthHandler.class);
if(tCost>0){
if(!wHandler.hasMoney(tPlayer,tCost))
return send(pSender,C("Main.YouNeed%%MoneyToUnsale").replace("%numb%",tCost+""));
wHandler.takeMoney(tPlayer,tCost);
}
recordMan.addUnsaleRecord(tPlayer.getUniqueId());
}
}
tBuy.getShop().removeItem(tBuy.getName(),true);
this.mPlugin.getManager(MailManager.class).addMail(tBuy,C("Main.FromHandUnsale"));
return send(pSender,C("Main.SuccessUnsaleItem")+"["+tBuy.getName()+"]");
}
@Override
public ArrayList<String> getHelp(CommandSender pSender,boolean pAll){
ArrayList<String> list=new ArrayList<>();
if(pSender.hasPermission(this.mPluginName+".unsale.user")||pSender.hasPermission(this.mPluginName+".unsale.admin")){
list.add(this.mMainCmdLabel+" unsale <"+C("Word.SaleID")+">");
list.add(C("Help.Unsale"));
}
return list;
}
@Override
public ArrayList<String> getSubCommand(CommandSender pSender,String[] pArgs){
ArrayList<String> allSale=new ArrayList<>();
if(pSender.hasPermission(this.mPluginName+".unsale.admin")){
allSale.addAll(this.mPlugin.getManager(SaleManager.class).getSaleItemsName());
}else if(pSender.hasPermission(this.mPluginName+".unsale.user")&&pSender instanceof Player){
allSale.addAll(this.mPlugin.getManager(SaleManager.class).getSaleItemsName((Player)pSender));
}
return allSale;
}
@Override
public int getMaxArgumentLength(){
return 1;
}
}

View File

@ -0,0 +1,657 @@
package org.black_ixx.bossshop.core;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import org.apache.commons.lang.StringUtils;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSEnums.BSBuyType;
import org.black_ixx.bossshop.core.BSEnums.BSPriceType;
import org.black_ixx.bossshop.events.BSPlayerPurchaseEvent;
import org.black_ixx.bossshop.events.BSPlayerPurchasedEvent;
import org.black_ixx.bossshop.lottery.LotteryHolder;
import org.black_ixx.bossshop.lottery.LotteryStatus;
import org.black_ixx.bossshop.mail.MailManager;
import org.black_ixx.bossshop.managers.ItemStackChecker;
import org.black_ixx.bossshop.managers.MultiplierHandler;
import org.black_ixx.bossshop.managers.RecordManager;
import org.black_ixx.bossshop.managers.ShopCustomizer;
import org.black_ixx.bossshop.managers.StringManager;
import org.black_ixx.bossshop.managers.TransactionLog;
import org.black_ixx.bossshop.managers.VaultHandler;
import org.black_ixx.bossshop.managers.WorthHandler;
import org.black_ixx.bossshop.misc.Enchant;
import org.black_ixx.bossshop.nbt.NBTEditManager;
import org.black_ixx.bossshop.sale.SaleManager;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import cc.util.bossshop.JsonExtra;
import cc.util.bossshop.NMSHelper;
import cc.util.bossshop.JsonExtra.ClickAction;
import cc.util.bossshop.JsonExtra.Color;
import cc.util.bossshop.JsonExtra.HoverAction;
import cc.util.bossshop.JsonExtra.Style;
public class BSBuy{
private BossShop mPlugin;
private int numberLimit=-1;
private int personalLimit=-1;
private int mLocation;
private int mWeight=0;
private int mHideItemFlag=0;
private boolean perm_is_group=false;
private boolean mHideNoStock=false;
private boolean mHideNotTime=false;
private String permission;
private String mName;
private String mMsg="undefine";
private UUID owner=null;
private Object mReward=null;
private Object mPrice=null;
private Date stopTime=null;
private Date startTime=null;
private BSShop mShop=null;
private BSPriceType priceT=null;
private BSBuyType buyT=null;
private boolean mNeedEdit=true;
public BSBuy(BossShop pPlugin,BSBuyParameter parameter){
this.mPlugin=pPlugin;
this.mShop=parameter.shop;
this.priceT=parameter.priceT;
this.buyT=parameter.buyT;
this.mReward=parameter.reward;
this.mPrice=parameter.price;
this.mName=parameter.name;
this.mMsg=transformMessage(parameter.msg);
this.owner=parameter.owner;
this.mLocation=parameter.location;
this.numberLimit=parameter.numberLimit;
this.personalLimit=parameter.personalLimit;
this.startTime=parameter.startTime;
this.stopTime=parameter.stopTime;
this.mHideNoStock=parameter.hideNoStock;
this.mHideNotTime=parameter.hideNotTime;
this.mHideItemFlag=parameter.hideItemFlag & 0xFFFFFFFF;
this.mWeight=parameter.weight;
if(StringUtils.isNotEmpty(parameter.permission)){
permission=parameter.permission;
if(permission.startsWith("[")&&permission.endsWith("]")&&permission.length()>2){
String group=permission.substring(1,permission.length()-1);
if(group!=null){
this.permission=group;
perm_is_group=true;
}
}
}
}
public int getWeight(){
return this.mWeight;
}
/**
* 如果为null,则使用默认
* @return
*/
public int getHideItemFlag(){
return this.mHideItemFlag;
}
/**
* 获取该商品的所有者,如果不存在则为null
* @return
*/
public UUID getOwner(){
return this.owner;
}
public boolean hasOwner(){
return this.owner!=null;
}
public BSBuyType getBuyType(){
return buyT;
}
public BSPriceType getPriceType(){
return priceT;
}
public boolean isHideNoStock(){
return this.mHideNoStock;
}
public boolean isHideNotTime(){
return this.mHideNotTime;
}
public String getShopName(){
return this.mShop.getShopName();
}
public BSShop getShop(){
return this.mShop;
}
public Object getReward(){
return this.mReward;
}
public Object getPrice(){
return this.mPrice;
}
public String getMessage(){
return this.mMsg;
}
public int getInventoryLocation(){
return this.mLocation;
}
public String getName(){
return this.mName;
}
public boolean isBuyTime(){
Date now=new Date();
if(this.startTime!=null&&this.startTime.after(now)) return false;
if(this.stopTime!=null&&this.stopTime.before(now)) return false;
return true;
}
public boolean hasBuyTime(){
return this.startTime!=null||this.stopTime!=null;
}
public Date getStartTime(){
return this.startTime;
}
public Date getStopTime(){
return this.stopTime;
}
public int getPersonalLimit(){
return this.personalLimit;
}
public boolean hasPersonalLimit(){
return this.personalLimit>-1;
}
public String C(String pNode){
return this.mPlugin.getLangManager().getNode(pNode);
}
/**
* 获取物品的配置节点
*/
public ConfigurationSection getConfigurationSection(){
return ((BSShop)mShop).getConfig().getConfigurationSection("shop."+mName);
}
public boolean hasPermission(Player p,boolean msg){
if(StringUtils.isEmpty(permission)) return true;
if(perm_is_group){
boolean no_group=true;
for(String group : this.mPlugin.getManager(VaultHandler.class).getPermission().getPlayerGroups(p)){
no_group=false;
if(group.equalsIgnoreCase(permission)){ return true; }
}
if(no_group&&permission.equalsIgnoreCase("default")){ return true; }
if(msg){
this.mPlugin.send(p,C("Main.NoPermitToBuyThisItem"));
}
return false;
}
if(p.hasPermission(permission)) return true;
if(msg){
this.mPlugin.send(p,C("Main.NoPermitToBuyThisItem"));
}
return false;
}
public boolean isExtraPermissionExisting(){
if(StringUtils.isEmpty(permission)) return false;
return true;
}
@SuppressWarnings("unchecked")
public boolean alreadyBought(Player p){
if(buyT==BSBuyType.Permission){
for(String s : (List<String>)mReward){ // Loop durch Perms
if(!p.hasPermission(s)){ // Sobald ein Spieler eine Perm nicht
return false;
}
}
return true; // Hat ein Spieler alle Perms wird true returned
}
return false;
}
public JsonExtra getPersonalChatMenuItem(Player pPlayer,Player pOwner){
String saleChat=BossShop.replaceParam(pOwner,C("Main.PlayerSaleItem"));
String[] saleCharPart=saleChat.split("%item%");
//生成Json消息
JsonExtra itemSaleMsg=new JsonExtra(saleCharPart.length==0?"玩家"+pOwner.getName()+"上架了 ":saleCharPart[0]+" ",Color.green);
//设置消息物品
JsonExtra itemMsg=new JsonExtra("",Color.white);
ShopCustomizer shopCusMan=this.mPlugin.getManager(ShopCustomizer.class);
ItemStack perItem=shopCusMan.createPersonalMenuItem(pPlayer,this,this.mShop.getMenuItem(this.mLocation));
String displayeItemName=perItem.getType().name();
if(perItem.hasItemMeta()&&perItem.getItemMeta().hasDisplayName()){
displayeItemName=perItem.getItemMeta().getDisplayName();
}else{
displayeItemName=displayeItemName.replace("_"," ");
displayeItemName=displayeItemName.charAt(0)+displayeItemName.substring(1).toLowerCase();
itemMsg.setInherit(false);
itemMsg.setStyle(Style.bold,Style.underline);
}
itemMsg.setText(displayeItemName);
itemMsg.setHoverEvent(HoverAction.show_item,NMSHelper.getItemJson(perItem));
itemMsg.setClickEvent(ClickAction.run_command,"/BS open "+this.mShop.getShopName());
itemSaleMsg.addExtra(itemMsg);
if(saleCharPart.length>1)
itemSaleMsg.addNormalWords(saleCharPart[1],true);//继承父节点样式
return itemSaleMsg;
}
/**
* 检查该用户是否能够购买该物品<br />
* 如果不能购买,失败原因会立刻在本函数中显示给玩家
* <p>所有检查项目包括:<br />
* 购买事件是否通过<br />
* 是否是购买自己的物品(只有寄售物品存在这条)<br />
* 是否有足够的库存<br />
* 是否已经达到个人购买上限<br />
* 是否在购买时间<br />
* 是否有足够的钱<br />
* 是否已经购买过了(例如权限)<br />
* 是否购买的物品合法(例如不适合的附魔)<br />
* </p>
* @return 是否能购买
*/
public boolean canBuy(Player pPlayer,BSShopHolder pHolder){
//抽奖检查
if(pHolder instanceof LotteryHolder){
LotteryHolder lHolder=(LotteryHolder)pHolder;
LotteryStatus tStatus=lHolder.getStatus();
if(tStatus==LotteryStatus.WAIT){
// 此两句多余,因为getShopItem里面已经做过判断
if(this.getBuyType()!=BSBuyType.Lottery) return false;
if(this.getWeight()>0) return false;
}else if(tStatus==LotteryStatus.RESULT){
// if(!this.canBuy(pPlayer,pHolder)) return false;
// this.stockOut(pPlayer,pHolder);
// lHolder.resetLottery();
}else return false;//其他情况不允许点击抽奖背包
}
//权限检查
if(!this.hasPermission(pPlayer,true)) return false;
//产生购买事件
BSPlayerPurchaseEvent e1=new BSPlayerPurchaseEvent(pPlayer,this.mShop,this);// Custom
Bukkit.getPluginManager().callEvent(e1);
if(e1.isCancelled()) return false;
//是不是购买自己的物品,op排除在外
if(this.hasOwner()&&!pPlayer.isOp()){
if(this.owner.equals(pPlayer.getUniqueId())){
this.mPlugin.send(pPlayer,C("Main.CannotBuyYourselfGoods"));
return false;
}
}
//库存数量是否够用
if(this.numberLimit==0){
this.mPlugin.send(pPlayer,C("Main.AlreadySoldOut"));
return false;
}
//是否已经达到个人购买上限
if(this.personalLimit>-1){
int nLimit=this.mPlugin.getManager(RecordManager.class).getBuyRecord(this.mShop.getShopName(),this.mName,pPlayer.getUniqueId());
if(nLimit>=this.personalLimit){
this.mPlugin.send(pPlayer,C("Main.OutOfPersonalLimit"));
return false;
}
}
//是否在购买时间
Date date=new Date();
if(this.startTime!=null&&date.before(this.startTime)){
this.mPlugin.send(pPlayer,C("Main.GoodsNotArriveTime"));
return false;
}
if(this.stopTime !=null&&date.after (this.stopTime )){
this.mPlugin.send(pPlayer,C("Main.GoodsOutOfDate"));
return false;
}
//是否有足够的钱
try{
if(!this.hasPrice(pPlayer)) return false;
}catch(Exception exp){
this.mPlugin.severe(exp.getMessage(),exp);
this.mPlugin.send(pPlayer,C("Main.ErrorHappend"));
return false;
}
//是否已经购买过了
if(this.alreadyBought(pPlayer)){
this.mPlugin.send(pPlayer,C("Main.AlreadyBought"));
return false;
}
//购买的物品是否合法
if(this.buyT==BSBuyType.Enchantment){
Enchant e=(Enchant)this.mReward;
ItemStack tItem=pPlayer.getItemInHand();
if(tItem==null|!ItemStackChecker.isValidEnchantment(tItem,e.getType(),e.getLevel())&!this.mPlugin.getConfigManager().allowUnsafeEnchantments()){
this.mPlugin.send(pPlayer,C("Enchantment.Invalid"));
return false;
}
}
return true;
}
/**
* 商品出货一件,此处进行相关库存管理工作,寄售的工作
* <p>
* 所有的工作项目包括:<br />
* 库存的调整<br />
* 个人购买数量的记录<br />
* 价格的收取<br />
* 商品的发放<br />
* 购买消息的发送<br />
* 寄售物品报酬的给予<br />
* </p>
* @param pPlayer 出货的对象
*/
public void stockOut(Player pPlayer,BSShopHolder pHolder){
//收取价格
String tLeft=this.takePrice(pPlayer);
//给予商品
if(pHolder instanceof LotteryHolder){
LotteryHolder tHoler=(LotteryHolder)pHolder;
if(this.buyT==BSBuyType.Lottery){
//如果是乐透商品,则开始抽奖
tHoler.startLottery();
}else{
//如果是普通商品,在获取商品后,关闭结果界面并回到WAIT状态
tHoler.resetLottery();
}
}
this.giveReward(pPlayer);
//给予寄售者的寄售的利润
if(this.hasOwner()) this.mPlugin.getManager(SaleManager.class).giveSaleReward(this);
//如果存在数量限制,库存减1
if(this.hasLimit()){
if(this.numberLimit==0) throw new IllegalStateException("库存为0时,不能进行出货函数的调用,这可能是程序bug,请通知作者");
this.numberLimit--;
if(this.hasOwner()&&this.numberLimit==0){
mShop.removeItem(this.mName,true);
if(this.buyT==BSEnums.BSBuyType.Item&&this.mPlugin.getConfigManager().isAutoClearNBT())
this.mPlugin.getManager(NBTEditManager.class).clearNBT();
}
else{
ConfigurationSection sec=getConfigurationSection();
if(sec!=null){
sec.set("NumberLimit",this.getLimit());
this.mShop.saveConfig();
}
}
}
//如果存在个人购买数量限制,增加购买记录到文件
if(this.hasPersonalLimit()){
this.mPlugin.getManager(RecordManager.class).addBuyRecord(this.mShop.getShopName(),this.mName,pPlayer.getUniqueId());
}
//购买后消息的生成
if(StringUtils.isNotEmpty(this.mMsg)){
String tMsg=BossShop.replaceParam(pPlayer,this.mMsg);
if(StringUtils.isNotEmpty(tLeft)&&tMsg.contains("%left%"))
tMsg=tMsg.replace("%left%",tLeft);
this.mPlugin.send(pPlayer,tMsg);
}
//购买记录的记录(非正式)
if(this.mPlugin.getConfigManager().transactionLogEnabled())
this.mPlugin.getManager(TransactionLog.class).addTransaction(pPlayer,this);
//更新所有依据该商店生成的背包
if(this.hasLimit()) mShop.updateAllInventory();
else mShop.updateInventory(pHolder.getInventory(),pPlayer);
//事件产生
BSPlayerPurchasedEvent e2=new BSPlayerPurchasedEvent(pPlayer,mShop,this);// Custom
Bukkit.getPluginManager().callEvent(e2);// Custom Event end
}
/**
* 玩家是否满足显示该商品的条件
* <p>如果商品是寄售商品,且已经卖完或或者不在售卖时间,将会调用{@link BSShop #removeItem(String, boolean)}</p>
* @param pPlayer 玩家
* @return 是否显示
*/
public boolean disaplyToPlayer(Player pPlayer){
if(!this.hasPermission(pPlayer,false)&&this.mPlugin.getConfigManager().hideNoPermitItem()) return false;
if(this.numberLimit==0){
if(this.hasOwner()){
this.mShop.removeItem(this.getName(),true);
if(this.getBuyType()==BSEnums.BSBuyType.Item&&this.mPlugin.getConfigManager().isAutoClearNBT())
this.mPlugin.getManager(NBTEditManager.class).clearNBT();
return false;
}
if(this.isHideNoStock()) return false;
}
if(!this.isBuyTime()){
if(this.hasOwner()){
this.mShop.removeItem(this.getName(),true);
String tMsg=BossShop.replaceParam(pPlayer,C("Mail.FromOutDateSale"));
this.mPlugin.getManager(MailManager.class).addMail(this,tMsg);
return false;
}
if(this.isHideNotTime()) return false;
}
return true;
}
/**
* 获取BSBuy库存
* @return
*/
public int getLimit(){
return this.numberLimit;
}
public boolean hasLimit(){
return this.numberLimit>-1;
}
@SuppressWarnings("unchecked")
public boolean hasPrice(Player p){
MultiplierHandler multipMan=this.mPlugin.getManager(MultiplierHandler.class);
WorthHandler wHandler=this.mPlugin.getManager(WorthHandler.class);
switch(priceT){
// EXP
case Exp:
// return hasExp(p, (Integer)price); old
return wHandler.hasExp(p,multipMan.calculateWithMultiplier(p,priceT,(Integer)mPrice));
// Item
case Item:
return wHandler.hasItems(p,(List<ItemStack>)mPrice);
// Money
case Money:
if(mPrice instanceof Integer){
// return hasMoney(p, (Integer)price); old
return wHandler.hasMoney(p,multipMan.calculateWithMultiplier(p,priceT,(Integer)mPrice));
}
// return hasMoney(p, (Integer)price); old
return wHandler.hasMoney(p,multipMan.calculateWithMultiplier(p,priceT,(Double)mPrice));
// Points
case Points:
// return hasPoints(p, (Integer)price); old
return wHandler.hasPoints(p,multipMan.calculateWithMultiplier(p,priceT,(Integer)mPrice));
// Free
case Free:
return true;
// Nothing
case Nothing:
return true;
}
return false;
}
@SuppressWarnings("unchecked")
public String takePrice(Player p){
MultiplierHandler multipMan=this.mPlugin.getManager(MultiplierHandler.class);
WorthHandler wHandler=this.mPlugin.getManager(WorthHandler.class);
switch(priceT){
// EXP
case Exp:
return wHandler.takeExp(p,multipMan.calculateWithMultiplier(p,priceT,(Integer)mPrice));
// Item
case Item:
return wHandler.takeItems(p,(List<ItemStack>)mPrice);
// Money
case Money:
if(mPrice instanceof Integer){ return wHandler.takeMoney(p,multipMan.calculateWithMultiplier(p,priceT,(Integer)mPrice)); }
return wHandler.takeMoney(p,multipMan.calculateWithMultiplier(p,priceT,(Double)mPrice));
// Points
case Points:
return wHandler.takePoints(p,multipMan.calculateWithMultiplier(p,priceT,(Integer)mPrice));
// Free
case Free:
return null;
// Nothing
case Nothing:
return null;
}
return null;
}
@SuppressWarnings("unchecked")
public void giveReward(Player p){
WorthHandler wHandler=this.mPlugin.getManager(WorthHandler.class);
switch(buyT){
case Command:
wHandler.giveRewardCommand(p,(List<String>)mReward);
return;
case PlayerCommand:
wHandler.giveRewardPlayerCommand(p,(List<String>)mReward);
return;
case TimeCommand:
wHandler.giveRewardTimeCommand(p,(HashMap<Integer,String>)mReward);
return;
case Item:
wHandler.giveRewardItem(p,(List<ItemStack>)mReward);
return;
case Permission:
wHandler.giveRewardPermission(p,(List<String>)mReward);
return;
case Money:
if(mReward instanceof Integer){
wHandler.giveRewardMoney(p,(Integer)mReward);
return;
}
wHandler.giveRewardMoney(p,(Double)mReward);
return;
case Points:
wHandler.giveRewardPoints(p,(Integer)mReward);
return;
case Shop:
wHandler.giveRewardShop(p,(String)mReward);
return;
case Enchantment:
wHandler.giveRewardEnchantment(p,(Enchant)mReward);
return;
case Lottery:
break;
case Nothing:
break;
}
}
/**
* 翻译BSBuy物品的属性
*/
public String transformMessage(String msg){
if(mReward==null){
mReward=1;
}
if(mPrice==null){
mPrice=1;
}
if(msg==null||msg.length()==0) return "";
msg=StringManager.transform(msg);
String priceM=""+mPrice;
if(mPrice instanceof List<?>){
List<?> list=(List<?>)mPrice;
if((!list.isEmpty())&&list.get(0) instanceof ItemStack){
String m="";
int x=0;
for(Object i : list){
if(i instanceof ItemStack){
x++;
String material=((ItemStack)i).getType().name().toLowerCase();
material=material.replaceFirst(material.substring(0,1),material.substring(0,1).toUpperCase());
m+=""+((ItemStack)i).getAmount()+" "+material+(x<list.size()?", ":"");
}
}
priceM=m;
}
}
String rewardM=""+mReward;
if(mReward instanceof List<?>){
List<?> list=(List<?>)mReward;
if((!list.isEmpty())&&list.get(0) instanceof ItemStack){
String m="";
int x=0;
for(Object i : list){
if(i instanceof ItemStack){
x++;
String material=((ItemStack)i).getType().name().toLowerCase();
material=material.replaceFirst(material.substring(0,1),material.substring(0,1).toUpperCase());
m+=""+((ItemStack)i).getAmount()+" "+material+(x<list.size()?", ":"");
}
}
rewardM=m;
}
}
if(mName!=null&&mName!=""&&mName.length()>0){
msg=msg.replace("%itemname%",mName);
msg=msg.replace("%shopitemname%",mName);
}
if(priceT!=null&&priceT.name()!=""&&priceT.name().length()>0){
msg=msg.replace("%pricetype%",priceT.name());
}
if(priceM!=null&&priceM!=""&&priceM.length()>0){
msg=msg.replace("%price%",priceM);
}
if(buyT!=null&&buyT.name()!=""&&buyT.name().length()>0){
msg=msg.replace("%rewardtype%",buyT.name());
}
if(rewardM!=null&&rewardM!=""&&rewardM.length()>0){
msg=msg.replace("%reward%",rewardM);
}
return msg;
}
@Deprecated
public void setInventoryLocation(int i){
mLocation=i;
}
public void setNeedEdit(boolean enable){
this.mNeedEdit=enable;
}
public boolean isNeedEdit(){
return this.mNeedEdit;
}
}

View File

@ -0,0 +1,29 @@
package org.black_ixx.bossshop.core;
import java.util.Date;
import java.util.UUID;
import org.black_ixx.bossshop.core.BSEnums.BSBuyType;
import org.black_ixx.bossshop.core.BSEnums.BSPriceType;
public class BSBuyParameter{
public int numberLimit=-1;
public int personalLimit=-1;
public int location;
public int weight=0;
public int hideItemFlag=0;
public boolean perm_is_group=false;
public boolean hideNoStock=false;
public boolean hideNotTime=false;
public String permission;
public String name;
public String msg="undefine";
public UUID owner=null;
public Object reward=null;
public Object price=null;
public Date stopTime=null;
public Date startTime=null;
public BSShop shop=null;
public BSPriceType priceT=null;
public BSBuyType buyT=null;
}

View File

@ -0,0 +1,47 @@
package org.black_ixx.bossshop.core;
public class BSEnums {
public enum BSBuyType{
Item,
Enchantment,
Command,
TimeCommand,
Permission,
Money,
Points,
Shop,
PlayerCommand,
Lottery,
Nothing
}
public enum BSPriceType{
Money,
Item,
Points,
Exp,
Nothing,
Free
}
public enum STOCK{
in,
out,
check
}
public static BSBuyType getBSBuyType(String name){
for(BSBuyType t : BSEnums.BSBuyType.values()){
if(name.equalsIgnoreCase(t.toString())) return t;
}
return null;
}
public static BSPriceType getBSPriceType(String name){
for(BSPriceType t : BSEnums.BSPriceType.values()){
if(name.equalsIgnoreCase(t.toString())) return t;
}
return null;
}
}

View File

@ -0,0 +1,81 @@
package org.black_ixx.bossshop.core;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSEnums.BSPriceType;
import org.bukkit.entity.Player;
public class BSMultiplier{
private String permission="Permission.Node";
private BSPriceType type=BSPriceType.Nothing;
private double multiplier=1.0;
public BSMultiplier(BossShop pPlugin,String config_line){
String[] parts=config_line.split(":",3);
if(parts.length!=3){
pPlugin.warn("Invalid Multiplier Group Line... \""+config_line+"\"! It should look like this: \"Permission.Node:<type>:<multiplier>\"");
return;
}
String permission=parts[0].trim();
if(parts[1].trim().equalsIgnoreCase("<type>")){
return;
}
BSPriceType type=null;
for(BSPriceType t : BSPriceType.values()){
if(t.name().equalsIgnoreCase(parts[1].trim())){
type=t;
}
}
if(type==null||type==BSPriceType.Item||type==BSPriceType.Nothing||type==BSPriceType.Free){
pPlugin.warn("Invalid Multiplier Group Line... \""+config_line+"\"! It should look like this: \"Permission.Node:<type>:<multiplier>\". '"+parts[1].trim()+"' is no valid PriceType... you can use: 'Money', 'Points' and 'EXP'!");
return;
}
double multiplier=1.0;
try{
multiplier=Double.parseDouble(parts[2].trim());
}catch(Exception e){
pPlugin.warn("Invalid Multiplier Group Line... \""+config_line+"\"! It should look like this: \"Permission.Node:<type>:<multiplier>\". '"+parts[2].trim()+"' is no valid multiplier... What you can use instead (examples): 0.25, 0.3, 0.75, 1.0, 1.5, 2.0 etc.!");
return;
}
setup(permission,type,multiplier);
}
public BSMultiplier(String permission,BSPriceType type,double multiplier){
setup(permission,type,multiplier);
}
public void setup(String permission,BSPriceType type,double multiplier){
this.permission=permission;
this.type=type;
this.multiplier=multiplier;
}
public boolean isValid(){
return type!=BSPriceType.Nothing;
}
public BSPriceType getType(){
return type;
}
public double getMultiplier(){
return multiplier;
}
public String getPermission(){
return permission;
}
public boolean hasPermission(Player p){
return p.hasPermission(permission);
}
public double calculateWithMultiplier(double d){
return d*multiplier;
}
public int calculateWithMultiplier(int d){
return (int)(d*multiplier);
}
}

View File

@ -0,0 +1,376 @@
package org.black_ixx.bossshop.core;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.lottery.LotteryHolder;
import org.black_ixx.bossshop.mail.MailManager;
import org.black_ixx.bossshop.managers.BuyItemHandler;
import org.black_ixx.bossshop.managers.ItemStackCreator;
import org.black_ixx.bossshop.managers.StringManager;
import org.black_ixx.bossshop.util.AttributeRemover;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
import cc.util.bossshop.FBukkit;
import cc.util.bossshop.filemanager.AFileManager;
public class BSShop extends AFileManager{
private static final Pattern PATTERN=Pattern.compile("[%]([^%]+)[%]");
public final String mShopName;
private String sign_text="[BossShop]";
private String mDisplayname="[BossShop]";
private boolean needPermToCreateSign=true;
private boolean mValid=true;
private boolean mSpecial=false;
private int mInvSize=9;
private int mTotalWeight=0;
private final HashMap<Integer,BSBuy> mShopItems=new HashMap<Integer,BSBuy>();
private final HashMap<Integer,ItemStack> mMenuItems=new HashMap<Integer,ItemStack>();
private String mEnterMsg="";
private String mLeaveMsg="";
/**
* 新建一个商店
* @param fileName /shops/下的商店配置文件名字
*/
public BSShop(BossShop pPlugin,String fileName,String shopName){
super(pPlugin,"shops/"+fileName,"1.0");
this.mShopName=shopName;
}
/**
* 重载商店配置
* @return 是否载入
*/
@Override
public boolean reloadConfig(){
this.info(C("Console.StartReloadShop")+this.mShopName);
if(!super.reloadConfig()) return false;
this.mMenuItems.clear();
this.mShopItems.clear();
this.addDefaults();
this.sign_text=this.mConfig.getString("signs.text");
this.needPermToCreateSign=this.mConfig.getBoolean("signs.NeedPermissionToCreateSign");
this.mSpecial=this.mConfig.getBoolean("ShopTypeSpecial",false);
this.mValid=true;
this.mDisplayname=StringManager.transform(this.mConfig.getString("DisplayName",""));
this.mEnterMsg=StringManager.transform(this.mConfig.getString("EnterMessage","进入"+this.mDisplayname+"商店"));
this.mLeaveMsg=StringManager.transform(this.mConfig.getString("LeaveMessage","离开"+this.mDisplayname+"商店"));
this.loadItems();
this.finishedAddingItems();
this.saveConfig();
return true;
}
private void addDefaultItem(String name,String rewardType,String priceType,Object reward,Object price,List<String> menuitem,String message,int loc,String permission){
ConfigurationSection c=this.mConfig.getConfigurationSection("shop").createSection(name);
c.set("RewardType",rewardType);
c.set("PriceType",priceType);
c.set("Price",price);
c.set("Reward",reward);
c.set("MenuItem",menuitem);
c.set("Message",message);
c.set("InventoryLocation",loc);
c.set("ExtraPermission",permission);
}
@Override
protected void addDefaults(){
super.addDefaults();
if(this.mConfig.get("ShopName")!=null) this.mConfig.set("ShopName",null);
this.mConfig.addDefault("signs.text","[ExtraShop]");
this.mConfig.addDefault("signs.NeedPermissionToCreateSign",false);
if(this.mConfig.getConfigurationSection("shop")==null){
this.mConfig.createSection("shop");
}
}
public String getShopName(){
return mShopName;
}
public String getDisplayName(){
return mDisplayname;
}
public String getEnterMessage(){
return this.mEnterMsg;
}
public String getLeaveMessage(){
return this.mLeaveMsg;
}
public String getSignText(){
return sign_text;
}
public boolean needPermToCreateSign(){
return needPermToCreateSign;
}
public int getInventorySize(){
return mInvSize;
}
public HashMap<Integer,BSBuy> getItems(){
return mShopItems;
}
/**
* 获取商店下一个可用的上架位置,从1开始,<=0为无位置
*/
public int getNextAvailableLoc(){
Set<Integer> tPos=this.getMenuItemSet();
for(int i=0;i<81;i++){
if(!tPos.contains(i)) return i+1;
}
return 0;
}
/**
* 根据物品名(此为配置文件节点名,非显示的名字),获取商店物品
* @param name 物品名
* @return 如果不存在返回null
*/
public BSBuy getShopItem(String name){
for(BSBuy sbuy : this.mShopItems.values()){
if(sbuy.getName().equalsIgnoreCase(name)) return sbuy;
}
return null;
}
public BSBuy getShopItem(int pos){
return this.mShopItems.get(pos);
}
/**
* 获取菜单物品的拷贝
* @param pos
* @return
*/
public ItemStack getMenuItem(int pos){
ItemStack menuItem=this.mMenuItems.get(pos);
if(menuItem==null) return null;
else return menuItem.clone();
}
/**
* 获取商店物品位置Set集合的拷贝
*/
public Set<Integer> getMenuItemSet(){
Set<Integer> pos=new HashSet<Integer>();
pos.addAll(this.mMenuItems.keySet());
return pos;
}
/**
* 添加物品到商店
* @param buy
* @param menu_item
* @param manager
*/
public void addShopItem(BSBuy buy,ItemStack menu_item){
boolean need_reedit=false;
if(menu_item.hasItemMeta()){
ItemMeta meta=menu_item.getItemMeta();
if(!need_reedit&&meta instanceof SkullMeta){
SkullMeta skullMeta=(SkullMeta)meta;
if(skullMeta.hasOwner()) need_reedit=PATTERN.matcher(skullMeta.getOwner()).find();
}
if(meta.hasDisplayName()){
String st=buy.transformMessage(meta.getDisplayName());
if(!need_reedit) need_reedit=PATTERN.matcher(st).find();
meta.setDisplayName(st);
}
if(meta.hasLore()){
List<String> tList=meta.getLore();
List<String> l=new ArrayList<String>();
for(String s : tList){
l.add(buy.transformMessage(s));
if(!need_reedit) need_reedit=PATTERN.matcher(s).find();
}
if(!FBukkit.isItemMetaEmpty(meta)) meta.setLore(l);
}
if(!FBukkit.isItemMetaEmpty(meta)) menu_item.setItemMeta(meta);
}
if(buy.hasLimit()||buy.hasBuyTime()||buy.hasPersonalLimit()) need_reedit=true;
buy.setNeedEdit(need_reedit);
menu_item=AttributeRemover.hideAttributes(menu_item,buy.getHideItemFlag());
mShopItems.put(buy.getInventoryLocation(),buy);
mMenuItems.put(buy.getInventoryLocation(),menu_item);
this.mTotalWeight+=buy.getWeight()>0?buy.getWeight():0;
}
/**
* 重新设置商店背包大小,在每次重载商店后调用
*/
private void resetInventorySize(){
int highest=0;
for(Integer pos : mShopItems.keySet()){
BSBuy b=mShopItems.get(pos);
if(b!=null&&pos>highest){
highest=pos;
}
}
highest++;
this.mInvSize=BSShop.getSuitableSize(highest);
}
public void finishedAddingItems(){
this.resetInventorySize();
}
/**
* 获取合适的背包大小
*/
public static int getSuitableSize(int pSize){
if(pSize>72) return 81;
int m=pSize/9;
if(m*9<pSize) pSize=(m+1)*9;
else pSize=m*9;
return pSize;
}
public int getTotalWeight(){
return this.mTotalWeight;
}
/**
* 为特定的玩家加载定制的背包
* <p>
* 外部勿直接调用该函数,请通过{@link BSShopManager#openShop(Player, BSShop)来打开商店}<br />
* 所有的信息均存储在holder中
* </p>
* @param pPlayer 玩家
*/
public void openInventory(Player pPlayer){
if(!this.mValid) return;
BSShopHolder holder=null;
if(this.mSpecial) holder=new LotteryHolder((BossShop)this.mPlugin,pPlayer,this);
else holder=new BSShopHolder((BossShop)this.mPlugin,pPlayer,this);
Inventory inventory=Bukkit.createInventory(holder,this.mInvSize,this.mDisplayname);
holder.setInventory(inventory);
holder.updateInventory();
pPlayer.openInventory(inventory);
}
/**
* 为指定玩家更新指定的背包,如果商店已经无效,将会清空玩家背包并关闭
* @param inv 指定的背包
* @param player 指定的玩家
*/
public void updateInventory(Inventory inv,Player player){
if(!(inv.getHolder() instanceof BSShopHolder)) return;
BSShopHolder tHolder=(BSShopHolder)inv.getHolder();
tHolder.updateInventory();
}
/**
* 为所有玩家更新打开此商店的背包,如果商店已经无效,将会清空玩家背包并关闭
*/
public void updateAllInventory(){
for(Player player : FBukkit.getOnlinePlayers()){
Inventory inv=player.getOpenInventory().getTopInventory();
if(inv.getHolder() instanceof BSShopHolder){
BSShop shop=((BSShopHolder)inv.getHolder()).getShop();
if(shop==this) this.updateInventory(inv,player);
}
}
}
/**
* 检查商店是否特殊类型的商店
*/
public boolean isShopSpecial(){
return this.mSpecial;
}
/**
* 检查商店是否合法,比如重载后文件不存在
*/
public boolean isShopValid(){
return this.mValid;
}
private void loadItems(){
ConfigurationSection shop_sec=this.mConfig.getConfigurationSection("shop");
for(String key : shop_sec.getKeys(false)){
ConfigurationSection sec=shop_sec.getConfigurationSection(key);
if(sec==null){
this.mPlugin.severe("创建商品["+shop_sec.getName()+"]时发生了错误,文件:"+this.mShopName);
continue;
}
List<String> menusec=sec.getStringList("MenuItem");
if(menusec==null){
this.mPlugin.severe("创建商品["+shop_sec.getName()+"]时发生了错误,菜单物品不存在");
continue;
}
ItemStack menu=((BossShop)this.mPlugin).getManager(ItemStackCreator.class).createItemStackS(menusec,true);
BSBuy items=((BossShop)this.mPlugin).getManager(BuyItemHandler.class).createBuyItem(this,sec);
if(items==null) continue;
if(items.hasOwner()){
if(items.getLimit()==0){
this.removeItem(items.getName(),false);
shop_sec.set(key,null);
continue;
}
if(!items.isBuyTime()){
((BossShop)this.mPlugin).getManager(MailManager.class).addMail(items,this.mPlugin.getLangManager().getNode("Mail.FromOutDateSale"));
shop_sec.set(key,null);
continue;
}
}
this.addShopItem(items,menu);
}
}
/**
* 删除商店配置文件中的商品
* @param pname 商品名字
* @param update 是否保存并重载配置
*/
public ConfigurationSection removeItem(String pname,boolean update){
ConfigurationSection sec=this.mConfig.getConfigurationSection("shop."+pname);
this.mConfig.set("shop."+pname,null);
if(update) this.saveConfig();
BSBuy tBuy=this.getShopItem(pname);
if(tBuy!=null){
this.mMenuItems.remove(tBuy.getInventoryLocation());
this.mShopItems.remove(tBuy.getInventoryLocation());
this.mTotalWeight-=tBuy.getWeight()>0?tBuy.getWeight():0;
}
return sec;
}
/**
* 重新载入商店
* @return
*/
public boolean reloadShop(){
if(!this.mFile.exists()||this.mFile.isDirectory()){
warn(C("Console.ShopFileNotExist")+"["+this.mShopName+"]");
this.mValid=false;
this.mMenuItems.clear();
this.mShopItems.clear();
this.mConfig.set("shop",null);
return false;
}
this.reloadConfig();
return true;
}
}

View File

@ -0,0 +1,82 @@
package org.black_ixx.bossshop.core;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.managers.ShopCustomizer;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
/**
* used by Inventory of BSShop
*/
public class BSShopHolder implements InventoryHolder{
protected BossShop mPlugin;
protected final BSShop mShop;
protected final Player mOwner;
protected Inventory mInv;
public BSShopHolder(BossShop pPlugin,Player pOwner,BSShop pShop){
this.mPlugin=pPlugin;
this.mOwner=pOwner;
this.mShop=pShop;
}
/**
* 获取holder所持有的背包
*/
@Override
public Inventory getInventory(){
return mInv;
}
/**
* 设置holder的背包,必须调用
* @param pInv 要设置成的背包
*/
public void setInventory(Inventory pInv){
this.mInv=pInv;
}
/**
* 获取背包内的物品
* <p>
* 函数内部已经做过过滤,对于不符合条件的物品一律返回null
* </p>
* @param pPos 位置
* @return 如果不存在则为null
*/
public BSBuy getShopItem(int pPos){
return mShop.getShopItem(pPos);
}
/**
* 获取holder所关联的商店
*/
public BSShop getShop(){
return mShop;
}
/**
* 获取holder所关联的玩家
*/
public Player getOwner(){
return this.mOwner;
}
/**
* 将定制的物品放入到背包中
* @return 如果商店不存在false,否则true
*/
public boolean updateInventory(){
if(!this.mShop.isShopValid()){
this.mInv.clear();
this.mOwner.closeInventory();
return false;
}
BossShop.getInstance().getManager(ShopCustomizer.class).updateInventory(this.mShop,this.mOwner,this.mInv,this.mShop.getMenuItemSet());
return true;
}
}

View File

@ -0,0 +1,203 @@
package org.black_ixx.bossshop.core;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.managers.DefaultCreator;
import org.black_ixx.bossshop.nbt.NBTEditManager;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import cc.util.bossshop.FBukkit;
import cc.util.bossshop.pluginmodel.INeedReload;
public class BSShopManager implements INeedReload{
private long mLastReloadTime=0;
private BossShop mPlugin;
private File folder;
private final HashMap<String,BSShop> shops=new HashMap<String,BSShop>();
/**
* 商店管理器
* @param plugin
*/
public BSShopManager(BossShop plugin){
this.mPlugin=plugin;
this.folder=new File(plugin.getDataFolder().getAbsolutePath()+"/shops/");
this.mPlugin.registerReloadModel(this);
}
/**
* 重载或载入所有商店
*/
@Override
public boolean reloadConfig(){
if(!folder.isDirectory()) createDefaults();
Iterator<Map.Entry<String,BSShop>> it=this.shops.entrySet().iterator();
while(it.hasNext()){
Map.Entry<String,BSShop> entry=it.next();
BSShop shop=entry.getValue();
if(!shop.reloadShop()){
this.mPlugin.debug("商店["+shop.mShopName+"]由于配置文件不存在,移除");
it.remove();
}
}
for(File file : folder.listFiles()){
if(file==null||!file.isFile()) continue;
String name=file.getName();
if(name.toLowerCase().endsWith(".yml")) this.loadShop(file);
}
this.mPlugin.info("载入了 "+shops.size()+" Shops!");
this.mLastReloadTime=System.currentTimeMillis();
// 一定要在调用清理函数之前调用时间
if(this.mPlugin.getConfigManager().isAutoClearNBT())
this.mPlugin.getManager(NBTEditManager.class).clearNBT();
this.updataAllInventory();
return true;
}
public long getLastReloadTime(){
return this.mLastReloadTime;
}
/**
* 重载所有由BS插件生成的背包
* <p>商店配置重载后悔自动调用该函数</p>
*/
public void updataAllInventory(){
for(Player player : FBukkit.getOnlinePlayers()){
Inventory inv=player.getOpenInventory().getTopInventory();
if(inv.getHolder() instanceof BSShopHolder){
BSShopHolder holder=(BSShopHolder)inv.getHolder();
holder.getShop().updateInventory(inv,player);
}
}
}
/**
* 检查根据机读名称(文件名)对应的商店是否存在
* @param name 商店机读名称,忽略大小写
* @return 是否存在
*/
public boolean isShopExist(String name){
return !(this.getShop(name)==null);
}
/**
* 检查指定的商店是否存在(多用于配置重载后的商店数据检验)
* @param shop 商店
* @return 是否存在
*/
public boolean isShopExist(BSShop shop){
return this.shops.containsValue(shop);
}
/**
* 根据商店机读名称(文件名)获取指定的商店,不存在则返回null
* @param name 商店机读名称,忽略大小写
* @return 商店
*/
public BSShop getShop(String name){
for(Map.Entry<String,BSShop> entry : this.shops.entrySet()){
if(entry.getKey().equalsIgnoreCase(name)) return entry.getValue();
}
return null;
}
/**
* 增加一个商店到管理器中
*/
public void addShop(BSShop pShop){
this.shops.put(pShop.getShopName(),pShop);
}
public BSShop removeShop(BSShop pShop){
return this.shops.remove(pShop);
}
/**
* 根据指定的文件载入所需的商店
* <p>如果商店已经载入,则重新载入但是商店对象不变,如果商店文件不存在,则去除该商店</p>
* @param file 要载入商店的文件
* @return 载入后的商店,自动添加到商店列表
*/
private BSShop loadShop(File file){
String fileName=file.getName();
String shopName=getName(fileName);
BSShop shop=this.getShop(shopName);
if(shop!=null) return shop;
else{
shop=new BSShop(this.mPlugin,fileName,shopName);
shop.reloadConfig();
this.shops.put(shopName,shop);
}
return shop;
}
/**
* 根据文件名生成商店名
* @param filename 文件名
* @return 去掉后缀的字符串
*/
public static String getName(String filename){
int pos=filename.lastIndexOf('.');
if(pos!=-1) return filename.substring(0,pos);
else return filename;
}
/**
* 根据机读名字移除指定的商店
* @param name 机读名字
* @return 被移除的商店,如果不存在则为null
*/
private BSShop removeShop(String name){
Iterator<Map.Entry<String,BSShop>> it=this.shops.entrySet().iterator();
while(it.hasNext()){
Map.Entry<String,BSShop> entry=it.next();
if(entry.getKey().equalsIgnoreCase(name)){
it.remove();
return entry.getValue();
}
}
return null;
}
/**
* 根据机读名称为玩家打开指定的商店
* @param player 玩家
* @param name 商店机读名
*/
public void openShop(Player player,String name){
BSShop shop=this.getShop(name);
if(shop==null){
this.mPlugin.send(player,this.mPlugin.getLangManager().getNode("Main.ShopNotExisting"));
return;
}
this.openShop(player,shop);
}
/**
* 为玩家打开指定的商店
* @param player 玩家
* @param shop 商店
*/
public void openShop(Player player,BSShop shop){
shop.openInventory(player);
this.mPlugin.send(player,shop.getEnterMessage());
}
public HashMap<String,BSShop> getShops(){
return shops;
}
/**
* 创建默认的商店
*/
public void createDefaults(){
new DefaultCreator().addAllExamples();
}
}

View File

@ -0,0 +1,52 @@
package org.black_ixx.bossshop.events;
import org.black_ixx.bossshop.core.BSBuy;
import org.black_ixx.bossshop.core.BSShop;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public class BSDisplayItemEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Player player;
private final BSBuy buy;
private final BSShop shop;
private boolean cancelled = false;
public BSDisplayItemEvent(Player player, BSShop shop, BSBuy buy) {
this.player=player;
this.buy=buy;
this.shop=shop;
}
public Player getPlayer() {
return player;
}
public BSBuy getShopItem(){
return buy;
}
public BSShop getShop(){
return shop;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
}

View File

@ -0,0 +1,55 @@
package org.black_ixx.bossshop.events;
import org.black_ixx.bossshop.core.BSBuy;
import org.black_ixx.bossshop.core.BSShop;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public class BSPlayerPurchaseEvent extends Event implements Cancellable{
private static final HandlerList handlers=new HandlerList();
private final Player player;
private final BSBuy buy;
private final BSShop shop;
private boolean cancelled=false;
public BSPlayerPurchaseEvent(Player player,BSShop shop,BSBuy buy){
this.player=player;
this.buy=buy;
this.shop=shop;
}
public Player getPlayer(){
return player;
}
public BSBuy getShopItem(){
return buy;
};
public BSShop getShop(){
return shop;
}
@Override
public boolean isCancelled(){
return cancelled;
}
@Override
public void setCancelled(boolean cancelled){
this.cancelled=cancelled;
}
public static HandlerList getHandlerList(){
return handlers;
}
@Override
public HandlerList getHandlers(){
return handlers;
}
}

View File

@ -0,0 +1,43 @@
package org.black_ixx.bossshop.events;
import org.black_ixx.bossshop.core.BSBuy;
import org.black_ixx.bossshop.core.BSShop;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public class BSPlayerPurchasedEvent extends Event{
private static final HandlerList handlers=new HandlerList();
private final Player player;
private final BSBuy buy;
private final BSShop shop;
public BSPlayerPurchasedEvent(Player player,BSShop shop,BSBuy buy){
this.player=player;
this.buy=buy;
this.shop=shop;
}
public Player getPlayer(){
return player;
}
public BSBuy getShopItem(){
return buy;
}
public BSShop getShop(){
return shop;
}
public static HandlerList getHandlerList(){
return handlers;
}
@Override
public HandlerList getHandlers(){
return handlers;
}
}

View File

@ -0,0 +1,26 @@
package org.black_ixx.bossshop.events;
import org.black_ixx.bossshop.BossShop;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public class BSReloadedEvent extends Event {
private static final HandlerList handlers = new HandlerList();
private BossShop plugin;
public BSReloadedEvent(BossShop plugin) {
this.plugin=plugin;
}
public BossShop getBossShop(){
return plugin;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
}

View File

@ -0,0 +1,108 @@
package org.black_ixx.bossshop.listeners;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.UUID;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSBuy;
import org.black_ixx.bossshop.core.BSEnums;
import org.black_ixx.bossshop.core.BSShopHolder;
import org.black_ixx.bossshop.lottery.LotteryHolder;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.inventory.InventoryType.SlotType;
import org.bukkit.inventory.ItemStack;
import cc.util.bossshop.pluginmodel.IClearAble;
public class InventoryListener implements Listener,IClearAble{
private BossShop mPlugin;
private long mLastClear=0;
private long mClearDis=3600000;
private HashMap<UUID,Long> mWait=new HashMap<>();
public InventoryListener(BossShop pPlugin){
this.mPlugin=pPlugin;
this.mPlugin.getServer().getPluginManager().registerEvents(this,this.mPlugin);
this.mPlugin.registerClearModel(this);
}
@Override
public boolean clearStatus(){
this.mWait.clear();
return true;
}
/**
* 在一定的时间后清理掉无用的等待列表
*/
private void clearWaitList(){
if((this.mLastClear+this.mClearDis)>System.currentTimeMillis()) return;
for(Iterator<Entry<UUID,Long>> it=this.mWait.entrySet().iterator();it.hasNext();){
if((it.next().getValue()+this.mPlugin.getConfigManager().getCoolTime()*1000)<System.currentTimeMillis()) it.remove();
}
this.mLastClear=System.currentTimeMillis();
}
@EventHandler
public void closeShop(InventoryCloseEvent event){
if(!(event.getInventory().getHolder() instanceof BSShopHolder)) return;
if(!(event.getPlayer() instanceof Player)) return;
Player tPlayer=(Player)event.getPlayer();
BSShopHolder bsHolder=(BSShopHolder)event.getInventory().getHolder();
this.mPlugin.send(tPlayer,bsHolder.getShop().getLeaveMessage());
if(bsHolder instanceof LotteryHolder){
LotteryHolder ltHolder=(LotteryHolder)bsHolder;
ltHolder.closeLottery();
}
}
public void onDargItem(InventoryDragEvent pEvent){
}
@EventHandler(priority=EventPriority.HIGH)
public void purchase(InventoryClickEvent event){
if(!(event.getWhoClicked() instanceof Player)) return;
if(!(event.getInventory().getHolder() instanceof BSShopHolder)) return;
BSShopHolder holder=(BSShopHolder)event.getInventory().getHolder();
event.setCancelled(true);
event.setResult(Result.DENY);
Player pPlayer=(Player)event.getWhoClicked();
this.clearWaitList();
try{
ItemStack item=event.getCurrentItem();
if(item==null||item.getType()==Material.AIR) return;
if(event.getSlotType()==SlotType.QUICKBAR) return;
BSBuy buy=holder.getShopItem(event.getRawSlot());
if(buy==null) return;
if(buy.getBuyType()==BSEnums.BSBuyType.Nothing) return;
// 检查是否很快的点击
Long time=this.mWait.put(pPlayer.getUniqueId(),System.currentTimeMillis());
if(time!=null&&(time+this.mPlugin.getConfigManager().getCoolTime())>System.currentTimeMillis()){
this.mPlugin.send(pPlayer,this.mPlugin.getLangManager().get("Main.YouClickTooQuick"));
return;
}
if(!buy.canBuy(pPlayer,holder)) return;
buy.stockOut(pPlayer,holder);
}catch(Throwable exp){
this.mPlugin.severe(exp.getMessage(),exp);
this.mPlugin.send(pPlayer,this.mPlugin.getLangManager().get("Main.ErrorHappend"));
}
}
}

View File

@ -0,0 +1,67 @@
package org.black_ixx.bossshop.listeners;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSShopManager;
import org.black_ixx.bossshop.mail.MailManager;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.inventory.ItemStack;
import cc.util.bossshop.config.CommentedYamlConfig;
import cc.util.bossshop.pluginmodel.INeedConfig;
public class PlayerListener implements Listener,INeedConfig{
private BossShop mPlugin;
private Material mOpenItem=Material.WATCH;
private boolean mSneakNeed=true;
public PlayerListener(BossShop pPlugin){
this.mPlugin=pPlugin;
this.mPlugin.getServer().getPluginManager().registerEvents(this,this.mPlugin);
this.mPlugin.registerConfigModel(this);
}
@EventHandler(priority=EventPriority.HIGHEST)
public void onPlayerInteractItem(PlayerInteractEvent e){
Player player=e.getPlayer();
ItemStack item=player.getItemInHand();
if(item==null||item.getType()==Material.AIR||item.getType()!=this.mOpenItem) return;
if(!player.hasPermission("BossShop.open.item")) return;
if(!mSneakNeed||player.isSneaking()){
e.setCancelled(true);
this.mPlugin.getManager(BSShopManager.class).openShop(player,this.mPlugin.getConfigManager().getMainShop());
}
}
@EventHandler
public void onPlayerJoin(final PlayerJoinEvent pEvent){
Bukkit.getScheduler().runTaskLater(this.mPlugin,new Runnable(){
@Override
public void run(){
PlayerListener.this.mPlugin.getManager(MailManager.class).noticeExistMail(pEvent.getPlayer());
}
},100);
}
@Override
public void setConfig(){
CommentedYamlConfig tConfig=this.mPlugin.getConfigManager().getConfig();
int bind_menn_item=tConfig.getInt("OpenMainShop.BindItem",347);
this.mOpenItem=Material.getMaterial(bind_menn_item);
if(this.mOpenItem==null){
this.mPlugin.warn("绑定打开BossShop主商店的的物品["+bind_menn_item+"]不是一个有效的物品,将设置为默认值的347(钟表)");
tConfig.set("OpenMainShop.BindItem",347);
this.mPlugin.getConfigManager().saveConfig();
this.mOpenItem=Material.WATCH;
}else this.mPlugin.info("使用"+this.mOpenItem.name()+"作为打开BossShop主商店的的物品");
this.mSneakNeed=tConfig.getBoolean("OpenMainShop.SneakNeed");
}
}

View File

@ -0,0 +1,97 @@
package org.black_ixx.bossshop.listeners;
import java.util.HashMap;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSShop;
import org.black_ixx.bossshop.core.BSShopManager;
import org.black_ixx.bossshop.managers.StringManager;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import cc.util.bossshop.pluginmodel.INeedConfig;
public class SignListener implements Listener,INeedConfig{
private boolean mEnable;
private BossShop mPlugin;
public SignListener(BossShop plugin){
this.mPlugin=plugin;
this.mPlugin.getServer().getPluginManager().registerEvents(this,this.mPlugin);
this.mPlugin.registerConfigModel(this);
}
@Override
public void setConfig(){
this.mEnable=this.mPlugin.getConfigManager().signsEnabled();
}
private BSShop getBossShopSign(String line){
if(line==null||line=="") return null;
line=line.toLowerCase();
HashMap<String,BSShop> set=this.mPlugin.getManager(BSShopManager.class).getShops();
for(String s : set.keySet()){
BSShop shop=set.get(s);
if(line.endsWith(shop.getSignText().toLowerCase())) return shop;
}
return null;
}
@EventHandler
public void createSign(SignChangeEvent e){
if(!this.mEnable) return;
BSShop shop=getBossShopSign(e.getLine(0));
if(shop!=null){
if(shop.needPermToCreateSign()){
if(!e.getPlayer().hasPermission("BossShop.createSign")){
this.mPlugin.send(e.getPlayer(),this.mPlugin.getLangManager().getNode("Main.NoPermitToCreateSignShop"));
e.setCancelled(true);
return;
}
}
if(e.getLine(0)!=""){
e.setLine(0,StringManager.transform(e.getLine(0)));
}
if(e.getLine(1)!=""){
e.setLine(1,StringManager.transform(e.getLine(1)));
}
if(e.getLine(2)!=""){
e.setLine(2,StringManager.transform(e.getLine(2)));
}
if(e.getLine(3)!=""){
e.setLine(3,StringManager.transform(e.getLine(3)));
}
}
}
@EventHandler
public void interactSign(PlayerInteractEvent e){
if(!this.mEnable) return;
if(e.getClickedBlock()!=null){
if(e.getAction()==Action.RIGHT_CLICK_BLOCK){
Block b=e.getClickedBlock();
if(b.getType()==Material.SIGN||b.getType()==Material.SIGN_POST||b.getType()==Material.WALL_SIGN){
if(b.getState() instanceof Sign){
Sign s=(Sign)b.getState();
BSShop shop=getBossShopSign(s.getLine(0));
if(shop!=null){
if(e.getPlayer().hasPermission("BossShop.open")||e.getPlayer().hasPermission("BossShop.open.sign")){
this.mPlugin.getManager(BSShopManager.class).openShop(e.getPlayer(),shop);
return;
}
this.mPlugin.send(e.getPlayer(),this.mPlugin.getLangManager().getNode("Main.NoPermitToOpenSignShop"));
return;
}
}
}
}
}
}
}

View File

@ -0,0 +1,224 @@
package org.black_ixx.bossshop.lottery;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Random;
import java.util.Set;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSBuy;
import org.black_ixx.bossshop.core.BSEnums.BSBuyType;
import org.black_ixx.bossshop.managers.ShopCustomizer;
import org.black_ixx.bossshop.core.BSShop;
import org.black_ixx.bossshop.core.BSShopHolder;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
public class LotteryHolder extends BSShopHolder{
private int mStopCount=4;
private LotteryStatus mStatus=LotteryStatus.UNOPENED;
private final Set<Integer> mNowShow=new HashSet<>();
private Random mItemRandom=new Random(System.currentTimeMillis());
public LotteryHolder(BossShop pPlugin,Player pOwner,BSShop pShop){
super(pPlugin,pOwner,pShop);
}
/**
* 获取当前乐透状态
*/
public LotteryStatus getStatus(){
synchronized(this){
return this.mStatus;
}
}
/**
* 切换抽奖背包状态为LotteryStatus.RUNNING,并刷新一次
*/
public void startLottery(){
this.mStatus=LotteryStatus.RUNNING;
this.mStopCount=LotteryManager.mRefalshFastCount;
this.gotoNextFrame();
}
/**
* 重置乐透,切换抽奖背包状态为{@link LotteryStatus#WAIT}
*/
public void resetLottery(){
this.mStatus=LotteryStatus.UNOPENED;
this.mNowShow.clear();
this.mInv.clear();
this.updateInventory();
}
/**
* 关闭乐透,在背包关闭时调用,此时切换背包状态为{@link LotteryStatus#CLOSE}
*/
public void closeLottery(){
this.mInv.clear();
this.mStatus=LotteryStatus.CLOSE;
}
@Override
public BSBuy getShopItem(int pPos){
synchronized(this){
if(this.mStatus==LotteryStatus.WAIT){
BSBuy tBuy=super.getShopItem(pPos);
if(tBuy!=null&&tBuy.getBuyType()==BSBuyType.Lottery&&tBuy.getWeight()<=0) return tBuy;
else return null;
}else if(this.mStatus==LotteryStatus.RUNNING){
return null;
}else if(this.mStatus==LotteryStatus.RESULT){
return super.getShopItem(pPos);
}
return null;
}
}
/**
* 只在配置重载,或者背包打开时调用
* <p>
*1.同步更新配置到物品<br />
*2.用于在背包打开的时候切换holder从{@link LotteryStatus#UNOPENED}{@link LotteryStatus#WAIT}
* </p>
*/
@Override
public boolean updateInventory(){
synchronized(this){
if(!this.mShop.isShopValid()){
this.mInv.clear();
this.mOwner.closeInventory();
return false;
}
if(this.mStatus==LotteryStatus.UNOPENED){
this.mStatus=LotteryStatus.WAIT;
this.mStopCount=4;
if(!LotteryManager.existTask(this)){
ReflashInventoryTask tTask=new ReflashInventoryTask(this);
int tTaskId=Bukkit.getScheduler().scheduleAsyncRepeatingTask(BossShop.getInstance(),tTask,LotteryManager.mReflashBaseTicks,LotteryManager.mReflashBaseTicks);
LotteryManager.addTask(this,tTaskId);
this.mPlugin.debug("新增抽奖背包刷新任务");
}
return this.gotoNextFrame();
}
this.mPlugin.getManager(ShopCustomizer.class).updateInventory(this.mShop,this.mOwner,this.mInv,this.mNowShow);
return true;
}
}
/**
* 显示抽奖背包的下一帧动画
* <p>
* 在背包状态为{@link LotteryStatus#WAIT}{@link LotteryStatus#RUNNING}的时候调用<br />
* {@link LotteryStatus#RUNNING}状态的最后一帧动画时,由该函数切换状态为{@link LotteryStatus#RESULT}
* </p>
*/
public boolean gotoNextFrame(){
synchronized(this){
if(!this.mShop.isShopValid()){
this.mInv.clear();
this.mOwner.closeInventory();
return false;
}
if(this.mStatus==LotteryStatus.WAIT){
if(this.mStopCount<=0){
this.mInv.clear();
this.reselectMenuItem();
this.mPlugin.getManager(ShopCustomizer.class).updateInventory(this.mShop,this.mOwner,this.mInv,this.mNowShow);
this.mStopCount=LotteryManager.mReflashLowMultiple;
}
this.mStopCount--;
}else if(this.mStatus==LotteryStatus.RUNNING&&this.mStopCount>0){
this.mInv.clear();
this.reselectMenuItem();
this.mPlugin.getManager(ShopCustomizer.class).updateInventory(this.mShop,this.mOwner,this.mInv,this.mNowShow);
this.mStopCount--;
}else if(this.mStopCount<=0||this.mStatus==LotteryStatus.RESULT){
if(this.mStatus!=LotteryStatus.RESULT){
//一定要先清背包,再切换状态
this.mInv.clear();
this.mNowShow.clear();
this.mStatus=LotteryStatus.RESULT;
int result=this.getResultItem();
this.mNowShow.add(result);
this.mPlugin.debug("生成抽奖结果["+result+"]");
this.mPlugin.getManager(ShopCustomizer.class).updateInventory(this.mShop,this.mOwner,this.mInv,this.mNowShow);
}
}
return true;
}
}
/**
* 重新设置{@link LotteryHolder#mNowShow}的内容
* <p>
* 此函数不会自动刷新背包,需要自己调用刷新函数<br />
* 如果背包当前状态为{@link LotteryStatus#WAIT}状态时,会自动添加一个抽奖按钮到当前显示列表
* 该抽奖按钮的设置条件为类型={@link BSBuyType#Lottery}且weight为0,且是第一个,该物品的添加
* 不会影响显示比例<br />
* 如果概率显示物品的数量除按钮外为零个,那么如果存在可以显示的物品,显示物品会自少添加一个到显示列表
* </p>
*/
private void reselectMenuItem(){
HashSet<Integer> tOldItem=new HashSet<>();
tOldItem.addAll(this.mNowShow);
this.mNowShow.clear();
ArrayList<Integer> canShowItem=new ArrayList<>();
//第一遍循环找出所有可以显示给玩家的商品,如果是等待状态,添加抽奖按钮到显示列表
boolean find=false;
Random random=new Random();
int total=0;
for(Integer sPos : this.mShop.getMenuItemSet()){
BSBuy buy=this.mShop.getShopItem(sPos);
if(buy==null||!buy.disaplyToPlayer(this.mOwner)) continue;
if(buy.getBuyType()==BSBuyType.Lottery&&buy.getWeight()<=0){
if(this.mStatus==LotteryStatus.WAIT&&!find){
find=true;
this.mNowShow.add(sPos);
continue;
}else if(this.mStatus==LotteryStatus.RUNNING){
continue;
}
}
total++;
if(tOldItem.contains(sPos)) continue;
int tPos=random.nextInt(canShowItem.size()+1);
canShowItem.add(tPos,sPos);
}
int showCount=total*LotteryManager.mShowPrecent/100;
if(showCount<=0) showCount=1;
for(int index=0;index<showCount&&index<canShowItem.size();index++){
this.mNowShow.add(canShowItem.get(index));
}
}
/**
* 获取抽奖结果物品,使用权重算法
* <p>如果没有符合条件的物品将返回-1</p>
* @return 物品背包位置
*/
private int getResultItem(){
LinkedHashMap<Integer,Integer> weigthQueue=new LinkedHashMap<>();
//设置权重队列值
int addWeight=0;
for(Integer sPos : this.mShop.getMenuItemSet()){
BSBuy buy=this.mShop.getShopItem(sPos);
if(buy==null||buy.getWeight()<=0||!buy.disaplyToPlayer(this.mOwner)) continue;
addWeight+=buy.getWeight();
weigthQueue.put(addWeight,sPos);
}
if(weigthQueue.size()==0) return -1;
int findWeight=mItemRandom.nextInt(addWeight+1);
//确定是哪个物品
for(int sWeight : weigthQueue.keySet()){
if(sWeight<findWeight) continue;
return weigthQueue.get(sWeight);
}
return -1;
}
}

View File

@ -0,0 +1,83 @@
package org.black_ixx.bossshop.lottery;
import java.util.HashMap;
import org.black_ixx.bossshop.BossShop;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import cc.util.bossshop.pluginmodel.INeedConfig;
public class LotteryManager implements INeedConfig{
public static final String CFG_MAIN="LotterySystem";
public static final String CFG_ReflashBaseTicks="ReflashBaseTicks";
public static final String CFG_ReflashLowMultiple="ReflashLowMultiple";
public static final String CFG_RefalshFastCount="RefalshFastCount";
public static final String CFG_ShowPrecent="ShowPrecent";
public static int mReflashBaseTicks=5;
public static int mReflashLowMultiple=4;
public static int mRefalshFastCount=20;
public static int mShowPrecent=34;
private BossShop mPlugin;
public LotteryManager(BossShop pPlugin){
this.mPlugin=pPlugin;
this.mPlugin.registerConfigModel(this);
}
@Override
public void setConfig(){
ConfigurationSection tSec=this.mPlugin.getConfigManager().getConfig().getConfigurationSection(CFG_MAIN);
if(tSec==null) return;
mReflashBaseTicks=tSec.getInt(CFG_ReflashBaseTicks,mReflashBaseTicks);
if(mReflashBaseTicks<2) mShowPrecent=2;
mReflashLowMultiple=tSec.getInt(CFG_ReflashLowMultiple,mReflashLowMultiple);
if(mReflashLowMultiple<1) mReflashLowMultiple=1;
mRefalshFastCount=tSec.getInt(CFG_RefalshFastCount,mRefalshFastCount);
if(mRefalshFastCount<1) mRefalshFastCount=20;
mShowPrecent=tSec.getInt(CFG_ShowPrecent,mShowPrecent);
if(mShowPrecent<=0||mShowPrecent>50) mShowPrecent=34;
this.mPlugin.debug("已经重载抽奖配置:"+mReflashBaseTicks+"|"+mReflashLowMultiple+"|"+mRefalshFastCount+"|"+mShowPrecent);
}
/**
* 任务列表
* <p>
* 第一个参数为任务目标背包的持有者<br />
* 第二个参数为Bukkit任务ID
* </p>
*/
private final static HashMap<LotteryHolder,Integer> mTasks=new HashMap<>();
/**
* 添加一个任务到列表中
* @param pHolder 任务关联的holder
* @param pTaskId Bukkit任务Id
*/
public static void addTask(LotteryHolder pHolder,int pTaskId){
LotteryManager.mTasks.put(pHolder,pTaskId);
}
/**
* 尝试停止一个列表中的任务
* @param pHolder 任务关联的holder
*/
public static void stopTask(LotteryHolder pHolder){
Integer tTaskId=LotteryManager.mTasks.remove(pHolder);
if(tTaskId!=null){
Bukkit.getScheduler().cancelTask(tTaskId);
}
}
/**
* 检查holder是否已经有关联的任务存在
* @param pHolder 任务关联的holder
* @return 是否存在
*/
public static boolean existTask(LotteryHolder pHolder){
return LotteryManager.mTasks.containsKey(pHolder);
}
}

View File

@ -0,0 +1,25 @@
package org.black_ixx.bossshop.lottery;
public enum LotteryStatus{
/**
* 玩家未打开背包时
*/
UNOPENED,
/**
* 等待用户运行抽奖系统,当前状态为默认的,慢速循环显示物品的状态
*/
WAIT,
/**
* 正在运行抽奖状态,快速循环显示物品
*/
RUNNING,
/**
* 抽奖结果显示状态,只有一个物品被显示
*/
RESULT,
/**
* 背包在打开后被关闭状态
*/
CLOSE
}

View File

@ -0,0 +1,31 @@
package org.black_ixx.bossshop.lottery;
import org.bukkit.inventory.Inventory;
public class ReflashInventoryTask implements Runnable{
private final LotteryHolder mHolder;
private final Inventory mInv;
public ReflashInventoryTask(LotteryHolder pHolder){
this.mHolder=pHolder;
this.mInv=this.mHolder.getInventory();
}
@Override
public void run(){
LotteryStatus status=this.mHolder.getStatus();
if(this.mInv.getViewers().isEmpty()) this.stopTask();
if(status==LotteryStatus.WAIT||status==LotteryStatus.RUNNING){
this.mHolder.gotoNextFrame();
}else if(status==LotteryStatus.CLOSE){
this.stopTask();
}
//status==LotteryStatus.RESULT时等待,不关闭任务,可以为下次连续抽奖做准备
}
protected void stopTask(){
LotteryManager.stopTask(this.mHolder);
}
}

View File

@ -0,0 +1,94 @@
package org.black_ixx.bossshop.mail;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSEnums.BSBuyType;
import org.black_ixx.bossshop.managers.ItemNameManager;
import org.bukkit.inventory.ItemStack;
public class MailItem{
private BSBuyType mItemType;
/**
* 过期物品
* item-->ItemStack,money->int,point->int
*/
private Object mItem;
private String mSource;
/**
* 物品预览
*/
private String mPreview=null;
/**
* 构造一个Mail物品
* @param pItem 物品,允许Integer,List<ItemStack> ItemStack
* @param pSaleType 物品类型,只支持Item,points,money
* @param pCount 数量
* @param pSource 来源,用于生成预览
*/
public MailItem(Object pItem,BSBuyType pSaleType,int pCount,String pSource){
this.mItem=pItem;
this.mItemType=pSaleType;
this.mSource=pSource;
this.mPreview=this.resetItem(pCount);
}
protected String C(String pNode){
return BossShop.getInstance().getLangManager().getNode(pNode);
}
/**
* 创建邮件物品的预览
* @param pCount 数量
* @return 预览
*/
protected String resetItem(int pCount){
switch(this.mItemType){
case Money:
if(pCount>=1) this.mItem=((Integer)this.mItem)*pCount;
this.mPreview=this.mItem+C("Word.Money");
break;
case Points:
if(pCount>=1) this.mItem=((Integer)this.mItem)*pCount;
this.mPreview=this.mItem+C("Word.Points");
break;
case Item:
ItemStack tItem=null;
if(this.mItem instanceof List<?>) tItem=((List<ItemStack>)this.mItem).get(0);
else tItem=(ItemStack)this.mItem;
this.mItem=tItem;
if(pCount>=1) tItem.setAmount(tItem.getAmount()*pCount);
String itemname=BossShop.getInstance().getManager(ItemNameManager.class).getDisPlayName(tItem);
this.mPreview=tItem.getAmount()+C("Word.Count")+itemname;
break;
default:
BossShop.getInstance().warn(C("CFG.UnsupportMailItemType")+"["+this.mItemType.name()+"]");
}
this.mPreview=(StringUtils.isEmpty(mSource)?C("Mail.FromUnknow")+": ":this.mSource+": ")+this.mPreview;
return this.mPreview;
}
public String getPreview(){
return this.mPreview;
}
public String getSource(){
return this.mSource;
}
/**
* 邮件列表中的物品统一为一件
* @return
*/
public Object getItem(){
return this.mItem;
}
public BSBuyType getItemType(){
return this.mItemType;
}
}

View File

@ -0,0 +1,310 @@
package org.black_ixx.bossshop.mail;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.UUID;
import java.util.Map.Entry;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSBuy;
import org.black_ixx.bossshop.core.BSEnums;
import org.black_ixx.bossshop.core.BSEnums.BSBuyType;
import org.black_ixx.bossshop.managers.ItemStackCreator;
import org.black_ixx.bossshop.managers.WorthHandler;
import org.black_ixx.bossshop.nbt.NBTEditManager;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import cc.util.bossshop.config.CommentedYamlConfig;
import cc.util.bossshop.filemanager.AFileManager;
import cc.util.bossshop.pluginmodel.INeedConfig;
import cc.util.bossshop.pluginmodel.INeedReload;
public class MailManager extends AFileManager implements INeedConfig,INeedReload{
public static final String CFG_MAIN="MailSystem";
public static final String SEC_ItemType="Type";
public static final String SEC_ItemContent="Content";
public static final String SEC_Source="Source";
public static final String SEC_MaxSize="MaxSize";
public static final String SEC_SendCost="SendCost";
private int mMaxSize=10;
private int mSendCost=1000;
private final HashMap<UUID,ArrayList<MailItem>> mMailItems=new HashMap<>();
private long mLastReloadTime=0;
public MailManager(BossShop pPlugin){
super(pPlugin,"mail_item.yml","1.0");
this.mPlugin.registerConfigModel(this);
this.mPlugin.registerReloadModel(this);
}
public long getLastReloadTime(){
return this.mLastReloadTime;
}
@Override
public void setConfig(){
CommentedYamlConfig tConfig=this.mPlugin.getConfigManager().getConfig();
this.mMaxSize=tConfig.getInt(CFG_MAIN+"."+SEC_MaxSize,mMaxSize);
this.mSendCost=tConfig.getInt(CFG_MAIN+"."+SEC_SendCost,mSendCost);
}
@Override
public boolean reloadConfig(){
if(!super.reloadConfig()) return false;
this.mLastReloadTime=System.currentTimeMillis();
this.loadMailItem();
return true;
}
/**
* 从配置文件中载入邮件物品
*/
protected void loadMailItem(){
this.mMailItems.clear();
for(String player_key : this.mConfig.getKeys(false)){
ConfigurationSection player_sec=this.mConfig.getConfigurationSection(player_key);
if(player_sec==null){
this.mConfig.set(player_key,null);
continue;
}
UUID tUuid=null;
try{
tUuid=UUID.fromString(player_key);
}catch(Exception exp){
this.mPlugin.severe(ChatColor.RED+"配置文件["+this.mFileName+"]存在错误,["+player_key+"] 必须为UUID");
continue;
}
ArrayList<MailItem> list=new ArrayList<>();
for(String item_key : player_sec.getKeys(false)){
try{
ConfigurationSection item_sec=player_sec.getConfigurationSection(item_key);
if(item_sec==null) continue;
BSBuyType tItemType=BSEnums.getBSBuyType(item_sec.getString(SEC_ItemType));
Object tItem=null;
if(tItemType==null){
this.warn(C("CFG.UnsupportMailItemType")+"["+item_sec.getString(SEC_ItemType)+"]");
continue;
}
switch(tItemType){
case Money:
tItem=item_sec.get(SEC_ItemContent);
break;
case Points:
tItem=item_sec.get(SEC_ItemContent);
break;
case Item:
tItem=((BossShop)this.mPlugin).getManager(ItemStackCreator.class).createItemStackS(item_sec.getStringList(SEC_ItemContent),false);
if(tItem==null){
this.warn(C("CannotCreatMailItem"));
continue;
}
break;
default:
this.warn(C("CFG.UnsupportMailItemType")+"["+tItemType.name()+"]");
continue;
}
list.add(new MailItem(tItem,tItemType,1,item_sec.getString(SEC_Source)));
if(list.size()>=this.mMaxSize) break;
}catch(Exception exp){
this.mPlugin.severe(exp.getMessage(),exp);
}
}
this.mMailItems.put(tUuid,list);
}
}
/**
* 添加一封来自他人的邮件,调用前请先检查邮件是否已经满了
* <p>如果玩家在线,会提醒玩家有新邮件</p>
* @param pFrom 来自谁
* @param pTo 给谁
* @param pItem 物品
*/
public MailItem addMail(Player pFrom,Player pTo,ItemStack pItem){
MailItem tItem=new MailItem(pItem,BSBuyType.Item,1,C("Mail.FromPlayer")+pFrom.getName());
if(!this.addMailToFile(pTo.getUniqueId(),tItem)) return null;
this.addMail(pTo.getUniqueId(),tItem);
return tItem;
}
/**
* 添加过期物品到邮件列表,如果玩家在线会发送提醒
* @return 失败返回空
*/
public MailItem addMail(BSBuy pBuy,String pSource){
if(!pBuy.hasOwner()||pBuy.getLimit()<=0) return null;
if(this.isMailFull(pBuy.getOwner())){
this.noticeMailFull(pBuy.getOwner());
return null;
}
MailItem tItem=new MailItem(pBuy.getReward(),pBuy.getBuyType(),pBuy.getLimit(),pSource);
if(!this.addMailToFile(pBuy.getOwner(),tItem)) return null;
this.addMail(pBuy.getOwner(),tItem);
return tItem;
}
/**
* 添加邮件到邮件列表,调用前必须检查isMailFull<br />
* 在此函数中统一发送通知消息
*/
private void addMail(UUID pUUID,MailItem pItem){
ArrayList<MailItem> tItems=this.mMailItems.get(pUUID);
if(tItems==null){
tItems=new ArrayList<>();
this.mMailItems.put(pUUID,tItems);
}
tItems.add(pItem);
Player tPlayer=Bukkit.getPlayer(pUUID);
if(tPlayer!=null&&tPlayer.isOnline()){
this.mPlugin.send(tPlayer,C("Mail.YouReciveMail").replace("%where%",pItem.getSource()));
//tPlayer.playSound(tPlayer.getLocation(),org.bukkit.Sound.ENTITY_PLAYER_LEVELUP,1,1);
}
}
/**
* 玩家邮箱是否达到了数量上限
*/
public boolean isMailFull(UUID pUUID){
if(this.mMaxSize<=0) return true;
ConfigurationSection tUserSec=this.mConfig.getConfigurationSection(pUUID.toString());
if(tUserSec==null) return false;
return tUserSec.getKeys(false).size()>=this.mMaxSize;
}
/**
* 通知玩家邮箱已经满了
* @param pUUID
*/
public void noticeMailFull(UUID pUUID){
Player tPlayer=Bukkit.getPlayer(pUUID);
if(tPlayer==null||!tPlayer.isOnline()) return;
this.mPlugin.send(tPlayer,C("YouMailIsFull"));
}
public void noticeExistMail(Player pPlayer){
if(pPlayer==null||!pPlayer.isOnline()) return;
int mailCount=this.getMailCount(pPlayer.getUniqueId());
if(mailCount<=0) ;//TODO 你没有邮件
else ; //TODO 你有邮件
}
/**
* 添加邮件到文件,调用前必须检查isMailFull
* @param pUUID 玩家UUID
* @param pItem 邮件
*/
protected boolean addMailToFile(UUID pUUID,MailItem pItem){
ConfigurationSection tUserSec=this.mConfig.getConfigurationSection(pUUID.toString());
if(tUserSec==null) tUserSec=this.mConfig.createSection(pUUID.toString());
long time=System.currentTimeMillis()/1000;
String tItemLabel="item_"+time;
while(tUserSec.contains(tItemLabel))
tItemLabel="item_"+(++time);
ConfigurationSection tItemSec=tUserSec.createSection(tItemLabel);
tItemSec.set(SEC_ItemType,pItem.getItemType().name());
switch(pItem.getItemType()){
case Money:
case Points:
tItemSec.set(SEC_ItemContent,pItem.getItem());
break;
case Item:
ItemStack item=(ItemStack)pItem.getItem();
ArrayList<String> tItemInfo=new ArrayList<>();
tItemInfo.add("id:"+item.getTypeId());
tItemInfo.add("durability:"+item.getDurability());
tItemInfo.add("amount:"+item.getAmount());
String nbtlabel=((BossShop)this.mPlugin).getManager(NBTEditManager.class).addItemNBTToStock(item,true);
if(nbtlabel!=null) tItemInfo.add("nbt:"+nbtlabel);
tItemSec.set(SEC_ItemContent,tItemInfo);
break;
default:
this.warn(ChatColor.RED+"["+pItem.getItemType().name()+"]");
this.warn(C("Mail.UnsupportMailItemType"));
tUserSec.set(tItemLabel,null);
return false;
}
tItemSec.set(SEC_Source,pItem.getSource());
this.saveConfig();
return true;
}
/**
* 返回玩家所有过期几首物品的预览
* @param pUUID 玩家UUID
* @return 过期物品预览列表,或没有邮件的消息
*/
public ArrayList<String> checkMail(UUID pUUID){
ArrayList<String> items_preview=new ArrayList<>();
for(Entry<UUID,ArrayList<MailItem>> entry : this.mMailItems.entrySet()){
if(entry.getKey().equals(pUUID)){
int i=1;
for(MailItem sitem : entry.getValue()){
items_preview.add(i+". "+sitem.getPreview());
i++;
}
break;
}
}
if(items_preview.size()!=0){
items_preview.add(0,C("Mail.MailMaxSaveNumb").replace("%numb%",items_preview.size()+"/"+this.mMaxSize));
items_preview.add(items_preview.size(),"====================");
}else items_preview.add(C("Mail.YouHaveNoMail"));
return items_preview;
}
public int getMailCount(UUID pUUID){
for(Entry<UUID,ArrayList<MailItem>> entry : this.mMailItems.entrySet()){
if(entry.getKey().equals(pUUID)){
return entry.getValue().size();
}
}
return 0;
}
/**
* 返还寄售过期的物品
*/
public void reciveMail(Player player){
if(player==null) return;
UUID tUuid=player.getUniqueId();
WorthHandler wHandler=((BossShop)this.mPlugin).getManager(WorthHandler.class);
for(UUID key : this.mMailItems.keySet()){
if(key.equals(tUuid)){
boolean tIsItem=false;
for(MailItem item : this.mMailItems.get(key)){
switch(item.getItemType()){
case Money:
wHandler.giveRewardMoney(player,(Integer)item.getItem());
break;
case Points:
wHandler.giveRewardPoints(player,(Integer)item.getItem());
break;
case Item:
tIsItem=true;
wHandler.giveRewardItem(player,(ItemStack)item.getItem());
break;
default:
break;
}
this.mPlugin.send(player,ChatColor.GREEN+C("Word.Revive")+item.getPreview());
}
if(tIsItem&&((BossShop)this.mPlugin).getConfigManager().isAutoClearNBT())
((BossShop)this.mPlugin).getManager(NBTEditManager.class).clearNBT();
this.mMailItems.remove(key);
this.mConfig.set(tUuid.toString(),null);
this.saveConfig();
return;
}
}
}
public int getMailSendCost(){
return this.mSendCost;
}
}

View File

@ -0,0 +1,355 @@
package org.black_ixx.bossshop.managers;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import org.apache.commons.lang.StringUtils;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSBuy;
import org.black_ixx.bossshop.core.BSBuyParameter;
import org.black_ixx.bossshop.core.BSShop;
import org.black_ixx.bossshop.core.BSEnums.BSBuyType;
import org.black_ixx.bossshop.core.BSEnums.BSPriceType;
import org.black_ixx.bossshop.misc.Enchant;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
/**
* 用于从商品节点上创建菜单物品和回报物品
* @author 聪聪
*
*/
public class BuyItemHandler{
private BossShop mPlugin;
private final static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm");
public BuyItemHandler(BossShop pPlugin){
this.mPlugin=pPlugin;
}
private static Date getDate(String str){
if(str==null) return null;
Date date=null;
try{
date=sdf.parse(str);
}catch(ParseException pexp){}
return date;
}
@SuppressWarnings({"unchecked","deprecation"})
public BSBuy createBuyItem(BSShop shop,ConfigurationSection c){
String stage="Basic Data";
String name=c.getName();
ItemStackCreator itemCteator=this.mPlugin.getManager(ItemStackCreator.class);
try{
BSBuyParameter parameter=new BSBuyParameter();
parameter.name=name;
parameter.shop=shop;
parameter.msg=c.getString("Message");
if(parameter.weight<0) parameter.weight=0;
String str_uuid=c.getString("Owner");
if(str_uuid!=null){
try{
parameter.owner=UUID.fromString(str_uuid);
}catch(Exception exp){
this.mPlugin.severe("配置文件"+shop.getConfigFilename()+"存在错误,["+str_uuid+"]不是一个合法的UUID",exp);
}
}
parameter.hideNoStock=c.getBoolean("HideNoStock",false);
parameter.hideNotTime=c.getBoolean("HideNotTime",false);
if(c.contains("HideItemFlag"))
parameter.hideItemFlag=c.getInt("HideItemFlag");
else parameter.hideItemFlag=this.mPlugin.getConfigManager().getHideItemFlag();
parameter.permission=c.getString("ExtraPermission");
parameter.weight=c.getInt("Weight",0);
if(StringUtils.isEmpty(parameter.permission)) parameter.permission=null;
parameter.numberLimit=c.getInt("NumberLimit",-1);
parameter.personalLimit=c.getInt("PersonalLimit",-1);
ConfigurationSection time=c.getConfigurationSection("TimeLimit");
if(time!=null){
parameter.startTime=BuyItemHandler.getDate(time.getString("start"));
parameter.stopTime =BuyItemHandler.getDate(time.getString("stop"));
}
parameter.location=c.getInt("InventoryLocation")-1;
if(parameter.location<0){
parameter.location=0;
this.mPlugin.warn("商店物品["+name+"]的背包位置["+parameter.location+"]不正确,已经设置为1号位置");
}
stage="获取商品类型";
String rewardType=c.getString("RewardType");
for(BSBuyType type : BSBuyType.values()){
if(rewardType.equalsIgnoreCase(type.name())){
parameter.buyT=type;
break;
}
}
if(parameter.buyT==null){
this.mPlugin.severe("无法创建商品["+name+"],["+rewardType+"]不是受支持商品类型");
this.mPlugin.severe("支持的商品类型有");
for(BSBuyType type : BSBuyType.values()){
this.mPlugin.severe("-"+type.name());
}
return null;
}
stage="获取价格类型";
String priceType=c.getString("PriceType");
for(BSPriceType type : BSPriceType.values()){
if(priceType.equalsIgnoreCase(type.name())){
parameter.priceT=type;
break;
}
}
if(parameter.priceT==null){
this.mPlugin.severe("无法创建商品["+name+"],["+priceType+"]不是受支持的价格类型");
this.mPlugin.severe("支持的价格类型又:");
for(BSPriceType type : BSPriceType.values()){
this.mPlugin.severe("-"+type.name());
}
return null;
}
parameter.price=c.get("Price");
parameter.reward=c.get("Reward");
stage="创建奖励物品";
switch(parameter.buyT){
case Item:
if(!(parameter.reward instanceof List<?>)){
this.mPlugin.severe("无法创建商品["+name+"],["+parameter.reward+"]不是List,物品类型的商品必须为List,参见 ( dev.bukkit.org/bukkit-plugins/bossshop/pages/setup-guide/ )");
return null;
}
List<?> l=(List<?>)parameter.reward;
boolean b=false;
for(Object o : l){
if(o instanceof List<?>){
b=true;
break;
}
}
// Wenn Liste korrekt ist: List<List<String>>
if(b){
List<ItemStack> items=new ArrayList<ItemStack>();
for(List<String> s : (List<List<String>>)parameter.reward){
items.add(itemCteator.createItemStackS(s,false));
}
parameter.reward=items;
}else{
// Wenn es eine Liste gibt, in der aber keine weitere Liste
// ist
List<ItemStack> items=new ArrayList<ItemStack>();
items.add(itemCteator.createItemStackS((List<String>)parameter.reward,false));
parameter.reward=items;
}
break;
case TimeCommand:
HashMap<Integer,String> cmds=new HashMap<Integer,String>();
// Wenn reward = List<String>
if(parameter.reward instanceof List<?>){
for(String s : (List<String>)parameter.reward){
try{
String[] parts=s.split(":",2);
String a1=parts[0].trim();
int i=Integer.parseInt(a1);
String cmd=parts[1].trim();
cmds.put(i,cmd);
}catch(Exception e){
this.mPlugin.severe("无法创建商品["+name+"],["+s+"]不是一个合法的(TimeCommand),类型商品,正确的格式应该是: <时间>:<命令> 例如 600:ban %name%");
return null;
}
}
}else{
if(!(parameter.reward instanceof String)){
this.mPlugin.severe("无法创建商品["+name+"],["+parameter.reward+"]不是一个合法的(TimeCommand)类型商品,正确的格式应该是: <时间>:<命令> 例如 600:ban %name%");
return null;
}
String s=(String)parameter.reward;
String[] parts=s.split(":",2);
String a1=parts[0].trim();
int i=Integer.parseInt(a1);
String cmd=parts[1].trim();
cmds.put(i,cmd);
}
parameter.reward=cmds;
break;
case Shop:
if(parameter.reward instanceof String){
String x=(String)parameter.reward;
parameter.reward=x.toLowerCase();
}else{
this.mPlugin.severe("无法创建商品["+name+"],["+parameter.reward+"]不是正确的(shop)类型商品");
return null;
}
break;
case Command:
if(!(parameter.reward instanceof List<?>)){
if(!(parameter.reward instanceof String)){
this.mPlugin.severe("无法创建商品["+name+"],["+parameter.reward+" 不是正确的(Command)类型商品");
return null;
}
List<String> li=new ArrayList<String>();
li.add((String)parameter.reward);
parameter.reward=li;
}
break;
case PlayerCommand:
if(!(parameter.reward instanceof List<?>)){
if(!(parameter.reward instanceof String)){
this.mPlugin.severe("无法创建商品["+name+"! "+parameter.reward+" (PlayerCommand) is no valid Reward list! It needs to be a list of commands!");
return null;
}
List<String> li=new ArrayList<String>();
li.add((String)parameter.reward);
parameter.reward=li;
}
break;
case Money:
if(!(parameter.reward instanceof Double)&!(parameter.reward instanceof Integer)){
try{
parameter.reward=Double.parseDouble((String)(parameter.reward));
}catch(Exception exc){
this.mPlugin.severe("无法创建商品["+name+"! "+parameter.reward+" (Money) is no valid Reward number!");
return null;
}
}
break;
case Points:
if(!(parameter.reward instanceof Integer)){
try{
parameter.reward=Integer.parseInt((String)(parameter.reward));
}catch(Exception exc){
this.mPlugin.severe("无法创建商品["+name+"! "+parameter.reward+" (Points) is no valid parameter.reward number!");
return null;
}
}
break;
case Permission:
if(!(parameter.reward instanceof List<?>)){
if(!(parameter.reward instanceof String)){
this.mPlugin.severe("无法创建商品["+name+"! "+parameter.reward+" (Permissions) is no valid parameter.reward list! It needs to be a list of permissions!");
return null;
}
List<String> li=new ArrayList<String>();
li.add((String)parameter.reward);
parameter.reward=li;
}
break;
case Enchantment:
if(!(parameter.reward instanceof String)){
this.mPlugin.severe("无法创建商品["+name+"! "+parameter.reward+" (Enchantment) is no valid parameter.reward line! It needs to be a text line looking like this: <enchantmenttype/enchantmentid>#<level>!");
return null;
}
String line=(String)parameter.reward;
String parts[]=line.split("#",2);
if(parts.length!=2){
this.mPlugin.severe("无法创建商品["+name+"! "+parameter.reward+" (Enchantment) is no valid parameter.reward line! It needs to be a text line looking like this: <enchantmenttype/enchantmentid>#<level>!");
return null;
}
String p_a=parts[0].trim();
String p_b=parts[1].trim();
int lvl=0;
Enchantment enchantment=null;
try{
lvl=Integer.parseInt(p_b);
}catch(Exception e){
this.mPlugin.severe("无法创建商品["+name+"! "+parameter.reward+" (Enchantment) is no valid parameter.reward line! Invalid level! It needs to be a number!");
return null;
}
int ench=-1;
try{
ench=Integer.parseInt(p_a);
}catch(Exception e){}
if(ench>=0){
enchantment=Enchantment.getById(ench);
}
if(enchantment==null){
enchantment=Enchantment.getByName(p_a);
}
if(enchantment==null){
this.mPlugin.severe("无法创建商品["+name+"! "+parameter.reward+" (Enchantment) is no valid Reward line! Enchantment not found! Here you can find the right enchantment names: http://jd.bukkit.org/doxygen/db/dbe/namespaceorg_1_1bukkit_1_1enchantments.html");
return null;
}
parameter.reward=new Enchant(enchantment,lvl);
break;
default:
break;
}
stage="创建价格";
switch(parameter.priceT){
case Item:
if(!(parameter.price instanceof List<?>)){
this.mPlugin.severe("无法创建商品["+name+"! "+parameter.price+" (Item) is no valid parameter.price Item List! There has to be a list of ItemData ( dev.bukkit.org/bukkit-plugins/bossshop/pages/setup-guide/ )");
return null;
}
List<?> l=(List<?>)parameter.price;
boolean b=false;
for(Object o : l){
if(o instanceof List<?>){
b=true;
}
}
// Wenn Liste korrekt ist: List<List<String>>
if(b){
List<ItemStack> items=new ArrayList<ItemStack>();
for(List<String> s : (List<List<String>>)parameter.price){
items.add(itemCteator.createItemStackS(s,false));
}
parameter.price=items;
}else{
// Wenn es eine Liste gibt, in der aber keine weitere Liste
// ist
List<ItemStack> items=new ArrayList<ItemStack>();
items.add(itemCteator.createItemStackS((List<String>)parameter.price,false));
parameter.price=items;
}
break;
case Free:
break;
case Nothing:
break;
case Exp:
if(!(parameter.price instanceof Integer)){
try{
parameter.price=Integer.parseInt((String)(parameter.price));
}catch(Exception exc){
this.mPlugin.severe("无法创建商品["+name+"! "+parameter.price+" (Exp) is no valid parameter.price number!");
return null;
}
}
break;
case Money:
if(!(parameter.price instanceof Double)&!(parameter.price instanceof Integer)){
try{
parameter.price=Double.parseDouble((String)(parameter.price));
}catch(Exception exc){
this.mPlugin.severe("无法创建商品["+name+"! "+parameter.price+" (Money) is no valid parameter.price number!");
return null;
}
}
break;
case Points:
if(!(parameter.price instanceof Integer)){
try{
parameter.price=Integer.parseInt((String)(parameter.price));
}catch(Exception exp){
this.mPlugin.severe("无法创建商品["+name+"! "+parameter.price+" (Points) is no valid parameter.price number!");
return null;
}
}
break;
}
return new BSBuy(this.mPlugin,parameter);
}catch(Throwable exp){
this.mPlugin.severe("无法创建商品 "+name+"! 在步骤 '"+stage+"',可能是由于错误的插件配置",exp);
return null;
}
}
}

View File

@ -0,0 +1,165 @@
package org.black_ixx.bossshop.managers;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.lottery.LotteryManager;
import org.black_ixx.bossshop.mail.MailManager;
import org.black_ixx.bossshop.sale.SaleManager;
import cc.util.bossshop.filemanager.AConfigManager;
public class ConfigManager extends AConfigManager{
private boolean signs;
private boolean ic_hide;
private boolean transaction_log;
private boolean allow_unsafe_enchantments;
private boolean debug;
private String mainshop;
private int mCoolTime=5;
private boolean mAutoClearNBT=true;
private int mHideItemFlag=63;
private int mShopOpenDelay=0;
private BossShop plugin;
public ConfigManager(BossShop pplugin){
super(pplugin,"1.4");
this.reloadConfig();
}
@Override
public boolean reloadConfig(){
if(!super.reloadConfig()) return false;
this.checkUpdate();
this.addDefaults();
this.saveConfig();
this.signs=this.mConfig.getBoolean("signs.enabled")||this.mConfig.getBoolean("EnableSigns");
this.mainshop=this.mConfig.getString("MainShop","Menu");
this.ic_hide=this.mConfig.getBoolean("HideItemsPlayersDoNotHavePermissionsFor",false);
this.transaction_log=this.mConfig.getBoolean("EnableTransactionLog",false);
this.allow_unsafe_enchantments=this.mConfig.getBoolean("AllowUnsafeEnchantments",false);
this.mCoolTime=this.mConfig.getInt("CoolTime",5);
this.debug=this.mConfig.getBoolean("debug",false);
this.mAutoClearNBT=this.mConfig.getBoolean("AutoClearNBT",true);
this.mHideItemFlag=this.mConfig.getInt("HideItemFlag",63);
this.mShopOpenDelay=this.mConfig.getInt("OpenShopDelay",0);
this.mShopOpenDelay/=50;
return true;
}
protected boolean checkUpdate(){
String tVersion=this.mConfig.getString(SEC_CFG_VERSION,"1.0");
if(tVersion.compareToIgnoreCase(this.mVersion)>=0) return false;
if(tVersion.compareToIgnoreCase("1.0")==0){// 1.0-->1.1
tVersion="1.1";
Object obj=this.mConfig.get("SaleSystem.OutDateItemNumbLimit");
if(obj!=null) this.mConfig.set("MailSystem.MaxSize",obj);
this.mConfig.set("SaleSystem.OutDateItemNumbLimit",null);
obj=this.mConfig.get("SaleSystem.AutoClearNBT");
if(obj!=null) this.mConfig.set("AutoClearNBT",true);
this.mConfig.set("SaleSystem.AutoClearNBT",null);
}
if(tVersion.compareToIgnoreCase("1.1")==0){// 1.1-->1.2
tVersion="1.2";
int coolTime=this.mConfig.getInt("CoolTime",1);
this.mConfig.set("CoolTime",coolTime*1000);
}
if(tVersion.compareToIgnoreCase("1.2")==0){// 1.2-->1.3
tVersion="1.3";
int item=this.mConfig.getInt("BindMenuItem");
this.mConfig.set("BindMenuItem",null);
this.mConfig.set("OpenMainShop.BindItem",item);
}
if(tVersion.compareToIgnoreCase("1.3")==0){// 1.3-->1.4
tVersion="1.4";
this.mConfig.set("AutoClearNBT",null);
this.mConfig.set("DisableUpdateNotifications",null);
}
this.mConfig.set(SEC_CFG_VERSION,this.mVersion);
return true;
}
public void addDefaults(){
super.addDefaults();
this.mConfig.addDefault("EnableSigns",true,"启用贴牌创建BossShop商店入口");
this.mConfig.addDefault("LogPrefix","[BossShop]","用于日志输出前缀,基本不用");
this.mConfig.addDefault("MsgPrefix","&c[&7&l商店&c]&b","前台聊天以及后台大部分输出的前缀");
this.mConfig.addDefault("MainShop","Menu","BossShop主商店");
this.mConfig.addDefault("ItemNameLang","zh_CN","物品名字翻译语言,用于寄售物品和邮件 时候使用","当前支持zh_CN,zh_TW,en_US,其中en_US翻译不需要依赖文件,且翻译准确","更多翻译支持请到.minecraft/assets/objects下找到对应的翻译文件,更改名字格式然后复制到插件目录就可以了","此项配置的原版物品名字需要靠ItemName_xx_XX文件,mod物品名字会自动获取","部分mod或mod物品可能存在翻译问题,比如怪物蛋(但是英文是肯定对的)","如果整个mod不能翻译,可能是该mod里没有对应的语言文件","此项配置需要重载整个插件才能使原版翻译生效","可以在手上拿着物品时输入/BS name查看手上的物品的翻译");
this.mConfig.addDefault("OpenMainShop.BindItem",347,"打开BossShop主商店的物品");
this.mConfig.addDefault("OpenMainShop.SneakNeed",true,"使用物品打开商店时是否需要潜行");
this.mConfig.addDefault("OpenShopDelay",0,"命令打开商店的延迟","用来兼容例如时钟命令等插件");
this.mConfig.addDefault("HideItemsPlayersDoNotHavePermissionsFor",false,"隐藏玩家没有权限购买的物品");
this.mConfig.addDefault("EnableTransactionLog",false,"启用交易记录");
this.mConfig.addDefault("AllowUnsafeEnchantments",false,"允许不安全的附魔");
this.mConfig.addDefault("MultiplierGroups.Enabled",false);
this.mConfig.addDefault("MultiplierGroups.List",new String[]{"Permission.Node:<type>:<multiplier>","BossShop.PriceMultiplier.Points1:points:0.75","BossShop.PriceMultiplier.Points1:points:0.5","BossShop.PriceMultiplier.Money1:money:0.75","BossShop.PriceMultiplier.Money2:money:0.5","BossShop.PriceMultiplier.MoneyNegative:money:2.0","BossShop.PriceMultiplier.Exp:exp:0.8",});
this.mConfig.addDefault(SaleManager.CFG_MAIN+"."+SaleManager.CFG_ShopBaseName,"SYSTEM_SALE","寄售系统主配置");
this.mConfig.addDefault(SaleManager.CFG_MAIN+"."+SaleManager.CFG_ShopSize,54,"寄售商店大小","必须为9的整数,不超过81,而且商店最后两格需要留空用来制作导航按钮","一旦设置过大小并创建了寄售商店后,就不要改这个值了,除非同时修改商店文件,不然导航功能会失效");
this.mConfig.addDefault(SaleManager.CFG_MAIN+"."+SaleManager.CFG_ShopMaxNumb,2,"寄售商店最大数量");
this.mConfig.addDefault(SaleManager.CFG_MAIN+"."+SaleManager.CFG_MoneyPoundage,5,"金币收入手续费,百分比0-99");
this.mConfig.addDefault(SaleManager.CFG_MAIN+"."+SaleManager.CFG_PointsPoundage,5,"点券收入手续费,百分比0-99");
this.mConfig.addDefault(SaleManager.CFG_MAIN+"."+SaleManager.CFG_MoneyItem,9,"金币寄售默认显示的物品,只支持数值,不支持12:3的类型");
this.mConfig.addDefault(SaleManager.CFG_MAIN+"."+SaleManager.CFG_PointsItem,10,"点券寄售默认显示的物品,只支持数值,不支持12:3的类型");
this.mConfig.addDefault(SaleManager.CFG_MAIN+"."+SaleManager.CFG_SaleTime,86400,"默认寄售时长(秒),这里是一天");
this.mConfig.addDefault(SaleManager.CFG_MAIN+"."+SaleManager.CFG_UnsaleCost,1000,"下架需要花费的金币数量,默认没有下架权限","权限BossShop.unsale.user: 下架自己物品的权限","权限BossShop.unsale.admin: 下架所有人物品的权限,并且不要支付下架花费");
this.mConfig.addDefault(SaleManager.CFG_MAIN+"."+SaleManager.CFG_UnsaleCount,3,"每天的下架数量限制,拥有BossShop.unsale.admin的使人可以无视该权限","下架记录保存在buyRecord.yml文件中");
this.mConfig.addDefault(SaleManager.CFG_MAIN+"."+SaleManager.CFG_PerOneSaleLimit,3,"个人允许最多同时寄售物品数量的上限,如果玩家有BossShop.sale.unlimited权限可以无限寄售");
this.mConfig.addDefault(SaleManager.CFG_MAIN+"."+SaleManager.CFG_SaleItemName,"&2寄售: %bs_sale_item_sigle_count% %bs_sale_item_name%","设置寄售物品的显示格式","如果一行中有空格的话需要用单引号把整句括起来","可用的变量,SaleItemLore中也可以使用这些变量","%bs_sale_owner_name% 寄售者的名字","%bs_sale_item_id% 寄售物品的编号","%bs_sale_item_sigle_count% 寄售物品单份数量","%bs_sale_item_part_count% 寄售物品份数","%bs_sale_item_type% 寄售物品类型,[金币,点券,物品],如果要修改这几个请转到语言列表的Word节点","%bs_sale_item_name% 寄售物品名字,[金币,点券,物品英文名],前两项同上,最后一项没办法,获取不到中文显示用的名字","%bs_sale_price% 寄售物品价格,这个只显示数字","%bs_sale_price_type% 寄售物品类型,[金币,点券],要修改同上上");
this.mConfig.addDefault(SaleManager.CFG_MAIN+"."+SaleManager.CFG_SaleItemLore,new String[]{"&3寄售者: %bs_sale_owner_name%","&2寄售编号: %bs_sale_item_id%","&c价格: %bs_sale_price% %bs_sale_price_type%"},"设置寄售物品的lore格式,时间限制和数量限制为默认lore,如果需要修改请转到语言文件","lore最好加上颜色,不然默认是斜体紫色,丑!","lore默认显示在物品属性下面,过期信息,数量限制等信息的上面");
this.mConfig.addDefault(MailManager.CFG_MAIN+"."+MailManager.SEC_MaxSize,10,"邮箱大小,超过此大小的物品将不会保存");
this.mConfig.addDefault(MailManager.CFG_MAIN+"."+MailManager.SEC_SendCost,1000,"发送邮件的花费(金币)");
this.mConfig.addDefault(LotteryManager.CFG_MAIN+"."+LotteryManager.CFG_ReflashBaseTicks,5,"基础Ticks,多少Ticks快速刷新一次背包");
this.mConfig.addDefault(LotteryManager.CFG_MAIN+"."+LotteryManager.CFG_ReflashLowMultiple,4,"预览抽奖时,过了多少倍ReflashBaseTicks后刷新一次背包");
this.mConfig.addDefault(LotteryManager.CFG_MAIN+"."+LotteryManager.CFG_RefalshFastCount,20,"进行抽奖时,刷新背包多少次");
this.mConfig.addDefault(LotteryManager.CFG_MAIN+"."+LotteryManager.CFG_ShowPrecent,34,"抽奖以及未抽奖时,物品显示比例,最高50,交替显示(50的话就只有两个显示样子了)");
this.mConfig.addDefault("AutoClear.NBTExpiredDays",7,"NBT过期天数,超过该天数未被引用而且是自动创建的NBT会被清理");
this.mConfig.addDefault("HideItemFlag",63,"隐藏寄售物品的攻击效果等属性"," 1|0.HIDE_ENCHANTS 附魔"," 2|1.HIDE_ATTRIBUTES 前缀"," 4|2.HIDE_UNBREAKABLE 不可破坏"," 8|3.HIDE_DESTROYS, 受损度","16|4.HIDE_PLACED_ON, 放置","32|5.HIDE_POTION_EFFECTS 药水效果","如何隐藏物品的状态??如果想隐藏相应的属性,只要把前面的数字加起来就可以了,如果要全部隐藏,就是63(默认)","注意此项设置只在1.8.3及其以后的版本有效,低版本的只有设置0和非零来开启全部或关闭全部显示,不能选择关闭什么","更低版本的可能不支持关闭","上面的表也可能存在错误就是前面的数字对应的不是这个属性的隐藏");
this.mConfig.addDefault("PointsPlugin","auto-detect","可选[PlayerPoints,PointsAPI,EnjinMinecraftPlugin,CommandPoints]","如果是[auto-detect],将会自动选择");
this.mConfig.addDefault("CoolTime",200,"玩家点击商品的间隔(毫秒),无论是否购买成功,都会重复点击会重新计时");
}
public boolean signsEnabled(){
return signs;
}
public String getMainShop(){
return mainshop;
}
public boolean hideNoPermitItem(){
return ic_hide;
}
public boolean transactionLogEnabled(){
return transaction_log;
}
public boolean allowUnsafeEnchantments(){
return allow_unsafe_enchantments;
}
public boolean debug(){
return this.debug;
}
public int getCoolTime(){
return this.mCoolTime;
}
public boolean isAutoClearNBT(){
return this.mAutoClearNBT;
}
public int getHideItemFlag(){
return this.mHideItemFlag;
}
/**
* 商店打开延迟,单位为tick
*/
public int getShopOpenDelay(){
return this.mShopOpenDelay<0?0:this.mShopOpenDelay;
}
}

View File

@ -0,0 +1,519 @@
package org.black_ixx.bossshop.managers;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSShop;
import org.black_ixx.bossshop.core.BSShopManager;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import com.mysql.jdbc.StringUtils;
import cc.util.bossshop.config.CommentedYamlConfig;;
public class DefaultCreator{
public static void addDefault(CommentedYamlConfig config,String name,String rewardType,String priceType,Object reward,Object price,List<String> menuitem,String message,int loc,String permission){
ConfigurationSection c=config.createSection("shop."+name);
c.set("RewardType",rewardType);
c.set("PriceType",priceType);
c.set("Price",price);
c.set("Reward",reward);
c.set("MenuItem",menuitem);
c.set("Message",message);
c.set("InventoryLocation",loc);
c.set("ExtraPermission",permission);
}
public static void addDefault(CommentedYamlConfig config,String name,String rewardType,String priceType,Object reward,Object price,List<String> menuitem,String message,int loc,String permission,String extra_node,Object extra_object){
ConfigurationSection c=config.createSection("shop."+name);
c.set("RewardType",rewardType);
c.set("PriceType",priceType);
c.set("Price",price);
c.set("Reward",reward);
c.set("MenuItem",menuitem);
c.set("Message",message);
c.set("InventoryLocation",loc);
c.set("ExtraPermission",permission);
c.set(extra_node,extra_object);
}
private File getFile(String name){
return new File(BossShop.getInstance().getDataFolder().getAbsolutePath()+"/shops/"+name);
}
private CommentedYamlConfig getConfig(File f){
CommentedYamlConfig tConfig=new CommentedYamlConfig();
tConfig.loadFromFile(f);
return tConfig;
}
public static List<String> createMenuItem(String name,String lore,String material,String add){
List<String> item=new ArrayList<String>();
item.add("type:"+material);
item.add("amount:1");
item.add("name:"+name);
if(!StringUtils.isNullOrEmpty(lore)) item.add("lore:"+lore);
if(!StringUtils.isNullOrEmpty(add)) item.add(add);
return item;
}
public static List<String> createMenuItem(String name,String lore,String material,String add,String add2){
List<String> item=new ArrayList<String>();
item.add("type:"+material);
item.add("amount:1");
item.add("name:"+name);
item.add("lore:"+lore);
if(add!=""){
item.add(add);
item.add(add2);
}
return item;
}
public static List<String> createMenuItem(String name,String lore,String material,String add,String add2,String add3){
List<String> item=new ArrayList<String>();
item.add("type:"+material);
item.add("amount:1");
item.add("name:"+name);
item.add("lore:"+lore);
if(add!=""){
item.add(add);
item.add(add2);
item.add(add3);
}
return item;
}
public static List<List<String>> createItem(String name,String lore,String material,String add,String add2){
List<List<String>> x=new ArrayList<List<String>>();
List<String> item=new ArrayList<String>();
item.add("type:"+material);
item.add("amount:1");
item.add("name:"+name);
item.add("lore:"+lore);
if(add!=""){
item.add(add);
item.add(add2);
}
x.add(item);
return x;
}
public static List<List<String>> createItem(String name,String lore,String material,String add,String add2,String add3){
List<List<String>> x=new ArrayList<List<String>>();
List<String> item=new ArrayList<String>();
item.add("type:"+material);
item.add("amount:1");
item.add("name:"+name);
item.add("lore:"+lore);
if(add!=""){
item.add(add);
item.add(add2);
item.add(add3);
}
x.add(item);
return x;
}
public static List<List<String>> createPoorItem(String amount,String material,String add){
List<List<String>> x=new ArrayList<List<String>>();
List<String> item=new ArrayList<String>();
item.add("type:"+material);
item.add("amount:"+amount);
if(add!=""){
item.add(add);
}
x.add(item);
return x;
}
public static List<String> createOneLineList(String text){
List<String> l=new ArrayList<String>();
l.add(text);
return l;
}
public static List<String> createMenuItemSpell(String name,String lore,String add){
List<String> item=new ArrayList<String>();
item.add("type:WRITTEN_BOOK");
item.add("amount:1");
item.add("name:"+name);
item.add("lore:"+lore);
if(add!=""){
item.add(add);
}
return item;
}
public static void setSettings(CommentedYamlConfig config,String shopName,String displayname){
config.set("DisplayName",displayname);
config.set("signs.text","["+shopName+"]");
config.set("signs.NeedPermissionToCreateSign",true);
config.createSection("shop");
}
/**
* 为商店添加一个物品项用于链接到其他商店
* @param config 配置文件
* @param pLocation 商店物品放置位置
* @param itemID 菜单显示物品ID
* @param pTarget 目标商店
* @param pName 配置文件中存储的物品名字
*/
public static void setGuidItem(CommentedYamlConfig config,int pLocation,int itemID,String pTarget,String pName){
String tTargetDisplay=pTarget;
BSShop tShop=BossShop.getInstance().getManager(BSShopManager.class).getShop(pTarget);
if(tShop!=null) tTargetDisplay=tShop.getDisplayName();
setGuidItem(config,pLocation,itemID,pTarget,tTargetDisplay,pName);
}
/**
* 为商店添加一个物品项用于链接到其他商店
* @param config 配置文件
* @param pLocation 商店物品放置位置
* @param itemID 菜单显示物品ID
* @param pTarget 目标商店
* @param pTargetDisplay 目标名字,用于合成菜单物品名
* @param pName 配置文件中存储的物品名字
*/
public static void setGuidItem(CommentedYamlConfig config,int pLocation,int itemID,String pTarget,String pTargetDisplay,String pName){
String display=BossShop.getInstance().getLangManager().getNode("Word.GoTo")+" "+pTargetDisplay;
String tShowItem=Material.REDSTONE.name();
Material mate=Material.getMaterial(itemID);
if(mate!=null) tShowItem=mate.name();
addDefault(config,pName,"shop","free",pTarget,null,createMenuItem("&9&l"+display,"",tShowItem,""),"",pLocation,"");
}
public void addAllExamples(){
// ShopMenu
{
String name="Menu";
File f=getFile(name+".yml");
CommentedYamlConfig config=getConfig(f);
setSettings(config,name,"&lMenu");
addDefault(config,"MenuBuyShop","shop","free","BuyShop",null,createMenuItem("&9&lBuyShop &6[+]","&8Here you can buy Items","GLASS",""),"",1,"");
addDefault(config,"MenuSellShop","shop","free","SellShop",null,createMenuItem("&b&lSellShop &6[+]","&8Here you can sell Items","COBBLESTONE",""),"",3,"");
addDefault(config,"MenuPotions","shop","free","Potions",null,createMenuItem("&5&lPotions &6[**]","&8Here you can buy Potions","POTION","potioneffect:SPEED#1#1"),"",5,"");
addDefault(config,"MenuSpells","shop","free","Spells",null,createMenuItem("&4&lSpells &6[*]","&8Here you can buy magical Spells","WRITTEN_BOOK",""),"",7,"");
String mpsl="&8Here you can buy Points #"+(simplePointsPluginCheck()?"#&b&lYour Points: &r&9%playerpoints_points%":"")+"#&b&lYour Money: &r&9%vault_eco_balance% ##&cOnly for VIPs";
addDefault(config,"MenuPointShop","shop","free","PointShop",null,createMenuItem("&6&lPointShop &a[v]",mpsl,"DIAMOND",""),"",9,"Permission.Vip");
addDefault(config,"MenuWarps","shop","free","Warps",null,createMenuItem("&a&lWarps &6[x]","&8Free Teleportation","PAPER",""),"",10,"");
config.saveToFile(f);
}
// Items
{
String name="BuyShop";
File f=getFile(name+".yml");
CommentedYamlConfig config=getConfig(f);
setSettings(config,name,"&9&lBuyShop");
List<List<String>> changeRewardItems=new ArrayList<List<String>>();
List<String> changeRewardItem1=new ArrayList<String>();
changeRewardItem1.add("type:WOOL");
changeRewardItem1.add("amount:10");
changeRewardItem1.add("durability:14");
List<String> changeRewardItem2=new ArrayList<String>();
changeRewardItem2.add("type:WOOL");
changeRewardItem2.add("amount:10");
changeRewardItem2.add("durability:11");
List<String> changeRewardItem3=new ArrayList<String>();
changeRewardItem3.add("type:WOOL");
changeRewardItem3.add("amount:10");
changeRewardItem3.add("durability:4");
List<String> changeRewardItem4=new ArrayList<String>();
changeRewardItem4.add("type:WOOL");
changeRewardItem4.add("amount:10");
changeRewardItem4.add("durability:5");
changeRewardItems.add(changeRewardItem1);
changeRewardItems.add(changeRewardItem2);
changeRewardItems.add(changeRewardItem3);
changeRewardItems.add(changeRewardItem4);
addDefault(config,"Wool","item","money",changeRewardItems,400,createMenuItem("&9Colored Wool","&c10 Red, &110 Blue, &e10 Yellow and &a10 Green Wool #&cPrice: 400 Money","WOOL","durability:11","amount:40"),"&eYou bought colored Wool! Money left: &c%left%",1,"");
addDefault(config,"Diamonds","item","money",createPoorItem("5","DIAMOND",""),5000,createMenuItem("&95 Diamonds","&cPrice: 5000 Money","DIAMOND","amount:5"),"&eYou bought %reward%! Money left: &c%left%",3,"");
addDefault(config,"ShadowArmor","item","money",createItem("&5ShadowArmor","","LEATHER_CHESTPLATE","color:110#10#140","enchantment:PROTECTION_ENVIRONMENTAL#10"),1500,createMenuItem("&5%itemname%","&cPrice: 1500 Money","LEATHER_CHESTPLATE","color:110#10#140","enchantment:PROTECTION_ENVIRONMENTAL#10"),"&eYou bought 1 %itemname%! Money left: &c%left%",5,"");
addDefault(config,"Obsidian","item","money",createPoorItem("64","OBSIDIAN",""),10000,createMenuItem("&964 Obsidian","&cPrice: 10000 Money","OBSIDIAN","amount:64"),"&eYou bought %reward%! Money left: &c%left%",7,"");
addDefault(config,"GodApple","item","money",createPoorItem("1","GOLDEN_APPLE","durability:1"),10000,createMenuItem("&9%itemname%","&cPrice: 10000 Money","GOLDEN_APPLE","durability:1"),"&eYou bought 1 %itemname%! Money left: &c%left%",9,"");
addDefault(config,"EnchantUnbreaking","enchantment","exp","DURABILITY#3",25,createMenuItem("&4[crown] &cEnchantment &4[crown]","&8Enchants the Item in your hand. #&cPrice: 25 Exp Level ##&cOnly for VIPs!","ENCHANTED_BOOK","enchantment:DURABILITY#3"),"&eThe Enchantment Unbreaking III was added to your item!",19,"Permission.Vip");
addDefault(config,"BossSword","item","points",createItem("&cBossSword","&8&o%player_name%'s Sword","DIAMOND_SWORD","enchantment:DAMAGE_ALL#5","enchantment:FIRE_ASPECT#2"),2000,createMenuItem("&4[*] &c%itemname% &4[*]","&cPrice: 2000 Points","DIAMOND_SWORD","enchantment:DAMAGE_ALL#5","enchantment:FIRE_ASPECT#2"),"&eYou bought 1 %itemname%! Money left: &c%left%",21,"");
addDefault(config,"Back","shop","free","menu",null,createMenuItem("&cBack","&8Back to Menu","REDSTONE",""),"&6Leaving the ItemShop...",27,"");
config.saveToFile(f);
}
// SellShop
{
String name="SellShop";
File f=getFile(name+".yml");
CommentedYamlConfig config=getConfig(f);
setSettings(config,name,"&b&lSellShop");
addDefault(config,"Diamond","money","item",100,createPoorItem("1","DIAMOND",""),createMenuItem("&b1 Diamond","&2Reward: 100 Money","DIAMOND","amount:1"),"&eYou sold %price% for %reward% %rewardtype%!",1,"");
addDefault(config,"Cobblestone","money","item",20,createPoorItem("32","COBBLESTONE",""),createMenuItem("&b32 Cobblestone","&2Reward: 20 Money","COBBLESTONE","amount:32"),"&eYou sold &eYou sold %price% for %reward% %rewardtype%!",2,"");
addDefault(config,"GLASS","money","item",30,createPoorItem("32","GLASS",""),createMenuItem("&b32 Glass","&2Reward: 30 Money","GLASS","amount:32"),"&eYou sold %price% for %reward% %rewardtype%!",3,"");
addDefault(config,"Back","shop","free","menu",null,createMenuItem("&cBack","&8Back to Menu","REDSTONE",""),"&6Leaving the ItemShop...",27,"");
config.saveToFile(f);
}
// Potions
{
String name="Potions";
File f=getFile(name+".yml");
CommentedYamlConfig config=getConfig(f);
setSettings(config,name,"&5&lPotions");
addDefault(config,"NinjaPotion","item","item",createItem("&5NinjaPotion","&8No Barrier can stop you!","POTION","potioneffect:SPEED#2#600","potioneffect:JUMP#0#600","amount:3"),createPoorItem("5","EMERALD",""),createMenuItem("&5NinjaPotion","&8No Barrier can stop you! #&cPrice: 5 Emeralds","POTION","potioneffect:SPEED#2#600","potioneffect:JUMP#0#600","amount:3"),"&eYou bought 3 NinjaPotions!",1,"");
addDefault(config,"BeserkerPotion","item","item",createItem("&5BeserkerPotion","&8Cut em down!!!","POTION","potioneffect:INCREASE_DAMAGE#2#600","potioneffect:CONFUSION#0#600","amount:3"),createPoorItem("1","GHAST_TEAR",""),createMenuItem("&5BeserkerPotion","&8Cut em down!!! #&cPrice: 1 Ghast Tear","POTION","potioneffect:INCREASE_DAMAGE#2#600","potioneffect:CONFUSION#0#600","amount:3"),"&eYou bought 3 BeserkerPotions!",2,"");
addDefault(config,"GhostPotion","item","item",createItem("&5GhostPotion","&8Where are you? I can't see you!","POTION","potioneffect:INVISIBILITY#0#600","potioneffect:NIGHT_VISION#0#600","amount:3"),createPoorItem("30","SOUL_SAND",""),createMenuItem("&5GhostPotion","&8Where are you? I can't see you! #&cPrice: 30 SoulSand","POTION","potioneffect:INVISIBILITY#0#600","potioneffect:NIGHT_VISION#0#600","amount:3"),"&eYou bought 3 GhostPotions!",3,"");
addDefault(config,"TitanPotion","item","points",createItem("&cTitanPotion","&8Ahaha only Gods can defeat you!!!","POTION","potioneffect:REGENERATION#1#600","amount:3"),750,createMenuItem("&4[*] &cTitanPotion &4[*]","&8Ahaha only Gods can defeat you!!! #&cPrice: 750 Points","POTION","potioneffect:REGENERATION#1#600","amount:3"),"&eYou bought 3 TitanPotions!",5,"");
addDefault(config,"Back","shop","free","menu",null,createMenuItem("&cBack","&8Back to Menu","REDSTONE",""),"&6Leaving the ItemShop...",9,"");
config.saveToFile(f);
}
// Spells
{
String name="Spells";
File f=getFile(name+".yml");
CommentedYamlConfig config=getConfig(f);
setSettings(config,name,"&4&lSpells");
addDefault(config,"SpellFireball","permission","exp",createOneLineList("Permission.Fireball"),10,createMenuItemSpell("&4Fireball","&8Allows you to shoot Fireballs #&cPrice: 10 Levels",""),"&eYou bought the Fireball Spell!",1,"");
addDefault(config,"SpellPoison","permission","exp",createOneLineList("Permission.Poison"),20,createMenuItemSpell("&4Poison &2[radioactive]","&8Allows you to poison your enemies #&cPrice: 20 Levels",""),"&eYou bought the Poison Spell!",2,"");
addDefault(config,"SpellBolt","permission","exp",createOneLineList("Permission.Bolt"),30,createMenuItemSpell("&4Bolt","&8Allows you to strike your enemies with Bolts #&cPrice: 30 Levels",""),"&eYou bought the Bolt Spell!",3,"");
addDefault(config,"SpellVanish","permission","exp",createOneLineList("Permission.Vanish"),40,createMenuItemSpell("&4Vanish","&8Allows you to vanish for a few seconds #&cPrice: 40 Levels",""),"&eYou bought the Vanish Spell!",4,"");
addDefault(config,"SpellFreeze","permission","points",createOneLineList("Permission.Freeze"),3500,createMenuItemSpell("&4[*] &cFreeze &4[*]","&8Allows you to freeze your enemies #&cPrice: 3500 Points",""),"&eYou bought the Freeze Spell!",6,"");
addDefault(config,"Back","shop","free","menu",null,createMenuItem("&cBack","&8Back to Menu","REDSTONE",""),"&6Leaving the SpellShop...",9,"");
config.saveToFile(f);
}
// PointShop
{
String name="PointShop";
File f=getFile(name+".yml");
CommentedYamlConfig config=getConfig(f);
setSettings(config,name,"&6&lPointShop &2[v]");
addDefault(config,"100Points","points","money",100,1000,createMenuItem("&6100 Points","&cPrice: 1000 Money","DIAMOND","amount:1"),"&eYou bought 100 Points! Money left: &c%left%",1,"");
addDefault(config,"500Points","points","money",500,5000,createMenuItem("&6500 Points","&cPrice: 5000 Money","DIAMOND","amount:5"),"&eYou bought 500 Points! Money left: &c%left%",2,"");
addDefault(config,"1000Points","points","money",1000,10000,createMenuItem("&61000 Points","&cPrice: 10000 Money","DIAMOND","amount:10"),"&eYou bought 1000 Points! Money left: &c%left%",3,"");
addDefault(config,"500Money","money","points",500,100,createMenuItem("&6500 Money","&cPrice: 100 Points","EMERALD","amount:5"),"&eYou bought 500 Money! Points left: &c%left%",19,"");
addDefault(config,"1000Money","money","points",1000,200,createMenuItem("&61000 Money","&cPrice: 200 Points","EMERALD","amount:10"),"&eYou bought 1000 Money! Points left: &c%left%",20,"");
addDefault(config,"5000Money","money","points",5000,1000,createMenuItem("&65000 Money","&cPrice: 1000 Points","EMERALD","amount:50"),"&eYou bought 5000 Money! Points left: &c%left%",21,"");
addDefault(config,"Back","shop","free","menu",null,createMenuItem("&cBack","&8Back to Menu","REDSTONE",""),"&6Leaving the PointShop...",27,"");
config.saveToFile(f);
}
// Warps
{
String name="Warps";
File f=getFile(name+".yml");
CommentedYamlConfig config=getConfig(f);
setSettings(config,name,"&a&lWarps");
ArrayList<String> w1=new ArrayList<String>();
w1.add("warp spawn");
ArrayList<String> w2=new ArrayList<String>();
w2.add("warp pvp");
ArrayList<String> w3=new ArrayList<String>();
w3.add("warp shop");
addDefault(config,"Spawn","playercommand","free",w1,null,createMenuItem("&aSpawn","&8Warp to the Spawn","COMPASS","amount:1"),null,1,"");
addDefault(config,"PvP","playercommand","free",w2,null,createMenuItem("&aPvP","&8Warp to the PvP Arena","DIAMOND_SWORD","amount:1"),null,2,"");
addDefault(config,"Shop","playercommand","free",w3,null,createMenuItem("&aShop","&8Warp to the Shop","GOLD_INGOT","amount:1"),null,3,"");
addDefault(config,"Back","shop","free","menu",null,createMenuItem("&cBack","&8Back to Menu","REDSTONE",""),"&6Leaving the ItemShop...",27,"");
config.saveToFile(f);
}
}
public void createShopItemsExample(File f,CommentedYamlConfig config){
config.set("ShopName","ExampleShop");
config.set("signs.text","[ExampleShop]");
config.set("signs.NeedPermissionToCreateSign",false);
config.createSection("shop");
List<List<String>> diaswordRewardItems=new ArrayList<List<String>>();
List<String> diaswordRewardItem=new ArrayList<String>();
diaswordRewardItem.add("id:276");
diaswordRewardItem.add("amount:1");
diaswordRewardItem.add("name:&bDiamond Sword");
diaswordRewardItem.add("lore:Line1#Line2#Line3#Line4#This is an Example");
diaswordRewardItem.add("enchantment:DAMAGE_ALL#3");
diaswordRewardItem.add("enchantment:FIRE_ASPECT#2");
diaswordRewardItems.add(diaswordRewardItem);
List<String> diaswordMenuItem=new ArrayList<String>();
diaswordMenuItem.add("type:DIAMOND_SWORD");
diaswordMenuItem.add("amount:1");
diaswordMenuItem.add("name:&bDiamond Sword");
diaswordMenuItem.add("lore:Line1#Line2#Line3#Line4#This is an Example");
diaswordMenuItem.add("enchantmentId:16#3");
diaswordMenuItem.add("enchantmentId:20#2");
addDefault(config,"DiamondSword","item","money",diaswordRewardItems,5000,diaswordMenuItem,"&6You bought a Diamond Sword! &cMoney left: %left%",1,"");
List<String> pointsMenuItem=new ArrayList<String>();
pointsMenuItem.add("type:WRITTEN_BOOK");
pointsMenuItem.add("amount:1");
pointsMenuItem.add("name:&6PointSet");
pointsMenuItem.add("lore:&e1000 Points#&cPrice: 500 Money!");
addDefault(config,"PointSet","points","money",1000,500,pointsMenuItem,"&6You bought 1000 Points! &cMoney left: %left%",3,"");
List<String> moneyMenuItem=new ArrayList<String>();
moneyMenuItem.add("type:WRITTEN_BOOK");
moneyMenuItem.add("amount:1");
moneyMenuItem.add("name:&6MoneySet");
moneyMenuItem.add("lore:&e500 Money#&cPrice: 1000 Points!");
addDefault(config,"MoneySet","money","points",500,1000,moneyMenuItem,"&6You bought 500 Money! &cPoints left: %left%",4,"");
List<String> sMenuItem=new ArrayList<String>();
sMenuItem.add("type:WRITTEN_BOOK");
sMenuItem.add("amount:1");
sMenuItem.add("name:&4Kick");
sMenuItem.add("lore:&cPrice: Free");
List<String> sCmds=new ArrayList<String>();
sCmds.add("kick %name%");
addDefault(config,"Kick","command","free",sCmds,null,sMenuItem,"",5,"");
List<String> opMenuItem=new ArrayList<String>();
opMenuItem.add("type:BEDROCK");
opMenuItem.add("amount:1");
opMenuItem.add("name:&5OP");
opMenuItem.add("lore:&eYou are from PlanetMinecraft and you want to #&ebecome OP to be able to review the server? #&eNo problem! #&cJust buy it for 5 Levels!");
List<String> opcmd=new ArrayList<String>();
opcmd.add("op %name%");
opcmd.add("say Yay! %name% will review the server now!");
addDefault(config,"OP","command","exp",opcmd,5,opMenuItem,"",9,"");
List<String> flyMenuItem=new ArrayList<String>();
flyMenuItem.add("type:FEATHER");
flyMenuItem.add("amount:1");
flyMenuItem.add("name:&5Fly");
flyMenuItem.add("lore:&eAllows you to fly#&cPrice: 64 diamonds and 10 emeralds! #&cOnly for VIPs!");
List<List<String>> flyPriceItems=new ArrayList<List<String>>();
List<String> flyPriceItem1=new ArrayList<String>();
flyPriceItem1.add("type:DIAMOND");
flyPriceItem1.add("amount:64");
List<String> flyPriceItem2=new ArrayList<String>();
flyPriceItem2.add("type:EMERALD");
flyPriceItem2.add("amount:10");
flyPriceItems.add(flyPriceItem1);
flyPriceItems.add(flyPriceItem2);
List<String> flyPermissions=new ArrayList<String>();
flyPermissions.add("essentials.fly");
addDefault(config,"Fly","permission","item",flyPermissions,flyPriceItems,flyMenuItem,"&6You bought Fly Permissions!",10,"VIP.Access");
List<List<String>> evilCookieRewardItems=new ArrayList<List<String>>();
List<String> evilCookieRewardItem=new ArrayList<String>();
evilCookieRewardItem.add("type: COOKIE");
evilCookieRewardItem.add("amount:1");
evilCookieRewardItem.add("name:&4Evil Cookie");
evilCookieRewardItem.add("lore:&0&l*_* #&cPrice: 40 Levels");
evilCookieRewardItem.add("enchantment:KNOCKBACK#10");
evilCookieRewardItem.add("enchantment:FIRE_ASPECT#2");
evilCookieRewardItem.add("enchantment:DAMAGE_ALL#5");
evilCookieRewardItems.add(evilCookieRewardItem);
List<String> evilCookieMenuItem=new ArrayList<String>();
evilCookieMenuItem.add("type: COOKIE");
evilCookieMenuItem.add("amount:1");
evilCookieMenuItem.add("name:&4Evil Cookie");
evilCookieMenuItem.add("lore:&0&l*_* #&cPrice: 40 Levels #&cOnly for VIPs!");
evilCookieMenuItem.add("enchantment:KNOCKBACK#10");
evilCookieMenuItem.add("enchantment:FIRE_ASPECT#2");
evilCookieMenuItem.add("enchantment:DAMAGE_ALL#5");
addDefault(config,"EvilCookie","item","exp",evilCookieRewardItems,40,evilCookieMenuItem,"&4Nothing will stop you now!",12,"VIP.Access");
List<String> npMenuItem=new ArrayList<String>();
npMenuItem.add("type:POTION");
npMenuItem.add("amount:1");
npMenuItem.add("name:&1NinjaPotion");
npMenuItem.add("lore:&e1 NinjaPotion #&cPrice: 400 Money");
npMenuItem.add("potioneffect:SPEED#4#600");
npMenuItem.add("potioneffect:JUMP#0#600");
npMenuItem.add("potioneffect:NIGHT_VISION#0#600");
List<List<String>> npItems=new ArrayList<List<String>>();
List<String> np2MenuItem=new ArrayList<String>();
np2MenuItem.add("type:POTION");
np2MenuItem.add("amount:1");
np2MenuItem.add("name:&1NinjaPotion");
np2MenuItem.add("lore:&e1 NinjaPotion #&cPrice: 400 Money #&cOnly for VIPs!");
np2MenuItem.add("potioneffect:SPEED#4#600");
np2MenuItem.add("potioneffect:JUMP#0#600");
np2MenuItem.add("potioneffect:NIGHT_VISION#0#600");
npItems.add(np2MenuItem);
addDefault(config,"NinjaPotion","item","money",npItems,400,npMenuItem,"&6You bought 1 NinjaPotion! &cMoney left: %left%",13,"VIP.Access");
List<List<String>> changePriceItems=new ArrayList<List<String>>();
List<String> changePriceItem=new ArrayList<String>();
changePriceItem.add("type:DIAMOND");
changePriceItem.add("amount:2");
changePriceItems.add(changePriceItem);
List<List<String>> changeRewardItems=new ArrayList<List<String>>();
List<String> changeRewardItem1=new ArrayList<String>();
changeRewardItem1.add("type:WOOL");
changeRewardItem1.add("amount:10");
changeRewardItem1.add("durability:14");
List<String> changeRewardItem2=new ArrayList<String>();
changeRewardItem2.add("type:WOOL");
changeRewardItem2.add("amount:10");
changeRewardItem2.add("durability:11");
List<String> changeRewardItem3=new ArrayList<String>();
changeRewardItem3.add("type:WOOL");
changeRewardItem3.add("amount:10");
changeRewardItem3.add("durability:4");
List<String> changeRewardItem4=new ArrayList<String>();
changeRewardItem4.add("type:WOOL");
changeRewardItem4.add("amount:10");
changeRewardItem4.add("durability:5");
changeRewardItems.add(changeRewardItem1);
changeRewardItems.add(changeRewardItem2);
changeRewardItems.add(changeRewardItem3);
changeRewardItems.add(changeRewardItem4);
List<String> changeMenuItem=new ArrayList<String>();
changeMenuItem.add("type:WOOL");
changeMenuItem.add("amount:40");
changeMenuItem.add("durability:10");
changeMenuItem.add("name:&bColored Wool");
changeMenuItem.add("lore:&c10 Red, &110 Blue, &e10 Yellow and &a10 Green Wool #&cPrice: 2 Diamonds");
addDefault(config,"WoolSet","item","item",changeRewardItems,changePriceItems,changeMenuItem,"&6You bought a set of wool!",14,"");
List<String> backMenuItem=new ArrayList<String>();
backMenuItem.add("type:REDSTONE");
backMenuItem.add("amount:1");
backMenuItem.add("name:&4Back");
backMenuItem.add("lore:&8Go back to the Menu");
addDefault(config,"Back","shop","free","ShopMenu",null,backMenuItem,"&6Leaving the ExampleShop...",18,"");
config.saveToFile(f);
}
public void createShopItemsMenu(File f,CommentedYamlConfig config){
config.set("ShopName","ShopMenu");
config.set("signs.text","[ShopMenu]");
config.set("signs.NeedPermissionToCreateSign",false);
config.createSection("shop");
List<String> exampleShopMenuItem=new ArrayList<String>();
exampleShopMenuItem.add("type:TNT");
exampleShopMenuItem.add("amount:1");
exampleShopMenuItem.add("name:&1ExampleShop");
exampleShopMenuItem.add("lore:&6Click me!");
addDefault(config,"ExampleShop","shop","free","ExampleShop",null,exampleShopMenuItem,"&6Opening ExampleShop...",1,"");
List<String> spellShopMenuItem=new ArrayList<String>();
spellShopMenuItem.add("type:WRITTEN_BOOK");
spellShopMenuItem.add("amount:1");
spellShopMenuItem.add("name:&5SpellShop");
spellShopMenuItem.add("lore:&8Click me!");
addDefault(config,"SpellShop","shop","free","SpellShop",null,spellShopMenuItem,"&6Opening SpellShop...",9,"");
config.saveToFile(f);
}
public void createShopItemsSpell(File f,CommentedYamlConfig config){
config.set("ShopName","SpellShop");
config.set("signs.text","[SpellShop]");
config.set("signs.NeedPermissionToCreateSign",false);
config.createSection("shop");
List<String> exampleShopMenuItem=new ArrayList<String>();
exampleShopMenuItem.add("type:WRITTEN_BOOK");
exampleShopMenuItem.add("amount:1");
exampleShopMenuItem.add("name:&4Fireball");
exampleShopMenuItem.add("lore:&8Allows you to shoot Fireballs! #&cPrice: 10 Levels");
List<String> perms=new ArrayList<String>();
perms.add("Plugin.Fireball");
addDefault(config,"SpellFireball","permission","exp",perms,10,exampleShopMenuItem,"&6Opening ExampleShop...",1,"");
List<String> backMenuItem=new ArrayList<String>();
backMenuItem.add("type:REDSTONE");
backMenuItem.add("amount:1");
backMenuItem.add("name:&4Back");
backMenuItem.add("lore:&8Go back to the Menu");
addDefault(config,"Back","shop","free","ShopMenu",null,backMenuItem,"&6Leaving the SpellShop...",9,"");
config.saveToFile(f);
}
private boolean simplePointsPluginCheck(){
if(Bukkit.getPluginManager().getPlugin("PlayerPoints")!=null){ return true; }
if(Bukkit.getPluginManager().getPlugin("PointsAPI")!=null){ return true; }
if(Bukkit.getPluginManager().getPlugin("CommandPoints")!=null){ return true; }
if(Bukkit.getPluginManager().getPlugin("EnjinMinecraftPlugin")!=null){ return true; }
if(Bukkit.getPluginManager().getPlugin("BossAPI")!=null){ return true; }
return false;
}
}

View File

@ -0,0 +1,137 @@
package org.black_ixx.bossshop.managers;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import org.apache.commons.lang.StringUtils;
import org.black_ixx.bossshop.BossShop;
import org.bukkit.inventory.ItemStack;
import cc.util.bossshop.ClassHelper;
import cc.util.bossshop.LocalLanguage;
import cc.util.bossshop.NMSHelper;
import cc.util.bossshop.config.CommentedYamlConfig;
import cc.util.bossshop.pluginmodel.INeedConfig;
import cc.util.bossshop.pluginmodel.INeedReload;
public class ItemNameManager extends LocalLanguage implements INeedConfig,INeedReload{
private final HashMap<String,String> mItemNames=new HashMap<>();
private String mLang="zh_CN";
public ItemNameManager(BossShop pPlugin){
super(pPlugin);
this.mPlugin.registerConfigModel(this);
this.mPlugin.registerReloadModel(this);
}
public String getLang(){
return this.mLang;
}
public String getDisPlayName(ItemStack pItem){
return this.getDisplayName(pItem,this.mLang);
}
@Override
public String getDisplayName(ItemStack pItem,String pLang){
if(pItem==null) return "";
if(this.hasSetName(pItem)) return pItem.getItemMeta().getDisplayName();
if(pLang.equals("en_US")){ //如果是en_US 直接使用ItemStack的getName
Object NMSItemStack=ClassHelper.invokeStaticMethod(NMSHelper.method_CraftItemStack_asNMSCopy,pItem);
if(NMSItemStack==null) return this.getIDFormatName(pItem);
return (String)ClassHelper.invokeMethod(NMSItemStack,method_NMSItemStack_getName);
}
String unlocalName=this.getUnlocalizedName(pItem);
String itemName=this.mItemNames.get(unlocalName);
if(StringUtils.isNotEmpty(itemName)) return itemName;
itemName=this.mItemNames.get(unlocalName+".name");
if(StringUtils.isNotEmpty(itemName)) return itemName;
return super.getDisplayName(pItem,pLang);
}
@Override
public boolean reloadConfig(){
if(this.mLang.equals("en_US")){
this.mItemNames.clear();
this.mPlugin.info("en_US语言无需配置物品翻译");
return true;
}
InputStream fis=null;
String fileName="ItemName_"+this.mLang+".lang";
File existItemName=new File(this.mPlugin.getDataFolder(),fileName);
if(!existItemName.isFile()){
fis=this.mPlugin.getResource("lang/"+fileName);
if(fis==null){
this.mPlugin.warn("未找到物品翻译文件["+fileName+"]");
return false;
}
try{
if(!existItemName.getParentFile().isDirectory())
existItemName.getParentFile().mkdirs();
existItemName.createNewFile();
}catch(IOException ioexp){
try{
fis.close();
}catch(IOException e){}
this.mPlugin.severe("创建物品翻译文件["+fileName+"]时发生了错误: "+ioexp.getMessage(),ioexp);
return false;
}
FileOutputStream fos=null;
byte[] buffer=new byte[1024];
try{
fos=new FileOutputStream(existItemName);
int readCount=-1;
while((readCount=fis.read(buffer))!=-1)
fos.write(buffer,0,readCount);
}catch(IOException ioexp){
this.mPlugin.severe("向物品翻译文件["+fileName+"]写入内容时发生了错误: "+ioexp.getMessage(),ioexp);
return false;
}finally{
if(fos!=null) try{
fos.close();
}catch(IOException e){}
try{
fis.close();
fis=null;
}catch(IOException e){}
}
}
String[] contentLines=new String[0];
try{
fis=new FileInputStream(existItemName);
byte[] contents=new byte[fis.available()];
fis.read(contents);
contentLines=new String(contents,"UTF-8").split("[\\r]?\n");
}catch(IOException ioexp){
this.mPlugin.severe("从文件["+fileName+"]读入物品翻译是发生了错误"+ioexp.getMessage(),ioexp);
return false;
}finally{
if(fis!=null) try{
fis.close();
}catch(IOException e){}
}
this.mItemNames.clear();
for(String sLine : contentLines){
String[] t=sLine.split("=",2);
if(t.length<2) continue;
this.mItemNames.put(t[0],t[1]);
}
this.mPlugin.info("已经成功载入原版物品翻译");
return true;
}
@Override
public void setConfig(){
CommentedYamlConfig tConfig=this.mPlugin.getConfigManager().getConfig();
this.mLang=tConfig.getString("ItemNameLang",this.mLang).trim();
if(this.mLang.isEmpty()) this.mLang="zh_CN";
this.mPlugin.info("设置物品翻译语言为["+this.mLang+"]");
}
}

View File

@ -0,0 +1,75 @@
package org.black_ixx.bossshop.managers;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import cc.util.bossshop.ClassHelper;
import cc.util.bossshop.NMSHelper;
/**
* 用于背包物品检查,背包物品收取
* @author 聪聪
*
*/
public class ItemStackChecker{
public static boolean isSame(ItemStack pItem1,ItemStack pItem2){
if(pItem1==null&&pItem2==null) return true;
if(pItem1==null||pItem2==null) return false;
if(pItem1.getType()!=pItem2.getType()) return false;
if(pItem1.getDurability()!=pItem2.getDurability()) return false;
Object tNMSItemStack_mcitem1=NMSHelper.getNMSItem(pItem1);
Object tNMSItemStack_mcitem2=NMSHelper.getNMSItem(pItem2);
if(tNMSItemStack_mcitem1==null&&tNMSItemStack_mcitem2==null) return true;
if(tNMSItemStack_mcitem1==null||tNMSItemStack_mcitem2==null) return false;
Object tag1=ClassHelper.getFieldValue(tNMSItemStack_mcitem1,NMSHelper.field_NMSItemStack_tag);
Object tag2=ClassHelper.getFieldValue(tNMSItemStack_mcitem2,NMSHelper.field_NMSItemStack_tag);
return (tag1==null&&tag2==null)||(tag1!=null&&tag2!=null&&tag1.equals(tag2));
}
public static boolean inventoryContainsItem(Player p,ItemStack item){
int a=0;
int rcount=item.getAmount();
for(ItemStack ii : p.getInventory().getContents()){
if(ii==null) continue;
if(item.getType()!=ii.getType()) continue;
if(item.getDurability()!=ii.getDurability()) continue;
if(isSame(ii,item))
a+=ii.getAmount();
if(rcount<=a) return true;
}
return false;
}
public static void takeItem(ItemStack item,Player p){
int a=0;
int rcount=item.getAmount();
ItemStack[] items=p.getInventory().getContents();
for(int i=0;i<items.length;i++){
ItemStack ii=items[i];
if(ii==null) continue;
if(!isSame(item,ii)) continue;
int amount=ii.getAmount();
int remove=a+amount<=rcount?amount:rcount-a;
a+=remove;
ii.setAmount(amount-remove);
items[i]=amount-remove==0?null:ii;
if(a>=rcount){
p.getInventory().setContents(items);
return;
}
}
}
public static boolean isValidEnchantment(ItemStack item,Enchantment enchantment,int level){
try{
item.clone().addEnchantment(enchantment,level);
}
catch(Exception e){
return false;
}
return true;
}
}

View File

@ -0,0 +1,304 @@
package org.black_ixx.bossshop.managers;
import java.util.ArrayList;
import java.util.List;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.nbt.NBTEditManager;
import org.bukkit.Color;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.material.Colorable;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import com.mysql.jdbc.StringUtils;
import cc.util.bossshop.FBukkit;
public class ItemStackCreator{
private BossShop mPlugin;
public ItemStackCreator(BossShop pPlugin){
this.mPlugin=pPlugin;
}
public ItemStack createItemStack(List<String> itemData){
return this.createItemStackS(itemData,false);
}
@SuppressWarnings("deprecation")
public ItemStack createItemStackS(List<String> itemData,boolean pOverrideName){
String tdisplayName=null;
ItemStack i=new ItemStack(Material.STONE);
for(String x : itemData){
String parts[]=x.split(":",2);
String s=parts[0].trim();
String a=parts[1].trim();
if(s.equalsIgnoreCase("id")){
a=stringFix(a);
if(a.contains(":")){
String pa[]=a.split(":",2);
String type=pa[0].trim();
String dur=pa[1].trim();
try{
short dura=Short.parseShort(dur);
i.setDurability(dura);
a=type;
}catch(Exception e){
// Do not change anything
}
}
if(!isInteger(a)){
this.mPlugin.severe("Mistake in Config: "+a+" (id) needs to be a number!");
continue;
}
if(Material.getMaterial(Integer.parseInt(a))==null){
this.mPlugin.severe("Mistake in Config: "+a+" (id) is no valid Material!");
continue;
}
i.setTypeId(Integer.parseInt(a));
continue;
}
if(s.equalsIgnoreCase("nbt")){
a=stringFix(a);
ItemStack ti=this.mPlugin.getManager(NBTEditManager.class).setItemNBT(i,a);
if(ti!=null) i=ti;
}
if(s.equalsIgnoreCase("type")){
a=stringFix(a);
if(a.contains(":")){
String pa[]=a.split(":",2);
String type=pa[0].trim();
String dur=pa[1].trim();
try{
short dura=Short.parseShort(dur);
i.setDurability(dura);
a=type;
}catch(Exception e){
// Do not change anything
}
}
a=a.toUpperCase();
if(Material.getMaterial(a)==null){
this.mPlugin.severe("Mistake in Config: "+a+" (type) is no valid Material!");
continue;
}
i.setType(Material.getMaterial(a));
continue;
}
if(s.equalsIgnoreCase("amount")){
a=stringFix(a);
if(!isInteger(a)){
this.mPlugin.severe("Mistake in Config: "+a+" (amount) needs to be a number!");
continue;
}
i.setAmount(Integer.parseInt(a));
continue;
}
if(s.equalsIgnoreCase("durability")||s.equalsIgnoreCase("damage")){
a=stringFix(a);
if(!isShort(a)){
this.mPlugin.severe("Mistake in Config: "+a+" (durability) needs to be a number!");
continue;
}
i.setDurability(Short.parseShort(a));
continue;
}
if(s.equalsIgnoreCase("name")){
tdisplayName=StringManager.transform(a);
continue;
}
if(s.equalsIgnoreCase("lore")){
ItemMeta meta=i.getItemMeta();
String par[]=a.split("#");
List<String> lore=meta.getLore();
if(lore==null) lore=new ArrayList<String>();
for(String b : par)
lore.add(StringManager.transform(b));
meta.setLore(lore);
if(!FBukkit.isItemMetaEmpty(meta))
i.setItemMeta(meta);
continue;
}
if(s.equalsIgnoreCase("enchantment")){
a=stringFix(a);
try{
String par[]=a.split("#");
String eType=par[0].trim().toUpperCase();
String eLvl=par[1].trim();
Enchantment e=Enchantment.DURABILITY;
if(isInteger(eType)){
e=Enchantment.getById((Integer)Integer.parseInt(eType));
}else{
e=Enchantment.getByName(eType);
}
if(e==null){
this.mPlugin.severe("Mistake in Config: "+a+" (enchantment) contains mistakes: Invalid Enchantment name");
continue;
}
if(i.getType()==Material.ENCHANTED_BOOK){
EnchantmentStorageMeta meta=(EnchantmentStorageMeta)i.getItemMeta();
meta.addStoredEnchant(e,Integer.parseInt(eLvl),true);
if(!FBukkit.isItemMetaEmpty(meta))
i.setItemMeta(meta);
continue;
}
i.addUnsafeEnchantment(e,Integer.parseInt(eLvl));
}catch(Exception e){
this.mPlugin.severe("Mistake in Config: "+a+" (enchantment) contains mistakes!");
}
continue;
}
if(s.equalsIgnoreCase("enchantmentid")){
a=stringFix(a);
try{
String par[]=a.split("#");
String eType=par[0].trim();
String eLvl=par[1].trim();
Enchantment e=Enchantment.getById(Integer.parseInt(eType));
if(e==null){
this.mPlugin.severe("Mistake in Config: "+a+" (enchantmentid) contains mistakes: Invalid Enchantment id");
continue;
}
if(i.getType()==Material.ENCHANTED_BOOK){
EnchantmentStorageMeta meta=(EnchantmentStorageMeta)i.getItemMeta();
meta.addStoredEnchant(e,Integer.parseInt(eLvl),true);
// meta.addEnchant(e, Integer.parseInt(eLvl), true);
if(!FBukkit.isItemMetaEmpty(meta))
i.setItemMeta(meta);
continue;
}
i.addUnsafeEnchantment(e,Integer.parseInt(eLvl));
}catch(Exception e){
this.mPlugin.severe("Mistake in Config: "+a+" (enchantmentid) contains mistakes!");
}
continue;
}
if(s.equalsIgnoreCase("color")){
a=stringFix(a);
Color c=Color.AQUA;
try{
String par[]=a.split("#");
String c1=par[0].trim();
String c2=par[1].trim();
String c3=par[2].trim();
Integer i1=Integer.parseInt(c1);
Integer i2=Integer.parseInt(c2);
Integer i3=Integer.parseInt(c3);
c=Color.fromRGB(i1,i2,i3);
}catch(Exception e){
this.mPlugin.severe("Mistake in Config: "+a+" (color) contains mistakes! A color Line should look like this: \"color:<red number>#<green number>#<blue number>\". You can find a list of RGB Colors here: http://www.farb-tabelle.de/de/farbtabelle.htm");
continue;
}
if(!(i.getItemMeta() instanceof Colorable)&!(i.getItemMeta() instanceof LeatherArmorMeta)){
this.mPlugin.severe("Mistake in Config: The item "+a+" (Type "+i.getType()+")"+"(color) can't be colored/dyed! Tip: Always define the Material Type before you color the item!");
continue;
}
if(i.getItemMeta() instanceof Colorable){
Colorable ic=(Colorable)i.getItemMeta();
DyeColor color=DyeColor.getByColor(c);
ic.setColor(color);
i.setItemMeta((ItemMeta)ic);
continue;
}
if(i.getItemMeta() instanceof LeatherArmorMeta){
LeatherArmorMeta ic=(LeatherArmorMeta)i.getItemMeta();
ic.setColor(c);
i.setItemMeta((ItemMeta)ic);
continue;
}
continue;
}
if(s.equalsIgnoreCase("playerhead")){
if(i.getType()!=Material.SKULL_ITEM){
this.mPlugin.severe("Mistake in Config: "+a+" (playerhead) You can't use \"PlayerHead\" on items which are not skulls...");
continue;
}
SkullMeta meta=(SkullMeta)i.getItemMeta();
meta.setOwner(a);
if(!FBukkit.isItemMetaEmpty(meta))
i.setItemMeta(meta);
continue;
}
if(s.equalsIgnoreCase("potioneffect")){
a=stringFix(a);
if(i.getType()!=Material.POTION){
this.mPlugin.severe("Mistake in Config: "+a+" (potioneffect) You can't add PotionEffects to items which are not potions...");
continue;
}
PotionMeta meta=(PotionMeta)i.getItemMeta();
try{
String par[]=a.split("#");
String pType=par[0].trim().toUpperCase();
String pLvl=par[1].trim();
String pTime=par[2].trim();
PotionEffectType type=null;
if(isInteger(pType)){
type=PotionEffectType.getById(Integer.parseInt(pType));
}else{
type=PotionEffectType.getByName(pType);
}
meta.addCustomEffect(new PotionEffect(type,getTicksFromSeconds(pTime),Integer.parseInt(pLvl)),true);
if(!FBukkit.isItemMetaEmpty(meta))
i.setItemMeta(meta);
}catch(Exception e){
this.mPlugin.severe("Mistake in Config: "+a+" (potioneffect) contains mistakes!");
}
continue;
}
}
if((pOverrideName||!i.getItemMeta().hasDisplayName())&&!StringUtils.isNullOrEmpty(tdisplayName)){
ItemMeta meta=i.getItemMeta();
meta.setDisplayName(tdisplayName);
i.setItemMeta(meta);
}
return i;
}
private static boolean isInteger(String str){
try{
Integer.parseInt(str);
}catch(NumberFormatException nfe){
return false;
}
return true;
}
private static boolean isShort(String str){
try{
Short.parseShort(str);
}catch(NumberFormatException nfe){
return false;
}
return true;
}
private static String stringFix(String s){
if(s.contains(" ")){
s=s.replaceAll(" ","");
}
return s;
}
private static int getTicksFromSeconds(String s){
try{
Double d=Double.parseDouble(s);
return (int)(d*20);
}catch(Exception e){}
try{
Integer i=Integer.parseInt(s);
return (int)(i*20);
}catch(Exception e){}
return 0;
}
}

View File

@ -0,0 +1,212 @@
package org.black_ixx.bossshop.managers;
import org.black_ixx.bossshop.BossShop;
import org.bukkit.ChatColor;
import cc.util.bossshop.filemanager.ALangManager;
public class LangManager extends ALangManager{
/**
* 语言翻译系统
* @param plugin
*/
public LangManager(BossShop pplugin){
super(pplugin,"messages.yml","1.1");
}
@Override
public boolean reloadConfig(){
if(!super.reloadConfig()) return false;
this.checkUpdate();
this.addDefaults();
this.saveConfig();
return false;
}
public boolean checkUpdate(){
boolean update=super.checkUpdate();
if(!update) return false;
String tVersion=this.mConfig.getString(SEC_CFG_VERSION,"1.0");
if(tVersion.equalsIgnoreCase("1.0")){// 1.0-->1.1
tVersion="1.1";
this.mConfig.set("Mail.MailMaxSaveNumb","====邮件最大保存数量[%numb%]====");
String tMsg=this.mConfig.getString("Mail.YouReciveMailFrom");
if(tMsg!=null){
tMsg=tMsg.replace("你收到了来自","你收到了");
this.mConfig.set("Mail.YouReciveMailFrom",null);
this.mConfig.set("Mail.YouReciveMail",tMsg);
}
}
this.mConfig.set(SEC_CFG_VERSION,this.mVersion);
return true;
}
@Override
public void addDefaults(){
this.mConfig.addDefault("CFG.CannotCreatMailItem","&c无法创建邮件物品");
this.mConfig.addDefault("CFG.UnableFoundSaleOwner","&c无法找到寄售商品的所有者");
this.mConfig.addDefault("CFG.UnknowOutDateSaleItemType","&c未知的过期寄售物品类型");
this.mConfig.addDefault("CFG.UnknowSalePriceType","&c未知的寄售价格类型,无法给寄售物品所有者所得");
this.mConfig.addDefault("CFG.UnsupportMailItemType","&c不支持的邮件物品类型");
this.mConfig.addDefault("CFG.UnsupportSaleItemParam","&c不支持的寄售物品变量设置");
this.mConfig.addDefault("Cmd.AlreadyReloadShop","已经重载%shop%商店");
this.mConfig.addDefault("Cmd.ClearedModelStatus","&c清理了%numb%个模块的状态");
this.mConfig.addDefault("Cmd.ClearedNoUsefulNBT","共清理了%numb%个未被引用且自动生成的NBT库存");
this.mConfig.addDefault("Cmd.ConfigReloacded","已经重载配置");
this.mConfig.addDefault("Cmd.ConsoleNotAllow","&c控制台不能执行该命令");
this.mConfig.addDefault("Cmd.ErrorHappedWhenHandlerCmd","&c插件在处理命令的时候发生了异常");
this.mConfig.addDefault("Cmd.ForSaleSuccessAndTisID","&c寄售物品成功,寄售物品的编号是: ");
this.mConfig.addDefault("Cmd.GetHelp","&c获取帮助");
this.mConfig.addDefault("Cmd.ItemMayDonotHaveNBT","&c物品可能没有nbt信息");
this.mConfig.addDefault("Cmd.LangReloacded","&2已经重载语言文件");
this.mConfig.addDefault("Cmd.MustAboveZero","&c必须大于零");
this.mConfig.addDefault("Cmd.MustBeNumb","&c必须为数字");
this.mConfig.addDefault("Cmd.NBTHasExistInStockAndItsID","NBT已经存在在NBT库存中,它的ID是: ");
this.mConfig.addDefault("Cmd.NBTHaveAddAndItsID","NBT已经添加到NBT库存,它的ID是: ");
this.mConfig.addDefault("Cmd.NoPermission","&c你没有权限");
this.mConfig.addDefault("Cmd.NoPlayerFound","&c未发现该玩家");
this.mConfig.addDefault("Cmd.NoShopFound","&c未发现该商店");
this.mConfig.addDefault("Cmd.OpenShopForPlayer","&2为玩家%player%开启商店%shop%");
this.mConfig.addDefault("Cmd.PluginReloaded","已经重载插件");
this.mConfig.addDefault("Cmd.SaleItemShouldNotSameWithPrice","&c寄售物品类型和价格类型不能相同");
this.mConfig.addDefault("Cmd.SaleReachPreOneLimit","&c寄售商品已达个人寄售上线");
this.mConfig.addDefault("Cmd.SaleShopIsFull","&c寄售商店寄售数量已经达到上限");
this.mConfig.addDefault("Cmd.ServerDisablePoints","&c服务器不支持点券或未启用点券");
this.mConfig.addDefault("Cmd.UnknowCommand","&c未知指令,输入/BossShop help 获取帮助");
this.mConfig.addDefault("Cmd.UnknowPriceType","&c未知的价格类型");
this.mConfig.addDefault("Cmd.UnknowSaleItemType","&c未知的寄售物品类型");
this.mConfig.addDefault("Cmd.UnsupportPriceType","&c不支持的价格类型");
this.mConfig.addDefault("Cmd.UnsupportSaleItemType","&c不支持的寄售物品类型");
this.mConfig.addDefault("Cmd.YouHaveNotOutDateSaleItem","&c你没有过期的寄售物品");
this.mConfig.addDefault("Cmd.YouSaleHasSellOne","你的寄售物品售出一份");
this.mConfig.addDefault("Cmd.YouShouldTakeItemInHand","&c你的手上必须拿着物品");
this.mConfig.addDefault("Cmd.unknowChildCommand","&c未知子命令指令");
this.mConfig.addDefault("Console.ErrorCreateSaleFile","&c创建寄售商店文件是发生了错误");
this.mConfig.addDefault("Console.ShopFileNotExist","&c商店配置文件不存在");
this.mConfig.addDefault("Console.StartReloadShop","开始重载商店");
this.mConfig.addDefault("Console.MissingNBTNode","&cNBT库丢失NBT节点");
this.mConfig.addDefault("Economy.NoAccount","&c你还没有开户");
this.mConfig.addDefault("Enchantment.Invalid","&c这个物品不能附这个魔");
this.mConfig.addDefault("Help.ClearModelStatus","&2清理插件中一些模块的状态");
this.mConfig.addDefault("Help.ClosePlayerShop","&2关闭玩家打开的BossShop商店");
this.mConfig.addDefault("Help.HelpOpen","&2获取有关/BossShop open的帮助指令");
this.mConfig.addDefault("Help.MailCheck","&2检查你的邮件列表");
this.mConfig.addDefault("Help.MailHelp","&2获取邮件命令的帮助");
this.mConfig.addDefault("Help.MailRevice","&2接受邮件中的物品");
this.mConfig.addDefault("Help.MailSend","&2发送物品到玩家的邮箱");
this.mConfig.addDefault("Help.NBTAdd","&2添加当前手上物品的NBT信息到NBT库存");
this.mConfig.addDefault("Help.NBTClear","&2清理由插件自动生成且引用次数为0的NBT库存");
this.mConfig.addDefault("Help.NBTHelp","&2获取有关/BossShop nbt 的帮助指令");
this.mConfig.addDefault("Help.OpenOtherShop","&2为别人打开商店");
this.mConfig.addDefault("Help.OpenShop","&2为自己打开商店");
this.mConfig.addDefault("Help.Reload","&2重载BossShop配置");
this.mConfig.addDefault("Help.ReloadConfig","&2重载插件主配置");
this.mConfig.addDefault("Help.ReloadHelp","&2获取有关/BossShop reload的帮助指令");
this.mConfig.addDefault("Help.ReloadLang","&2重载语言文件,部分语言可能无法更新");
this.mConfig.addDefault("Help.ReloadShop","&2重载指定商店配置,商店名需要文件名");
this.mConfig.addDefault("Help.SaleHelp","&2获取有关/BossShop sale 的帮助命令");
this.mConfig.addDefault("Help.StartSaleWithChat","&2使用聊天栏开始图形化寄售");
this.mConfig.addDefault("Help.StopSaleWithChat","&2退出聊天栏寄售");
this.mConfig.addDefault("Help.SaleForsale","&2寄售物品");
this.mConfig.addDefault("Help.SaleOther","&2其他参数均为整数");
this.mConfig.addDefault("Help.SalePriceType","&2支持的价格类型 money,points");
this.mConfig.addDefault("Help.SaleSellType","&2支持的售卖类型 item,money,points");
this.mConfig.addDefault("Help.Unsale","&2下架指定编号的寄售物品");
this.mConfig.addDefault("Lore.AlreadySoldOut","&c商品已经售罄");
this.mConfig.addDefault("Lore.BuyIsNotTime","§c商品未到购买时间,将于%time%开放购买");
this.mConfig.addDefault("Lore.EveryoneLimit","§2每人限购%numb%件,你还可以购买%left%件");
this.mConfig.addDefault("Lore.GoodsOutOfDate","&c商品已经过了购买日期");
this.mConfig.addDefault("Lore.GoodsStockLeft","&2库存剩余%numb%件!");
this.mConfig.addDefault("Lore.NowCanBuyGoods","&2现在可以购买该商品");
this.mConfig.addDefault("Lore.WillCloseInTime","&c将于%time%结束开放购买");
this.mConfig.addDefault("Mail.FromOutDateSale","来自过期寄售");
this.mConfig.addDefault("Mail.FromPlayer","来自玩家");
this.mConfig.addDefault("Mail.FromUnknow","来自未知");
this.mConfig.addDefault("Mail.MailHasSend","邮件已经发送");
this.mConfig.addDefault("Mail.MailMaxSaveNumb","====邮件最大保存数量====");
this.mConfig.addDefault("Mail.NoPermitToCreateSignShop","没有权限创建牌子商店");
this.mConfig.addDefault("Mail.NoPermitToOpenSignShop","没有权限打开牌子商店");
this.mConfig.addDefault("Mail.PlayerMailIsFull","&c玩家[%player%]的邮箱已经满了");
this.mConfig.addDefault("Mail.YouCannotSendMailToYouSelf","&c你不能给自己发邮件");
this.mConfig.addDefault("Mail.YouHaveNoMail","你没有任何邮件");
this.mConfig.addDefault("Mail.YouMailIsFull","&c你的邮箱已经满了");
this.mConfig.addDefault("Mail.YouNeed%%MoneyToSendMail","&c你需要%numb%的金币来发送邮件");
this.mConfig.addDefault("Mail.YouReciveMail","你收到了%where%的邮件,输入/BS mail check查看");
this.mConfig.addDefault("Main.AlreadyBought","&c这东西你已经买过了");
this.mConfig.addDefault("Main.AlreadyClosePlayerShop","&2已经关闭玩家商店");
this.mConfig.addDefault("Main.AlreadySoldOut","&c商品已经售罄");
this.mConfig.addDefault("Main.CannotBuyYourselfGoods","&c你不能购买自己的寄售物品");
this.mConfig.addDefault("Main.CloseShop","&6下次再来??");
this.mConfig.addDefault("Main.ErrorHappend","&c商店发生了一点小错误,请通知管理员");
this.mConfig.addDefault("Main.FromHandUnsale","来自手动下架");
this.mConfig.addDefault("Main.GoodsNotArriveTime","&c商品未到购买时间");
this.mConfig.addDefault("Main.GoodsOutOfDate","&c商品已经过了购买时间");
this.mConfig.addDefault("Main.ItemCannotPileMoreThan","&c此物品的堆叠数量不能超过");
this.mConfig.addDefault("Main.NoPermitToBuyThisItem","&c你没有权限购买该物品");
this.mConfig.addDefault("Main.NoPlayerFound","&c未找到该玩家");
this.mConfig.addDefault("Main.NoSaleItemFound","&c未找到该寄售物品");
this.mConfig.addDefault("Main.OpenShop","&6开启小店");
this.mConfig.addDefault("Main.OutOfPersonalLimit","&c已经达到个人购买物品数量上限");
this.mConfig.addDefault("Main.PlayerNotOpenBSShop","&c玩家没有打开BossShop商店");
this.mConfig.addDefault("Main.PlayerOffline","&c玩家未在线");
this.mConfig.addDefault("Main.PlayerSaleItem","&2玩家%player_name%寄售了%item%");
this.mConfig.addDefault("Main.SuccessUnsaleItem","成功下架寄售物品");
this.mConfig.addDefault("Main.YouCannotUnsaleOther","&c你不能下架别人的寄售的物品");
this.mConfig.addDefault("Main.YouClickTooQuick","&c你点击的太快了");
this.mConfig.addDefault("Main.YouNeed%%MoneyToUnsale","&c你需要%numb%的金币来下架物品");
this.mConfig.addDefault("Main.YouTodayCannotUnsaleMore","&c你今天已经不能再下架更多物品了");
this.mConfig.addDefault("NotEnough.Exp","&c你的经验太少了");
this.mConfig.addDefault("NotEnough.Item","&c兑换需要的物品不足");
this.mConfig.addDefault("NotEnough.Money","&c你钱不够了");
this.mConfig.addDefault("NotEnough.Points","&c你点券不足");
this.mConfig.addDefault("Sale.ChatSaleStart","你已经进入寄售物品状态,输入/BS sale stop 来退出");
this.mConfig.addDefault("Sale.ChatSaleRepartStart","&c你已经开始寄售了,请勿重复开始");
this.mConfig.addDefault("Sale.ChatSaleExit","你已经退出聊天栏寄售");
this.mConfig.addDefault("Sale.ChatSaleFinish","你已经设置所有寄售参数");
this.mConfig.addDefault("Sale.NowSaleParameter","当前寄售参数(§6可以重复使用)");
this.mConfig.addDefault("Sale.NowSaleParameterColor","&a");
this.mConfig.addDefault("Sale.ClickSaleButtonFor","点击寄售按钮来进行");
this.mConfig.addDefault("Sale.YouSetSaleParamTo","&a你设置了%param%为%value%");
this.mConfig.addDefault("Sale.IntroduceSellType","点击选择你要寄售的商品类型: ");
this.mConfig.addDefault("Sale.IntroduceSingleNumb","请输入你要寄售物品每份的数量: ");
this.mConfig.addDefault("Sale.IntroducePartNumb","请输入你要寄售物品的份数: ");
this.mConfig.addDefault("Sale.IntroducePriceType","点击选择购买商品的支付方式: ");
this.mConfig.addDefault("Sale.IntroducePrice","请输入每份商品的价格: ");
this.mConfig.addDefault("Sale.IntroduceSingleNumb","请输入你要寄售物品每份的数量: ");
this.mConfig.addDefault("Word.All","所有");
this.mConfig.addDefault("Word.Count","");
this.mConfig.addDefault("Word.ForSale","寄售");
this.mConfig.addDefault("Word.GoTo","前往");
this.mConfig.addDefault("Word.Input","输入");
this.mConfig.addDefault("Word.Item","物品");
this.mConfig.addDefault("Word.Money","金币");
this.mConfig.addDefault("Word.PartNumb","份数");
this.mConfig.addDefault("Word.PlayerName","玩家名");
this.mConfig.addDefault("Word.Points","点券");
this.mConfig.addDefault("Word.Price","价格");
this.mConfig.addDefault("Word.PriceType","价格类型");
this.mConfig.addDefault("Word.Revive","接收");
this.mConfig.addDefault("Word.SaleID","物品编号");
this.mConfig.addDefault("Word.SaleShop","寄售商店");
this.mConfig.addDefault("Word.SellType","寄售类型");
this.mConfig.addDefault("Word.ShopName","商店名称");
this.mConfig.addDefault("Word.SigleNumb","每份数量");
this.mConfig.addDefault("Word.YouBought","你购买了");
this.mConfig.options().copyDefaults(true);
}
/**
* 获取消息节点(不做替换)
* @param node
* @return
*/
public String get(String node){
if(!this.mConfig.contains(node)){
this.mPlugin.warn("missing language node(丢失语言节点)["+node+"]");
return node;
}
return ChatColor.translateAlternateColorCodes('&',this.mConfig.getString(node,node));
}
}

View File

@ -0,0 +1,71 @@
package org.black_ixx.bossshop.managers;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSMultiplier;
import org.black_ixx.bossshop.core.BSEnums.BSPriceType;
import org.bukkit.entity.Player;
import cc.util.bossshop.config.CommentedYamlConfig;
import cc.util.bossshop.pluginmodel.INeedConfig;
public class MultiplierHandler implements INeedConfig{
private BossShop plugin;
private Set<BSMultiplier> multipliers=new HashSet<BSMultiplier>();
/**
* 会员价格系统
* @param plugin
*/
public MultiplierHandler(BossShop plugin){
this.plugin=plugin;
this.plugin.registerConfigModel(this);
}
@Override
public void setConfig(){
CommentedYamlConfig tConfig=this.plugin.getConfigManager().getConfig();
if(!tConfig.getBoolean("MultiplierGroups.Enabled")) return;
List<String> lines=tConfig.getStringList("MultiplierGroups.List");
if(lines==null) return;
multipliers.clear();
for(String s : lines){
BSMultiplier m=new BSMultiplier(plugin,s);
if(m.isValid()){
multipliers.add(m);
}
}
}
public double calculateWithMultiplier(Player p,BSPriceType type,double d){
for(BSMultiplier m : multipliers){
if(m.getType()==type){
if(m.hasPermission(p)){
d=d*m.getMultiplier();
}
}
}
return d;
}
public int calculateWithMultiplier(Player p,BSPriceType type,int d){
double x=d;
for(BSMultiplier m : multipliers){
if(m.getType()==type){
if(m.hasPermission(p)){
x=x*m.getMultiplier();
}
}
}
return (int)x;
}
public Set<BSMultiplier> getMultipliers(){
return multipliers;
}
}

View File

@ -0,0 +1,152 @@
package org.black_ixx.bossshop.managers;
import java.util.Calendar;
import java.util.UUID;
import org.black_ixx.bossshop.BossShop;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import cc.util.bossshop.filemanager.AFileManager;
import cc.util.bossshop.pluginmodel.INeedReload;
/**
* 用于记录玩家购买限制数量物品的记录
* @author 聪聪
*
*/
public class RecordManager extends AFileManager implements INeedReload{
public static final String SEC_UNSALE="_UnsaleRecord_";
public static final String SEC_BUY="_BuyRecord_";
public static final String SEC_UNSALE_COUNT="Count";
public static final String SEC_UNSALE_TIME="Time";
/**
* 无初始化限制条件
* @param mPlugin
*/
public RecordManager(BossShop pplugin){
super(pplugin,"buyRecord.yml","1.2");
this.mPlugin.registerReloadModel(this);
}
@Override
public boolean reloadConfig(){
if(!super.reloadConfig()) return false;
if(this.checkUpdate()) this.saveConfig();
return true;
}
protected boolean checkUpdate(){
boolean update=super.checkUpdate();
if(!update) return false;
String tVersion=this.mConfig.getString(SEC_CFG_VERSION,"1.0");
if(tVersion.equalsIgnoreCase("1.0")){
tVersion="1.1";
for(String shop_key : this.mConfig.getKeys(false)){
ConfigurationSection shop_sec=this.mConfig.getConfigurationSection(shop_key);
if(shop_sec==null) continue;
for(String item_key : shop_sec.getKeys(false)){
ConfigurationSection item_sec=shop_sec.getConfigurationSection(item_key);
if(item_sec==null) continue;
for(String player_key : item_sec.getKeys(false)){
int numb=item_sec.getInt(player_key);
item_sec.set(player_key,null);
if(numb<=0) continue;
Player tPlayer=Bukkit.getPlayer(player_key);
if(tPlayer==null) continue;
item_sec.set(tPlayer.getUniqueId().toString(),numb);
}
if(item_sec.getKeys(false).size()==0) shop_sec.set(item_key,null);
}
if(shop_sec.getKeys(false).size()==0) this.mConfig.set(shop_key,null);
}
}
if(tVersion.equalsIgnoreCase("1.1")){
for(String shop_key : this.mConfig.getKeys(false)){
if(shop_key.equalsIgnoreCase(SEC_BUY)) continue;
ConfigurationSection shop_sec=this.mConfig.getConfigurationSection(shop_key);
this.mConfig.set(shop_key,null);
this.mConfig.set(SEC_BUY+"."+shop_key,shop_sec);
}
}
this.mConfig.set(SEC_CFG_VERSION,this.mVersion);
return true;
}
/**
* 增加一次玩家购买该物品的次数
* @param shopname 商店名
* @param buyname 物品名
* @param player 用户名
*/
public void addBuyRecord(String shopname,String buyname,UUID pUUID){
String path=(shopname+"."+buyname+"."+pUUID.toString()).toLowerCase();
int buy=this.mConfig.getInt(path,0);
this.mConfig.set(path,buy+1);
this.saveConfig();
}
/**
* 获取玩家购买该物品的次数
* @param shopname 商店名
* @param buyname 物品名
* @param player 用户名
*/
public int getBuyRecord(String shopname,String buyname,UUID pUUID){
String path=(shopname+"."+buyname+"."+pUUID.toString()).toLowerCase();
return this.mConfig.getInt(path,0);
}
public int addUnsaleRecord(UUID pUUID){
String path=SEC_UNSALE+"."+pUUID.toString();
ConfigurationSection tSec=this.mConfig.getConfigurationSection(path);
int count=0;
if(tSec!=null){
long time=this.mConfig.getLong(path+"."+SEC_UNSALE_TIME,System.currentTimeMillis());
if(dxDays(time)==0){
count=this.mConfig.getInt(path+"."+SEC_UNSALE_COUNT,0);
count++;
}
}else count=1;
this.mConfig.set(path+"."+SEC_UNSALE_COUNT,count);
this.mConfig.set(path+"."+SEC_UNSALE_TIME,System.currentTimeMillis());
this.saveConfig();
return count;
}
public int getUnsaleRecord(UUID pUUID){
String path=SEC_UNSALE+"."+pUUID.toString();
ConfigurationSection tSec=this.mConfig.getConfigurationSection(path);
if(tSec==null) return 0;
long time=this.mConfig.getLong(path+"."+SEC_UNSALE_TIME,System.currentTimeMillis());
if(dxDays(time)!=0) return 0;
return this.mConfig.getInt(path+"."+SEC_UNSALE_COUNT,0);
}
/**
* 计算所给时间和现在的相差的天数,结果肯定>=0
* @param date 给定的时间
* @return 相差的天数
*/
public static int dxDays(long date){
return dxDays(System.currentTimeMillis(),date);
}
/**
* 计算所给连个时间相差的天数,结果肯定>=0
* @param data 给定的时间
* @return 相差的天数
*/
public static int dxDays(long dateb,long datef){
int ptime=Calendar.getInstance().getTimeZone().getRawOffset();
int ndays=(int)((dateb+ptime)/86400000);
int tdays=(int)((datef+ptime)/86400000);
return Math.abs(ndays-tdays);
}
}

View File

@ -0,0 +1,134 @@
package org.black_ixx.bossshop.managers;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSBuy;
import org.black_ixx.bossshop.core.BSShop;
import org.black_ixx.bossshop.core.BSShopHolder;
import org.black_ixx.bossshop.events.BSDisplayItemEvent;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
import cc.util.bossshop.FBukkit;
/**
* 定制专属于某个玩家的商店
* @author 聪聪
*
*/
public class ShopCustomizer{
private final static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm");
private BossShop mPlugin;
public ShopCustomizer(BossShop pPlugin){
this.mPlugin=pPlugin;
}
private String C(String key,Player player){
return BossShop.replaceParam(player,this.mPlugin.getLangManager().getNode(key));
}
/**
* 根据指定的玩家,商店创建物品到指定的背包
* @param pShop 商店
* @param pPlayer 玩家
* @param pInventory 背包
* @param pPoss 要显示的物品的位置
*/
public Inventory updateInventory(BSShop pShop,Player pPlayer,Inventory pInventory,Set<Integer> pPoss){
if(!(pInventory.getHolder() instanceof BSShopHolder)) return pInventory;
pInventory.clear();
for(Integer pos : pPoss){
BSBuy buy=pShop.getShopItem(pos);
if(buy==null||!buy.disaplyToPlayer(pPlayer)) continue;
ItemStack menu_item=pShop.getMenuItem(pos);
if(!buy.isNeedEdit()){
pInventory.setItem(pos,menu_item);
continue;
}
pInventory.setItem(pos,createPersonalMenuItem(pPlayer,buy,menu_item));
}
return pInventory;
}
/**
* 根据玩家信息,商品信息设置菜单物品Lore
* <p>此函数只管设置lore,不会检测是否隐藏物品</p>
* @param pPlayer 玩家
* @param pBuy 商品
* @param pMenuItem 菜单物品
* @return 肯定不是null
*/
public ItemStack createPersonalMenuItem(Player pPlayer,BSBuy pBuy,ItemStack pMenuItem){
BSShop pShop=pBuy.getShop();
BSDisplayItemEvent event=new BSDisplayItemEvent(pPlayer,pShop,pBuy);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) return null;
ItemMeta meta=pMenuItem.getItemMeta();
//设置骷髅所有者
if(meta instanceof SkullMeta){
SkullMeta skullMeta=(SkullMeta)meta;
if(skullMeta.hasOwner()) skullMeta.setOwner(BossShop.replaceParam(pPlayer,skullMeta.getOwner()));
}
//设置lore和物品名字
if(meta.hasDisplayName())
meta.setDisplayName(BossShop.replaceParam(pPlayer,meta.getDisplayName()));
List<String> lore=meta.getLore();
if(lore!=null){
int co=0;
for(String line : lore){
lore.set(co,BossShop.replaceParam(pPlayer,line));
co++;
}
}else lore=new ArrayList<String>();
// 设置剩余数量,售卖时间
int limit=pBuy.getLimit();
int perLimit=pBuy.getPersonalLimit();
Date start_t=pBuy.getStartTime();
Date stop_t=pBuy.getStopTime();
ArrayList<String> addlore=new ArrayList<>();
String faillore=null;
//设置剩余数量
if(limit>-1){
if(limit>0) addlore.add(C("Lore.GoodsStockLeft",pPlayer).replace("%numb%",limit+""));
else faillore=C("Lore.AlreadySoldOut",pPlayer);
}
//设置个人剩余数量
if(faillore==null&&perLimit>-1){
int leftbuy=perLimit-this.mPlugin.getManager(RecordManager.class).getBuyRecord(pShop.getShopName(),pBuy.getName(),pPlayer.getUniqueId());
if(leftbuy<0) leftbuy=0;
if(leftbuy==0) faillore=C("Main.OutOfPersonalLimit",pPlayer);
else addlore.add(C("Lore.EveryoneLimit",pPlayer).replace("%numb%",perLimit+"").replace("%left%",leftbuy+""));
}
//设置开始和结束时间
if(faillore==null&&(start_t!=null||stop_t!=null)){
Date date=new Date();
if(start_t==null||date.after(start_t)){
if(stop_t==null||date.before(stop_t)){
addlore.add(C("Lore.NowCanBuyGoods",pPlayer));
if(stop_t!=null) addlore.add(C("Lore.WillCloseInTime",pPlayer).replaceAll("%time%",getTimeString(stop_t)));
}else faillore=C("Lore.GoodsOutOfDate",pPlayer);
}else faillore=C("Lore.BuyIsNotTime",pPlayer).replaceAll("%time%",getTimeString(start_t));
}
if(faillore==null) lore.addAll(addlore);
else lore.add(faillore);
if(lore.size()!=0) meta.setLore(lore);
if(!FBukkit.isItemMetaEmpty(meta)) pMenuItem.setItemMeta(meta);
return pMenuItem;
}
private static String getTimeString(Date date){
return sdf.format(date);
}
}

View File

@ -0,0 +1,29 @@
package org.black_ixx.bossshop.managers;
import org.bukkit.ChatColor;
/**
* 用于转换字符串中的特殊字符
* @author 聪聪
*
*/
public class StringManager{
public static String transform(String s){
s=s.replace("[<3]","");
s=s.replace("[*]","");
s=s.replace("[**]","");
s=s.replace("[o]","");
s=s.replace("[v]","");
s=s.replace("[+]","");
s=s.replace("[x]","");
s=s.replace("[%]","");
s=s.replace("[%%]","");
s=s.replace("[radioactive]","");
s=s.replace("[peace]","");
s=s.replace("[moon]","");
s=s.replace("[crown]","");
s=s.replace("[note]","");
return ChatColor.translateAlternateColorCodes('&',s);
}
}

View File

@ -0,0 +1,32 @@
package org.black_ixx.bossshop.managers;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.timedCommands.TimedCommands;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
public class TimeHandler{
private BossShop mPlugin;
private TimedCommands tc;
public TimeHandler(BossShop pPlugin){
this.mPlugin=pPlugin;
}
private void buildPlugin(){
Plugin plugin=Bukkit.getServer().getPluginManager().getPlugin("TimedCommands");
if(plugin!=null){
tc=(TimedCommands.class.cast(plugin));
}else{
this.mPlugin.warn("未发现TimedCommands插件,如果你需要使用该插件,请前往: http://dev.bukkit.org/bukkit-plugins/scheduledcommands/");
return;
}
}
public TimedCommands getTimedCommands(){
if(tc==null) this.buildPlugin();
return tc;
}
}

View File

@ -0,0 +1,38 @@
package org.black_ixx.bossshop.managers;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSBuy;
import org.black_ixx.bossshop.core.BSEnums.BSBuyType;
import org.bukkit.entity.Player;
import cc.util.bossshop.filemanager.AFileManager;
import cc.util.bossshop.pluginmodel.INeedReload;
public class TransactionLog extends AFileManager implements INeedReload{
private SimpleDateFormat formatter=new SimpleDateFormat("yyyy dd-MM 'at' hh:mm:ss a (E)");
public TransactionLog(BossShop pPlugin){
super(pPlugin,"TransactionLog.yml","1.0");
this.mPlugin.registerReloadModel(this);
}
public String getDate(){
Date dNow=new Date();
return formatter.format(dNow);
}
public void addTransaction(String message){
this.mConfig.set(getDate(),message);
this.saveConfig();
}
public void addTransaction(Player p,BSBuy buy){
if(buy.getBuyType()==BSBuyType.Shop) return;
addTransaction("Player "+p.getName()+" bought "+buy.getName()+"("+buy.getBuyType().name()+") for "+buy.getPriceType().name()+".");
}
}

View File

@ -0,0 +1,59 @@
package org.black_ixx.bossshop.managers;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.permission.Permission;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.misc.NoEconomy;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
public class VaultHandler{
private BossShop mPlugin;
private Permission perms;
private Economy economy;
public VaultHandler(BossShop pPlugin){
this.mPlugin=pPlugin;
Plugin VaultPlugin=Bukkit.getServer().getPluginManager().getPlugin("Vault");
if(VaultPlugin==null){
this.mPlugin.warn("未发现Vault插件,如果你想使用经济系统,请前往: http://dev.bukkit.org/server-mods/vault/ 下载");
return;
}
this.mPlugin.info("Vault found.");
setupEconomy();
setupPermissions();
}
public Permission getPermission(){
if(perms==null) this.setupPermissions();
return perms;
}
public Economy getEconomy(){
if(economy==null) this.setupEconomy();
return economy;
}
private void setupEconomy(){
RegisteredServiceProvider<Economy> economyProvider=Bukkit.getServer().getServicesManager().getRegistration(net.milkbowl.vault.economy.Economy.class);
if(economyProvider==null){
this.mPlugin.warn("未发现Economy类型插件... 如果你需要用到经济系统: http://plugins.bukkit.org/.");
economy=new NoEconomy(this.mPlugin);
return;
}
economy=economyProvider.getProvider();
}
private void setupPermissions(){
RegisteredServiceProvider<Permission> rsp=Bukkit.getServer().getServicesManager().getRegistration(Permission.class);
perms=rsp.getProvider();
if(perms==null){
this.mPlugin.warn("未发现Permissions类型插件... 如果你需要用到权限系统: http://plugins.bukkit.org/");
return;
}
}
}

View File

@ -0,0 +1,226 @@
package org.black_ixx.bossshop.managers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSShopManager;
import org.black_ixx.bossshop.misc.Enchant;
import org.black_ixx.bossshop.points.PointsManager;
import org.black_ixx.timedCommands.StoreHandler;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
import cc.util.bossshop.FBukkit;
import net.milkbowl.vault.permission.Permission;
public class WorthHandler{
private BossShop mPlugin;
public WorthHandler(BossShop pPlugin){
this.mPlugin=pPlugin;
}
public String C(String pNode){
return this.mPlugin.getLangManager().getNode(pNode);
}
public void giveRewardCommand(Player pPlayer,List<String> pCommands){
for(String scmd : pCommands){
scmd=StringManager.transform(BossShop.replaceParam(pPlayer,scmd));
boolean tOp=pPlayer.isOp();
try{
pPlayer.setOp(true);
pPlayer.performCommand(scmd);
}catch(Throwable exp){
}finally {
pPlayer.setOp(tOp);
}
}
}
public void giveRewardPlayerCommand(Player pPlayer,List<String> pCommands){
for(String scmd : pCommands){
String command=StringManager.transform(BossShop.replaceParam(pPlayer,scmd));
PlayerCommandPreprocessEvent event=new PlayerCommandPreprocessEvent(pPlayer,"/"+command);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) continue;
pPlayer.performCommand(event.getMessage().substring(1));
}
}
public void giveRewardTimeCommand(Player pPlayer,HashMap<Integer,String> pCommands){
StoreHandler s=this.mPlugin.getManager(TimeHandler.class).getTimedCommands().getStoreHandler();
for(int i : pCommands.keySet()){
String cmd=BossShop.replaceParam(pPlayer,pCommands.get(i));
s.addCommandToHashMap(System.currentTimeMillis()+1000*i,cmd);
}
}
public void giveRewardItem(Player p,ItemStack item){
item=transformRewardItem(item.clone(),p);
if(p.getInventory().firstEmpty()==-1){ // Inventory full
if(item.getMaxStackSize()==1){ // Max Stack Size == 1
p.getWorld().dropItem(p.getLocation(),item); // -> Drop Item
return;
}
}
int free=0;
for(ItemStack sitem : p.getInventory().getContents()){
if(sitem!=null&&sitem.getTypeId()!=0){
if(ItemStackChecker.isSame(sitem,item)){
free+=sitem.getMaxStackSize()-sitem.getAmount();
}
}else{
free+=item.getMaxStackSize();
}
if(free>=item.getAmount()) break;
}
if(free<item.getAmount()){
ItemStack drop_item=item.clone();
drop_item.setAmount(item.getAmount()-free);
item.setAmount(free);
p.getWorld().dropItem(p.getLocation(),drop_item);// Drop Item!
}
p.getInventory().addItem(item);
}
public void giveRewardItem(Player p,List<ItemStack> items){
for(ItemStack i : items){
this.giveRewardItem(p,i);
}
}
public void giveRewardPermission(Player p,List<String> permissions){
Permission per=this.mPlugin.getManager(VaultHandler.class).getPermission();
for(String s : permissions){
per.playerAdd(p,s);
}
}
public void giveRewardMoney(Player p,double money){
VaultHandler vaultMan=this.mPlugin.getManager(VaultHandler.class);
if(!vaultMan.getEconomy().hasAccount(p.getName())){
this.mPlugin.send(p,C("Economy.NoAccount"));
this.mPlugin.severe("Unable to give "+p.getName()+" his/her money: He/She does not have an Economy Account");
return;
}
vaultMan.getEconomy().depositPlayer(p.getName(),money);
}
public void giveRewardPoints(Player p,Integer points){
this.mPlugin.getManager(PointsManager.class).givePoints(p,points);
}
public void giveRewardShop(Player p,String shopName){
if(shopName==null||shopName==""||shopName.length()<1){
p.closeInventory();
return;
}
this.mPlugin.getManager(BSShopManager.class).openShop(p,shopName);
}
public void giveRewardEnchantment(Player p,Enchant e){
if(p.getItemInHand()!=null){
p.getItemInHand().addUnsafeEnchantment(e.getType(),e.getLevel());
}
}
public boolean hasExp(Player p,int price){
if((p.getLevel()<(Integer)price)){
this.mPlugin.send(p,C("NotEnough.Exp"));
return false;
}
return true;
}
public boolean hasItems(Player p,List<ItemStack> items){
for(ItemStack i : items){
if(!ItemStackChecker.inventoryContainsItem(p,i)){
this.mPlugin.send(p,C("NotEnough.Item"));
return false;
}
}
return true;
}
public boolean hasMoney(Player p,double money){
VaultHandler vaultMan=this.mPlugin.getManager(VaultHandler.class);
if(!vaultMan.getEconomy().hasAccount(p.getName())){
this.mPlugin.send(p,C("Economy.NoAccount"));
return false;
}
if(vaultMan.getEconomy().getBalance(p.getName())<money){
this.mPlugin.send(p,C("NotEnough.Money"));
return false;
}
return true;
}
public boolean hasPoints(Player p,Integer points){
if(this.mPlugin.getManager(PointsManager.class).getPoints(p)<points){
this.mPlugin.send(p,C("NotEnough.Points"));
return false;
}
return true;
}
public String takeExp(Player p,int exp){
p.setLevel(p.getLevel()-exp);
return ""+p.getLevel();
}
public String takeItems(Player p,List<ItemStack> items){
for(ItemStack i : items){
ItemStackChecker.takeItem(i,p);
}
return null;
}
public String takeMoney(Player p,double money){
VaultHandler vaultMan=this.mPlugin.getManager(VaultHandler.class);
if(!vaultMan.getEconomy().hasAccount(p.getName())){
this.mPlugin.severe("Unable to take money! No economy account existing! ("+p.getName()+", "+money+")");
return "";
}
vaultMan.getEconomy().withdrawPlayer(p.getName(),money);
return ""+vaultMan.getEconomy().getBalance(p.getName());
}
public String takePoints(Player p,Integer d){
return ""+this.mPlugin.getManager(PointsManager.class).takePoints(p,d);
}
private ItemStack transformRewardItem(ItemStack i,Player p){
if(i.hasItemMeta()){
ItemMeta meta=i.getItemMeta();
//设置骷髅所有者
if(meta instanceof SkullMeta){
SkullMeta skullMeta=(SkullMeta)meta;
if(skullMeta.hasOwner()) skullMeta.setOwner(BossShop.replaceParam(p,skullMeta.getOwner()));
}
if(meta.hasDisplayName()){
meta.setDisplayName(BossShop.replaceParam(p,meta.getDisplayName()));
}
if(meta.hasLore()){
List<String> new_lore=new ArrayList<String>();
for(String s : meta.getLore()){
new_lore.add(BossShop.replaceParam(p,s));
}
meta.setLore(new_lore);
}
if(!FBukkit.isItemMetaEmpty(meta))
i.setItemMeta(meta);
}
return i;
}
}

View File

@ -0,0 +1,20 @@
package org.black_ixx.bossshop.misc;
import org.bukkit.enchantments.Enchantment;
public class Enchant {
private Enchantment type;
private int lvl;
public Enchant(Enchantment type, int lvl){
this.type=type;
this.lvl=lvl;
}
public Enchantment getType(){
return type;
}
public int getLevel(){
return lvl;
}
}

View File

@ -0,0 +1,276 @@
package org.black_ixx.bossshop.misc;
import java.util.List;
import org.black_ixx.bossshop.BossShop;
import org.bukkit.OfflinePlayer;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.economy.EconomyResponse;
public class NoEconomy implements Economy{
private BossShop mPlugin;
public NoEconomy(BossShop pPlugin){
this.mPlugin=pPlugin;
}
@Override
public EconomyResponse bankBalance(String arg0){
this.mPlugin.warn("No Economy Plugin found!");
return null;
}
@Override
public EconomyResponse bankDeposit(String arg0,double arg1){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return null;
}
@Override
public EconomyResponse bankHas(String arg0,double arg1){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return null;
}
@Override
public EconomyResponse bankWithdraw(String arg0,double arg1){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return null;
}
@Override
public EconomyResponse createBank(String arg0,String arg1){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return null;
}
@Override
public boolean createPlayerAccount(String arg0){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return false;
}
@Override
public boolean createPlayerAccount(String arg0,String arg1){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return false;
}
@Override
public String currencyNamePlural(){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return null;
}
@Override
public String currencyNameSingular(){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return null;
}
@Override
public EconomyResponse deleteBank(String arg0){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return null;
}
@Override
public EconomyResponse depositPlayer(String arg0,double arg1){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return null;
}
@Override
public EconomyResponse depositPlayer(String arg0,String arg1,double arg2){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return null;
}
@Override
public String format(double arg0){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return null;
}
@Override
public int fractionalDigits(){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return 0;
}
@Override
public double getBalance(String arg0){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return 0;
}
@Override
public double getBalance(String arg0,String arg1){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return 0;
}
@Override
public List<String> getBanks(){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return null;
}
@Override
public String getName(){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return null;
}
@Override
public boolean has(String arg0,double arg1){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return false;
}
@Override
public boolean has(String arg0,String arg1,double arg2){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return false;
}
@Override
public boolean hasAccount(String arg0){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return false;
}
@Override
public boolean hasAccount(String arg0,String arg1){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return false;
}
@Override
public boolean hasBankSupport(){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return false;
}
@Override
public EconomyResponse isBankMember(String arg0,String arg1){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return null;
}
@Override
public EconomyResponse isBankOwner(String arg0,String arg1){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return null;
}
@Override
public boolean isEnabled(){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return false;
}
@Override
public EconomyResponse withdrawPlayer(String arg0,double arg1){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return null;
}
@Override
public EconomyResponse withdrawPlayer(String arg0,String arg1,double arg2){
this.mPlugin.warn("No Economy Plugin was found... You need one if you want to work with Money! Get it there: http://plugins.bukkit.org/.");
return null;
}
@Override
public EconomyResponse createBank(String arg0,OfflinePlayer arg1){
// TODO Auto-generated method stub
return null;
}
@Override
public boolean createPlayerAccount(OfflinePlayer arg0){
// TODO Auto-generated method stub
return false;
}
@Override
public boolean createPlayerAccount(OfflinePlayer arg0,String arg1){
// TODO Auto-generated method stub
return false;
}
@Override
public EconomyResponse depositPlayer(OfflinePlayer arg0,double arg1){
// TODO Auto-generated method stub
return null;
}
@Override
public EconomyResponse depositPlayer(OfflinePlayer arg0,String arg1,double arg2){
// TODO Auto-generated method stub
return null;
}
@Override
public double getBalance(OfflinePlayer arg0){
// TODO Auto-generated method stub
return 0;
}
@Override
public double getBalance(OfflinePlayer arg0,String arg1){
// TODO Auto-generated method stub
return 0;
}
@Override
public boolean has(OfflinePlayer arg0,double arg1){
// TODO Auto-generated method stub
return false;
}
@Override
public boolean has(OfflinePlayer arg0,String arg1,double arg2){
// TODO Auto-generated method stub
return false;
}
@Override
public boolean hasAccount(OfflinePlayer arg0){
// TODO Auto-generated method stub
return false;
}
@Override
public boolean hasAccount(OfflinePlayer arg0,String arg1){
// TODO Auto-generated method stub
return false;
}
@Override
public EconomyResponse isBankMember(String arg0,OfflinePlayer arg1){
// TODO Auto-generated method stub
return null;
}
@Override
public EconomyResponse isBankOwner(String arg0,OfflinePlayer arg1){
// TODO Auto-generated method stub
return null;
}
@Override
public EconomyResponse withdrawPlayer(OfflinePlayer arg0,double arg1){
// TODO Auto-generated method stub
return null;
}
@Override
public EconomyResponse withdrawPlayer(OfflinePlayer arg0,String arg1,double arg2){
// TODO Auto-generated method stub
return null;
}
}

View File

@ -0,0 +1,18 @@
package org.black_ixx.bossshop.nbt;
public class NBT{
/**
* 此处的值类型为NMS的NBTTagCompound
*/
public final String mLabel;
protected final Object nbt;
protected boolean autoadd=false;
protected long lastUseTime=System.currentTimeMillis();
NBT(String pLabel,Object pnbt,boolean pauto){
this.mLabel=pLabel;
this.nbt=pnbt;
this.autoadd=pauto;
}
}

View File

@ -0,0 +1,538 @@
package org.black_ixx.bossshop.nbt;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang.StringUtils;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.core.BSShopManager;
import org.black_ixx.bossshop.mail.MailManager;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import cc.util.bossshop.ClassHelper;
import cc.util.bossshop.FBukkit;
import cc.util.bossshop.NMSHelper;
import cc.util.bossshop.config.CommentedSection;
import cc.util.bossshop.config.CommentedYamlConfig;
import cc.util.bossshop.filemanager.AFileManager;
import cc.util.bossshop.pluginmodel.INeedConfig;
import cc.util.bossshop.pluginmodel.INeedReload;
/**
* NBT管理系统,用于NBT的创建,保存和恢复
* @author 聪聪
*
*/
public class NBTEditManager extends AFileManager implements INeedConfig,INeedReload{
public static final String SEC_NBT_MAIN="NBTS";
public static final String SEC_NBT_CONTENT="Content";
public static final String SEC_AUTO_ADD="AutoAdd";
public static final String SEC_LAST_USE_TIME="LastUseTime";
/**
* 用于NBT节点中名中.符号的替换
*/
private static char re='$';
private final HashMap<String,NBT> nbtmap=new HashMap<>();
private int mExpiredDays=7;
/**
* 无初始化限制条件
* @param plugin
*/
public NBTEditManager(BossShop pplugin){
super(pplugin,"nbt.yml","1.1");
pplugin.registerConfigModel(this);
pplugin.registerReloadModel(this);
}
@Override
public void setConfig(){
CommentedYamlConfig tConfig=this.mPlugin.getConfigManager().getConfig();
this.mExpiredDays=tConfig.getInt("AutoClear.NBTExpiredDays",this.mExpiredDays);
if(this.mExpiredDays<=0) this.mExpiredDays=Integer.MAX_VALUE;
}
/**
* 切勿单独调用,防止NBT引用次数被重置
*/
public boolean reloadConfig(){
super.reloadConfig();
this.checkUpdate();
this.generateNBT();
this.saveConfig();
return true;
}
/**
* 检查配置文件版本,用以更新配置文件
* 当前更新范围 无版本->1.1
*/
protected boolean checkUpdate(){
boolean update=super.checkUpdate();
if(!update) return false;
String tversion=this.mConfig.getString(SEC_CFG_VERSION,"1.0");
if(tversion.equalsIgnoreCase("1.0")){
tversion="1.1";
this.mConfig.set("index",null);
if(tversion.compareToIgnoreCase("1.0")==0){
ConfigurationSection sec=this.mConfig.getConfigurationSection(SEC_NBT_MAIN);
if(sec!=null){
for(String label : sec.getKeys(false)){
ConfigurationSection nbtsec=sec.getConfigurationSection(label);
sec.set(label,null);
sec.set(label+"."+SEC_NBT_CONTENT,nbtsec);
sec.set(label+"."+SEC_AUTO_ADD,false);
}
}
}
}
this.mConfig.set(SEC_CFG_VERSION,this.mVersion);
return true;
}
/**
* 清理自动生成且引用次数为0的NBT节点
* @return 清理的个数
*/
public int clearNBT(){
ConfigurationSection sec=this.mConfig.getConfigurationSection(SEC_NBT_MAIN);
if(sec==null) return 0;
//先检查商店和邮件是否在范围时间内引用了NBT,如果没有则重载来增加NBT最后引用时间
MailManager mailMan=((BossShop)this.mPlugin).getManager(MailManager.class);
if(System.currentTimeMillis()-mailMan.getLastReloadTime()>=this.mExpiredDays*86400000)
mailMan.reloadConfig();
BSShopManager shopMan=((BossShop)this.mPlugin).getManager(BSShopManager.class);
if(System.currentTimeMillis()-shopMan.getLastReloadTime()>=this.mExpiredDays*86400000)
shopMan.reloadConfig();
int count=0;
Iterator<Entry<String,NBT>> it=this.nbtmap.entrySet().iterator();
while(it.hasNext()){
Entry<String,NBT> entry=it.next();
NBT nbt=entry.getValue();
if(nbt.autoadd&&System.currentTimeMillis()-nbt.lastUseTime>this.mExpiredDays*86400000){
sec.set(entry.getKey(),null);
it.remove();
count++;
}
}
if(count>0){
this.saveConfig();
this.debug("NBT库清理函数被调用,共清理 " +count+" 个过期NBT");
}
return count;
}
/**
* 添加物品的NBT到库存
* @param item 要获取NBT的物品
* @param auto 是否是自动添加的
* @return 添加成功后存储在文件中的NBT节点名,如果物品没有nbt信息,将返回null
*/
public String addItemNBTToStock(ItemStack item,boolean auto){
Object tObj_NBTTagCompound_tag=NMSHelper.getNBTTagCompound(item);
if(tObj_NBTTagCompound_tag==null) return null;
Object tNBTTagCompound_tagClone=ClassHelper.invokeMethod(tObj_NBTTagCompound_tag,NMSHelper.clazz_NBTBase); //克隆方法
Map<String,Object> tagContent=NMSHelper.getNBTTagMapFromTag(tNBTTagCompound_tagClone);
if(tagContent==null||tagContent.isEmpty())
return null;
NBT addNBT=this.getNBTByTag(tNBTTagCompound_tagClone);
if(addNBT==null){
long time=System.currentTimeMillis()/1000;
String label=time+"_"+item.getType().name();
while(this.mConfig.contains(label)){
time++;
label=time+"_"+item.getType().name();
}
addNBT=new NBT(label,tNBTTagCompound_tagClone,auto);
this.nbtmap.put(label,addNBT);
}
this.updateNBTLastTime(addNBT);
return addNBT.mLabel;
}
/**
* 更新NBT最后引用时间(配置文件和自身实例)
* <p>如果NBT配置节点不存在会自动创建</p>
* @param pNBT 要更新的NBT
*/
public void updateNBTLastTime(NBT pNBT){
ConfigurationSection sec=this.mConfig.getConfigurationSection(SEC_NBT_MAIN);
if(sec==null) sec=this.mConfig.createSection(SEC_NBT_MAIN);
ConfigurationSection nsec=sec.getConfigurationSection(pNBT.mLabel);
if(nsec==null){
nsec=sec.createSection(pNBT.mLabel);
nsec.set(SEC_AUTO_ADD,pNBT.autoadd);
ConfigurationSection content_sec=nsec.createSection(SEC_NBT_CONTENT);
this.putNBTToSection(content_sec,pNBT.nbt);
}
nsec.set(SEC_LAST_USE_TIME,System.currentTimeMillis());
pNBT.lastUseTime=System.currentTimeMillis();
this.saveConfig();
}
/**
* 根据pItem来获取NBT类实例
* @param pItem Bukkit物品
* @return 找到的NBl类实例或null
*/
public NBT getNBTByItem(ItemStack pItem){
return this.getNBTByTag(NMSHelper.getNBTTagCompound(pItem));
}
/**
* 根据NBTTagCompound来获取NBT类实例
* @param pTag
* @return 找到的NBT类实例或null
*/
private NBT getNBTByTag(Object pTag){
if(pTag==null) return null;
for(NBT sNBT : this.nbtmap.values()){
if(sNBT.nbt.equals(pTag)) return sNBT;
}
return null;
}
/**
* 将NBT信息存储到配置文件指定的节点中
*/
private void putNBTToSection(ConfigurationSection sec,Object tObj_NBTBase_nbt){
if(NMSHelper.clazz_NBTTagCompound.isInstance(tObj_NBTBase_nbt)){
Map<String,Object> nbtContents=NMSHelper.getNBTTagMapFromTag(tObj_NBTBase_nbt);
for(Map.Entry<String,Object> entry : nbtContents.entrySet()){
String cname=entry.getKey().replace('.',re);
Object tObj_NBTBase_tnbt=entry.getValue();
if(NMSHelper.clazz_NBTTagCompound.isInstance(tObj_NBTBase_tnbt)||NMSHelper.clazz_NBTTagList.isInstance(tObj_NBTBase_tnbt)){
ConfigurationSection nsec=sec.createSection(cname);
putNBTToSection(nsec,tObj_NBTBase_tnbt);
}else sec.set(cname,this.getStringValue(tObj_NBTBase_tnbt));
}
}else if(NMSHelper.clazz_NBTTagList.isInstance(tObj_NBTBase_nbt)){
List<Object> contentList=(List<Object>)ClassHelper.getFieldValue(tObj_NBTBase_nbt,NMSHelper.field_NBTTagList_value);
sec.set("_type_",9);
int i=0;
for(Object sNBTBase: contentList){
String name=i+"";i++;
if(NMSHelper.clazz_NBTTagCompound.isInstance(sNBTBase)||NMSHelper.clazz_NBTTagList.isInstance(sNBTBase)){
ConfigurationSection nsec=sec.createSection(name);
putNBTToSection(nsec,sNBTBase);
}else{
String str=sNBTBase.toString();
if(NMSHelper.clazz_NBTTagString.isInstance(sNBTBase))
str=(String)ClassHelper.getFieldValue(sNBTBase,NMSHelper.field_NBTTagString_value);
sec.set(name,str);
}
}
if(sec.getKeys(false).size()==1) sec.set("_type_",null);
}else{
warn("NBT Edit maybe make a bug");
}
}
/**
* 从配置文件中生成NBT
*/
private void generateNBT(){
this.nbtmap.clear();
CommentedSection sec=this.mConfig.getConfigurationSection(SEC_NBT_MAIN);
if(sec==null){
sec=this.mConfig.createSection(SEC_NBT_MAIN);
return ;
}
for(String label : sec.getKeys(false)){
Object tObj_NBTTagCompound=ClassHelper.getInstance(NMSHelper.clazz_NBTTagCompound);
CommentedSection nbtSec=sec.getConfigurationSection(label);
if(label==null) continue;
boolean auto=nbtSec.getBoolean(NBTEditManager.SEC_AUTO_ADD,false);
CommentedSection contentSec=nbtSec.getConfigurationSection(NBTEditManager.SEC_NBT_CONTENT);
if(contentSec==null){
this.mPlugin.warn("NBT配置节点["+label+"]没有["+NBTEditManager.SEC_NBT_CONTENT+"]节点,这是一个配置错误");
continue;
}
this.setTagContent(contentSec,tObj_NBTTagCompound);
NBT cfgNBT=new NBT(label,tObj_NBTTagCompound,auto);
cfgNBT.lastUseTime=nbtSec.getLong(NBTEditManager.SEC_LAST_USE_TIME,System.currentTimeMillis());;
this.nbtmap.put(label,cfgNBT);
}
}
/**
* 使用该方法是必须接受返回结果
* @param item 要设置nbt信息的物品
* @param nbtLabel nbt标签,所有标签在数据文件夹下的nbt.yml中的NBTS节点下
* @return 设置完nbt信息后的物品
*/
public ItemStack setItemNBT(ItemStack item,String nbtLabel){
NBT nbtcom=this.nbtmap.get(nbtLabel);
if(nbtcom==null){
if(StringUtils.isNotEmpty(nbtLabel))
warn(C("Console.MissingNBTNode")+"["+nbtLabel+"]");
return null;
}
this.updateNBTLastTime(nbtcom);
ItemMeta meta=item.getItemMeta();
List<String> lore_old=new ArrayList<String>();
if(meta.hasLore()) lore_old.addAll(meta.getLore());
Object tObj_NMSItemStack=ClassHelper.invokeStaticMethod(NMSHelper.method_CraftItemStack_asNMSCopy,item);
if(tObj_NMSItemStack==null) return item;
Object tObj_NBTTagCompound_tag=ClassHelper.getFieldValue(tObj_NMSItemStack,NMSHelper.field_NMSItemStack_tag);//获取物品tag
if(tObj_NBTTagCompound_tag!=null){
//清空原lore
Map<String,Object> tagContent=NMSHelper.getNBTTagMapFromTag(tObj_NBTTagCompound_tag);
Object tNBTTagCompound_display=tagContent.get("display");
if(tNBTTagCompound_display!=null){
Map<String,Object> tagDisplayContent=NMSHelper.getNBTTagMapFromTag(tNBTTagCompound_display);
tagDisplayContent.remove("Lore");
}
this.mixNBT(tObj_NBTTagCompound_tag,nbtcom.nbt);
}
else{
Object tNBTTagCompound_tagClone=ClassHelper.invokeMethod(nbtcom.nbt,NMSHelper.method_NBTTagCompound_clone);//克隆 nbt
ClassHelper.setFieldValue(tObj_NMSItemStack,NMSHelper.field_NMSItemStack_tag,tNBTTagCompound_tagClone);//设置tag
}
ItemStack ritem=(ItemStack)ClassHelper.invokeStaticMethod(NMSHelper.method_CraftItemStack_asCraftMirror,tObj_NMSItemStack);
meta=ritem.getItemMeta();
List<String> lore_nbt=meta.getLore();
if(lore_nbt==null) lore_nbt=new ArrayList<>();
if(lore_old!=null) lore_nbt.addAll(lore_old);
meta.setLore(lore_nbt);
if(!FBukkit.isItemMetaEmpty(meta)){//防止空meta清空nbt
ritem.setItemMeta(meta);
}
return ritem;
}
/**
* 混合两个 NBTTagCompound,如果同时存在节点名相同但属性不同,优先保存前一个的数据
*/
private void mixNBT(Object tObj_NBTTagCompound_to,Object tObj_NBTTagCompound_from){
Object tNBTBase_toChild=null;
Map<String,Object> tagFromContent=NMSHelper.getNBTTagMapFromTag(tObj_NBTTagCompound_from);//获取from com的map
Map<String,Object> tagToContent=NMSHelper.getNBTTagMapFromTag(tObj_NBTTagCompound_to);//获取to com的map
for(Object obj : tagFromContent.keySet()){
String name=obj.toString();
tNBTBase_toChild=tagToContent.get(name); //尝试to com中是否有该节点
Object tNBTBase_fromChild=tagFromContent.get(name); //获取from com中的该值
if(tNBTBase_fromChild==null) continue; //如果复制源为null就没必要继续了
if(tNBTBase_toChild==null){ //to com中不存在直接put
tagToContent.put(name,tNBTBase_fromChild);
}else{ //to com中存在,分类
if(tNBTBase_toChild.getClass()==tNBTBase_fromChild.getClass()){//如果同是com
if(NMSHelper.clazz_NBTTagCompound.isInstance(tNBTBase_toChild))//如果是com,混合
mixNBT(tNBTBase_toChild,tNBTBase_fromChild);
else if(NMSHelper.clazz_NBTTagList.isInstance(tNBTBase_toChild)){//如果list,相加
List<Object> from_contentList=(List<Object>)ClassHelper.getFieldValue(tNBTBase_fromChild,NMSHelper.field_NBTTagList_value);//获取from taglist中的list
int tListSize=from_contentList.size();
for(int i=0;i<tListSize;i++){//将from中的内容放到to中
Object tNBTTagCompound_tb=from_contentList.get(i);//获取from list中的值
if(tNBTTagCompound_tb==null) continue;
ClassHelper.invokeMethod(tNBTBase_toChild,NMSHelper.method_NBTTagList_add,tNBTTagCompound_tb);
}
}else{//其他则直接覆盖
tagToContent.put(name,tNBTBase_fromChild);
}
}else warn("same nbt node name exist of: "+name+",but they have different types,please check ");
}
}
}
/**
* 将配置节点sec中的NBT信息放到tag中
*/
private void setTagContent(CommentedSection sec,Object pObj_NBTBase){
if(sec.getInt("_type_")==9&&NMSHelper.clazz_NBTTagList.isInstance(pObj_NBTBase)){// NBTTagList
for(String n : sec.getKeys(false)){
if(n.equalsIgnoreCase("_type_")) continue;
Object value=sec.get(n);
if(value instanceof String){
Object tObj_NBTBase_ntag=getNBTNode((String)value);
if(tObj_NBTBase_ntag!=null)
ClassHelper.invokeMethod(pObj_NBTBase,NMSHelper.method_NBTTagList_add,tObj_NBTBase_ntag);
}else if(value instanceof CommentedSection){
CommentedSection nsec=(CommentedSection)value;
Object tObj_NBTBase_nbt=null;
if(nsec.getInt("_type_")==9) tObj_NBTBase_nbt=ClassHelper.getInstance(NMSHelper.clazz_NBTTagList);
else tObj_NBTBase_nbt=ClassHelper.getInstance(NMSHelper.clazz_NBTTagCompound);
ClassHelper.invokeMethod(pObj_NBTBase,NMSHelper.method_NBTTagList_add,tObj_NBTBase_nbt);
setTagContent(nsec,tObj_NBTBase_nbt);
}else{
warn("NBT配置存在错误,无法处理["+sec.getCurrentPath()+"]的值"+value);
}
}
}else if(NMSHelper.clazz_NBTTagCompound.isInstance(pObj_NBTBase)){// NBTTag NBTTagCompound
Map<String,Object> tObj_content=NMSHelper.getNBTTagMapFromTag(pObj_NBTBase);
for(String n : sec.getKeys(false)){
Object value=sec.get(n);
String tname=n.replace(re,'.');
if(value instanceof String){
Object tObj_NBTBase_ntag=getNBTNode((String)value);
if(tObj_NBTBase_ntag!=null) tObj_content.put(tname,tObj_NBTBase_ntag);
}else if(value instanceof CommentedSection){
CommentedSection nsec=(CommentedSection)value;
Object tObj_NBTBase_nbt=null;
if(nsec.getInt("_type_")==9) tObj_NBTBase_nbt=ClassHelper.getInstance(NMSHelper.clazz_NBTTagList);
else tObj_NBTBase_nbt=ClassHelper.getInstance(NMSHelper.clazz_NBTTagCompound);
tObj_content.put(tname,tObj_NBTBase_nbt);
setTagContent(nsec,tObj_NBTBase_nbt);
}else{
warn("NBT配置存在错误,无法处理["+sec.getCurrentPath()+"]的值"+value);
}
}
}else warn("你的NBT配置文件可能存在问题,节点"+sec.getCurrentPath()+"\"_type_\"标识符错误");
}
/**
* 根据字符串格式生成指定的NBT节点
* @return 返回类型为NBTBase
*/
private Object getNBTNode(String value){
String[] vals=value.split("[|]",2);
if(vals.length<2) return ClassHelper.getInstance(NMSHelper.clazz_NBTTagString,String.class,value);
int type=0;
try{
type=Integer.parseInt(vals[0]);
}
catch(NumberFormatException nbfexp){
warn("NBT.yml file at "+value+" is uncorrect,value before '|' must be a int");
return null;
}
switch(type){
case 1:
try{
byte tByteValue=Byte.parseByte(vals[1]);
return ClassHelper.getInstance(NMSHelper.clazz_NBTTagByte,byte.class,tByteValue);
}
catch(NumberFormatException nbfexp){
warn("NBT.yml file at "+value+" is uncorrect,value after '|' must be a byte value");
return null;
}
case 2:
try{
short tShortValue=Short.parseShort(vals[1]);
return ClassHelper.getInstance(NMSHelper.clazz_NBTTagShort,short.class,tShortValue);
}
catch(NumberFormatException nbfexp){
warn("NBT.yml file at "+value+" is uncorrect,value after '|' must be a short value");
return null;
}
case 3:
try{
int tIntValue=Integer.parseInt(vals[1]);
return ClassHelper.getInstance(NMSHelper.clazz_NBTTagInt,int.class,tIntValue);
}
catch(NumberFormatException nbfexp){
warn("NBT.yml file at "+value+" is uncorrect,value after '|' must be a int value");
return null;
}
case 4:
try{
long tLongValue=Long.parseLong(vals[1]);
return ClassHelper.getInstance(NMSHelper.clazz_NBTTagLong,long.class,tLongValue);
}
catch(NumberFormatException nbfexp){
warn("NBT.yml file at "+value+" is uncorrect,value after '|' must be a long value");
return null;
}
case 5:
try{
float tFloatValue=Float.parseFloat(vals[1]);
return ClassHelper.getInstance(NMSHelper.clazz_NBTTagFloat,float.class,tFloatValue);
}
catch(NumberFormatException nbfexp){
warn("NBT.yml file at "+value+" is uncorrect,value after '|' must be a float value");
return null;
}
case 6:
try{
double tDoubleValue=Double.parseDouble(vals[1]);
return ClassHelper.getInstance(NMSHelper.clazz_NBTTagDouble,double.class,tDoubleValue);
}
catch(NumberFormatException nbfexp){
warn("NBT.yml file at "+value+" is uncorrect,value after '|' must be a double value");
return null;
}
case 7:
String[] bvals=vals[1].trim().split(",");
List<Byte> blist=new ArrayList<>();
for(String v : bvals){
try{
blist.add(Byte.parseByte(v));
}
catch(NumberFormatException nbfexp){
warn("NBT.yml file at "+value+" is uncorrect,"+v+" is not a short value");
}
}
byte[] mbvals=new byte[blist.size()];
for(int i=0;i<blist.size();i++)
mbvals[i]=blist.get(i);
return ClassHelper.getInstance(NMSHelper.clazz_NBTTagByteArray,byte[].class,mbvals);
case 11:
String[] ivals=vals[1].trim().split(",");
List<Integer> ilist=new ArrayList<>();
for(String v : ivals){
try{
ilist.add(Integer.parseInt(v));
}
catch(NumberFormatException nbfexp){
warn("NBT.yml file at "+value+" is uncorrect,"+v+" is not a int value");
}
}
int[] mivals=new int[ilist.size()];
for(int i=0;i<ilist.size();i++)
mivals[i]=ilist.get(i);
return ClassHelper.getInstance(NMSHelper.clazz_NBTTagIntArray,int[].class,mivals);
case 8:
return ClassHelper.getInstance(NMSHelper.clazz_NBTTagString,String.class,vals[1]);
default:
warn("NBT.yml file at "+value+" is unknow how to handle");
}
return null;
}
private String getStringValue(Object tObj_NBTBase_nbt){
//ClassHelper.
if(String.class.isInstance(tObj_NBTBase_nbt))
return String.class.cast(tObj_NBTBase_nbt);
String value="";
if(NMSHelper.clazz_NBTTagByte.isInstance(tObj_NBTBase_nbt)){
value="1|"+ClassHelper.getFieldValue(tObj_NBTBase_nbt,NMSHelper.field_NBTTagByte_value);
}else if(NMSHelper.clazz_NBTTagShort.isInstance(tObj_NBTBase_nbt)){
value="2|"+ClassHelper.getFieldValue(tObj_NBTBase_nbt,NMSHelper.field_NBTTagShort_value);
}else if(NMSHelper.clazz_NBTTagInt.isInstance(tObj_NBTBase_nbt)){
value="3|"+ClassHelper.getFieldValue(tObj_NBTBase_nbt,NMSHelper.field_NBTTagInt_value);
}else if(NMSHelper.clazz_NBTTagLong.isInstance(tObj_NBTBase_nbt)){
value="4|"+ClassHelper.getFieldValue(tObj_NBTBase_nbt,NMSHelper.field_NBTTagLong_value);
}else if(NMSHelper.clazz_NBTTagFloat.isInstance(tObj_NBTBase_nbt)){
value="5|"+ClassHelper.getFieldValue(tObj_NBTBase_nbt,NMSHelper.field_NBTTagFloat_value);
}else if(NMSHelper.clazz_NBTTagDouble.isInstance(tObj_NBTBase_nbt)){
value="6|"+ClassHelper.getFieldValue(tObj_NBTBase_nbt,NMSHelper.field_NBTTagDouble_value);
}else if(NMSHelper.clazz_NBTTagByteArray.isInstance(tObj_NBTBase_nbt)){// 7 .c()
value="7|";
byte[] bvals=ClassHelper.getFieldValue(tObj_NBTBase_nbt,byte[].class,-1);
for(byte bv : bvals)
value+=bv+",";
if(value.endsWith(",")) value=value.substring(0,value.length()-1);
}else if(NMSHelper.clazz_NBTTagString.isInstance(tObj_NBTBase_nbt)){
value="8|"+ClassHelper.getFieldValue(tObj_NBTBase_nbt,NMSHelper.field_NBTTagString_value);
}else if(NMSHelper.clazz_NBTTagIntArray.isInstance(tObj_NBTBase_nbt)){// 11 .c()
value="11|";
int[] ivals=ClassHelper.getFieldValue(tObj_NBTBase_nbt,int[].class,-1);
for(int iv : ivals)
value+=iv+",";
if(value.endsWith(",")) value=value.substring(0,value.length()-1);
}else{
warn("NBT of type: "+tObj_NBTBase_nbt.getClass().getName()+" unknow how to record,value: "+tObj_NBTBase_nbt.toString());
}
return value;
}
}

View File

@ -0,0 +1,43 @@
package org.black_ixx.bossshop.points;
import org.black_ixx.bossshop.BossShop;
import org.bukkit.OfflinePlayer;
import org.bukkit.plugin.Plugin;
import pgDev.bukkit.CommandPoints.CommandPoints;
public class CommandPointsAPI extends IPointsAPI{
private pgDev.bukkit.CommandPoints.CommandPointsAPI pp;
public CommandPointsAPI(BossShop pPlugin){
super(pPlugin,"CommandPoints");
Plugin commandPoints=pPlugin.getServer().getPluginManager().getPlugin("CommandPoints");
if(commandPoints!=null){
pp=((CommandPoints)commandPoints).getAPI();
}
}
@Override
public int getPoints(OfflinePlayer player){
return pp.getPoints(player.getName(),this.mPlugin);
}
@Override
public int setPoints(OfflinePlayer player,int points){
pp.setPoints(player.getName(),points,this.mPlugin);
return getPoints(player);
}
@Override
public int takePoints(OfflinePlayer player,int points){
pp.removePoints(player.getName(),points,"Purchase",this.mPlugin);
return getPoints(player);
}
@Override
public int givePoints(OfflinePlayer player,int points){
pp.addPoints(player.getName(),points,"Reward",this.mPlugin);
return getPoints(player);
}
}

View File

@ -0,0 +1,67 @@
package org.black_ixx.bossshop.points;
import org.black_ixx.bossshop.BossShop;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.plugin.Plugin;
import com.enjin.officialplugin.points.ErrorConnectingToEnjinException;
import com.enjin.officialplugin.points.PlayerDoesNotExistException;
import com.enjin.officialplugin.points.PointsAPI.Type;
public class EnjinPointsAPI extends IPointsAPI{
public EnjinPointsAPI(BossShop pPlugin){
super(pPlugin,"EnjinMinecraftPlugin");
final Plugin plugin=Bukkit.getServer().getPluginManager().getPlugin("EnjinMinecraftPlugin");
if(plugin==null){
// Sinnlos? Wird Klasse wird eh nur erstellt wenn es Plugin gibt
this.mPlugin.warn("PlayerPoints was not found... You need it if you want to work with Points! Get it there: http://dev.bukkit.org/server-mods/playerpoints/");
return;
}
}
public int getPoints(OfflinePlayer player){
try{
return com.enjin.officialplugin.points.PointsAPI.getPointsForPlayer(player.getName());
}catch(PlayerDoesNotExistException e){
this.mPlugin.warn("[Enjin Minecraft Plugin] Not able to get Player "+player.getName()+". Not Existing!");
}catch(ErrorConnectingToEnjinException e){
this.mPlugin.warn("[Enjin Minecraft Plugin] Not able to connect to Enjin!");
}
return 0;
}
public int setPoints(OfflinePlayer player,int points){
com.enjin.officialplugin.points.PointsAPI.modifyPointsToPlayerAsynchronously(player.getName(),points,Type.SetPoints);
return points;
}
public int takePoints(OfflinePlayer player,int points){
String name=player.getName();
try{
return com.enjin.officialplugin.points.PointsAPI.modifyPointsToPlayer(name,points,Type.RemovePoints);
}catch(NumberFormatException e){
this.mPlugin.warn("[Enjin Minecraft Plugin] Not able to take Points... \"NumberFormatException\" Tried to take "+points+" Points from "+name+".");
}catch(PlayerDoesNotExistException e){
this.mPlugin.warn("[Enjin Minecraft Plugin] Not able to get Player "+name+". Not Existing!");
}catch(ErrorConnectingToEnjinException e){
this.mPlugin.warn("[Enjin Minecraft Plugin] Not able to connect to Enjin!");
}
return getPoints(player);
}
public int givePoints(OfflinePlayer player,int points){
String name=player.getName();
try{
return com.enjin.officialplugin.points.PointsAPI.modifyPointsToPlayer(name,points,Type.AddPoints);
}catch(NumberFormatException e){
this.mPlugin.warn("[Enjin Minecraft Plugin] Not able to take Points... \"NumberFormatException\" Tried to take "+points+" Points from "+name+".");
}catch(PlayerDoesNotExistException e){
this.mPlugin.warn("[Enjin Minecraft Plugin] Not able to get Player "+name+". Not Existing!");
}catch(ErrorConnectingToEnjinException e){
this.mPlugin.warn("[Enjin Minecraft Plugin] Not able to connect to Enjin!");
}
return getPoints(player);
}
}

View File

@ -0,0 +1,38 @@
package org.black_ixx.bossshop.points;
import org.black_ixx.bossshop.BossShop;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
public class FailedPointsAPI extends IPointsAPI{
public FailedPointsAPI(BossShop pPlugin){
super(pPlugin,"Failed");
}
public int getPoints(OfflinePlayer player){
informPlayer(player);
return 0;
}
public int setPoints(OfflinePlayer player,int points){
informPlayer(player);
return 0;
}
public int takePoints(OfflinePlayer player,int points){
informPlayer(player);
return 0;
}
public int givePoints(OfflinePlayer player,int points){
informPlayer(player);
return 0;
}
private void informPlayer(OfflinePlayer player){
Bukkit.getConsoleSender().sendMessage("PlayerPoints/CommandPoints was not found... "+"You need one of that plugins if you want to work with Points! "+"Get PlayerPoints there: "+"http://dev.bukkit.org/server-mods/playerpoints/");
if(player.isOnline()) player.getPlayer().sendMessage("[BossShop] Invalid configuration encountered. Please inform an administrator.");
}
}

View File

@ -0,0 +1,32 @@
package org.black_ixx.bossshop.points;
import org.black_ixx.bossshop.BossShop;
import org.bukkit.OfflinePlayer;
public abstract class IPointsAPI{
protected final String name;
protected BossShop mPlugin;
public IPointsAPI(BossShop pPlugin,String name){
this.mPlugin=pPlugin;
this.name=name;
}
public String getName(){
return name;
}
public abstract int getPoints(OfflinePlayer player);
public abstract int setPoints(OfflinePlayer player,int points);
public abstract int takePoints(OfflinePlayer player,int points);
public abstract int givePoints(OfflinePlayer player,int points);
public void register(){
PointsAPI.register(this);
}
}

View File

@ -0,0 +1,48 @@
package org.black_ixx.bossshop.points;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.playerpoints.PlayerPoints;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.plugin.Plugin;
public class PlayerPointsAPI extends IPointsAPI{
public PlayerPointsAPI(BossShop pPlugin){
super(pPlugin,"PlayerPoints");
final Plugin plugin=Bukkit.getServer().getPluginManager().getPlugin("PlayerPoints");
if(plugin!=null){
pp=(PlayerPoints.class.cast(plugin));
}else{
// Sinnlos? Wird Klasse wird eh nur erstellt wenn es Plugin gibt
this.mPlugin.warn("PlayerPoints was not found... You need it if you want to work with Points! Get it there: http://dev.bukkit.org/server-mods/playerpoints/");
return;
}
}
private PlayerPoints pp;
@Override
public int getPoints(OfflinePlayer player){
return pp.getAPI().look(player.getName());
}
@Override
public int setPoints(OfflinePlayer player,int points){
pp.getAPI().set(player.getName(),points);
return points;
}
@Override
public int takePoints(OfflinePlayer player,int points){
pp.getAPI().take(player.getName(),points);
return getPoints(player);
}
@Override
public int givePoints(OfflinePlayer player,int points){
pp.getAPI().give(player.getName(),points);
return getPoints(player);
}
}

View File

@ -0,0 +1,18 @@
package org.black_ixx.bossshop.points;
import java.util.HashMap;
/**
* 用于支持其他插件注册点券插件
*
*/
public class PointsAPI {
private static HashMap<String, IPointsAPI> interfaces = new HashMap<String, IPointsAPI>();
public static void register(IPointsAPI points) {
interfaces.put(points.getName(), points);
}
public static IPointsAPI get(String name) {
return interfaces.get(name);
}
}

View File

@ -0,0 +1,43 @@
package org.black_ixx.bossshop.points;
import org.black_ixx.bossshop.BossShop;
import org.bukkit.OfflinePlayer;
import org.bukkit.plugin.Plugin;
import me.BukkitPVP.PointsAPI.PointsAPI;
public class PointsAPIPlugin extends IPointsAPI{
private PointsAPI pp;
public PointsAPIPlugin(BossShop pPlugin){
super(pPlugin,"PointsAPI");
Plugin pointsApi=this.mPlugin.getServer().getPluginManager().getPlugin("PointsAPI");
if(pointsApi!=null){
pp=((PointsAPI)pointsApi);
}
}
@Override
public int getPoints(OfflinePlayer player){
return pp.getPoints(player);
}
@Override
public int setPoints(OfflinePlayer player,int points){
pp.setPoints(player.getPlayer(),points);
return getPoints(player);
}
@Override
public int takePoints(OfflinePlayer player,int points){
pp.removePoints(player,points);
return getPoints(player);
}
@Override
public int givePoints(OfflinePlayer player,int points){
pp.addPoints(player,points);
return getPoints(player);
}
}

View File

@ -0,0 +1,142 @@
package org.black_ixx.bossshop.points;
import org.black_ixx.bossshop.BossShop;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import cc.util.bossshop.pluginmodel.INeedConfig;
import cc.util.bossshop.pluginmodel.INeedReload;
public class PointsManager extends IPointsAPI implements INeedConfig,INeedReload{
private IPointsAPI pa;
private PointsPlugin mPointPlugin;
private String mPointsPlugin="auto-detect";
public enum PointsPlugin{
PLAYERPOINTS,COMMANDPOINTS,ENJIN_MINECRAFT_PLUGIN,POINTSAPI,CUSTOM;
private String name;
public void setCustom(String name){
this.name=name;
}
public String getCustom(){
return name;
}
}
/**
* 点券管理系统
*/
public PointsManager(BossShop pPlugin){
super(pPlugin,"");
this.mPlugin.registerConfigModel(this);
this.mPlugin.registerReloadModel(this);
}
public String getPluginName(){
return this.mPointPlugin==null?"":this.mPointPlugin.name();
}
@Override
public void setConfig(){
this.mPointsPlugin=this.mPlugin.getConfigManager().getConfig().getString("PointsPlugin",this.mPointsPlugin);
}
public boolean reloadConfig(){
mPointPlugin=null;
if(mPointsPlugin!=null){
if(Bukkit.getPluginManager().getPlugin("PlayerPoints")!=null){
mPointPlugin=PointsPlugin.PLAYERPOINTS;
}
if(Bukkit.getPluginManager().getPlugin("CommandPoints")!=null){
if(mPointPlugin==null||mPointsPlugin.equalsIgnoreCase("CommandPoints"))
mPointPlugin=PointsPlugin.COMMANDPOINTS;
}
if(Bukkit.getPluginManager().getPlugin("PointsAPI")!=null){
if(mPointPlugin==null||mPointsPlugin.equalsIgnoreCase("PointsAPI"))
mPointPlugin=PointsPlugin.POINTSAPI;
}
if(Bukkit.getPluginManager().getPlugin("EnjinMinecraftPlugin")!=null){
if(mPointPlugin==null||mPointsPlugin.equalsIgnoreCase("EnjinMinecraftPlugin"))
mPointPlugin=PointsPlugin.ENJIN_MINECRAFT_PLUGIN;
}
if(PointsAPI.get(mPointsPlugin)!=null){
mPointPlugin=PointsPlugin.CUSTOM;
mPointPlugin.setCustom(mPointsPlugin);
}
}
if (mPointPlugin==null) {
this.mPlugin.severe("未找到任何支持的点券插件");
pa = new FailedPointsAPI(this.mPlugin);
return false;
}else if(mPointsPlugin.equalsIgnoreCase("auto-detect")){
this.mPlugin.info("自动选择"+mPointPlugin.toString()+"点券插件");
}else if(!mPointPlugin.toString().equalsIgnoreCase(mPointsPlugin)){
this.mPlugin.severe("未找到配置文件中指定的"+mPointsPlugin+"点券插件,但是发现了支持的点券插件"+mPointPlugin.toString()+",将此插件作为默认");
}else{
this.mPlugin.info("自定义点券插件为 " + mPointPlugin.name() + ".");
}
switch (mPointPlugin) {
case COMMANDPOINTS:
if (Bukkit.getPluginManager().getPlugin("CommandPoints") == null) {
this.mPlugin.severe("You defined CommandPoints as the Points Plugin... BUT IT WAS NOT FOUND?! Please download it at Bukkit.org!");
return false;
}
pa = new CommandPointsAPI(this.mPlugin);
return false;
case ENJIN_MINECRAFT_PLUGIN:
if (Bukkit.getPluginManager().getPlugin("EnjinMinecraftPlugin") == null) {
this.mPlugin.severe("You defined Enjin Minecraft Plugin as the Points Plugin... BUT IT WAS NOT FOUND?! Please download it at Bukkit.org!");
return false;
}
pa = new EnjinPointsAPI(this.mPlugin);
return false;
case PLAYERPOINTS:
if (Bukkit.getPluginManager().getPlugin("PlayerPoints") == null) {
this.mPlugin.severe("You defined PlayerPoints as the Points Plugin... BUT IT WAS NOT FOUND?! Please download it at Bukkit.org!");
return false;
}
pa = new PlayerPointsAPI(this.mPlugin);
return false;
case POINTSAPI:
if (Bukkit.getPluginManager().getPlugin("PointsAPI") == null) {
this.mPlugin.severe("You defined PointsAPI as the Points Plugin... BUT IT WAS NOT FOUND?! Please download it at Bukkit.org!");
return false;
}
pa = new PointsAPIPlugin(this.mPlugin);
return false;
case CUSTOM:
IPointsAPI customPoints = PointsAPI.get(mPointPlugin.getCustom());
if (customPoints != null) {
pa = customPoints;
return false;
}
break;
}
this.mPlugin.warn("PlayerPoints/CommandPoints was not found... You need one of those plugins if you want this plugin to work with Points! Get PlayerPoints here: http://dev.bukkit.org/server-mods/playerpoints/");
pa = new FailedPointsAPI(this.mPlugin);
return true;
}
public int getPoints(OfflinePlayer player){
return pa.getPoints(player);
}
public int setPoints(OfflinePlayer player,int points){
return pa.setPoints(player,points);
}
public int givePoints(OfflinePlayer player,int points){
return pa.givePoints(player,points);
}
public int takePoints(OfflinePlayer player,int points){
return pa.takePoints(player,points);
}
}

View File

@ -0,0 +1,243 @@
package org.black_ixx.bossshop.sale;
import java.util.HashMap;
import org.apache.commons.lang.StringUtils;
import org.black_ixx.bossshop.BossShop;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import cc.util.bossshop.JsonExtra;
import cc.util.bossshop.JsonExtra.ClickAction;
import cc.util.bossshop.JsonExtra.Color;
import cc.util.bossshop.JsonExtra.HoverAction;
import cc.util.bossshop.JsonExtra.Style;
public class SaleListener implements Listener{
private BossShop mPlugin;
private HashMap<Player,SaleParameter> mForSale=new HashMap<>();
public SaleListener(BossShop pPlugin){
this.mPlugin=pPlugin;
this.mPlugin.getServer().getPluginManager().registerEvents(this,this.mPlugin);
}
private String C(String pNode){
return this.mPlugin.C(pNode);
}
@EventHandler(priority=EventPriority.LOW)
public void onPlayerChat(AsyncPlayerChatEvent pEvent){
synchronized(this){
if(!this.needHandle(pEvent.getPlayer(),pEvent.getMessage())) return;
pEvent.setCancelled(true);
this.handlePlayerMsg(pEvent.getPlayer(),pEvent.getMessage());
}
}
protected boolean needHandle(Player sender,String pMsg){
if(sender==null||StringUtils.isEmpty(pMsg)) return false;
if(pMsg.startsWith("/")) return false; //跳过命令
SaleParameter tParam=this.mForSale.get(sender);
if(tParam==null) return false;
if(tParam.mStep==SaleStep.Finish){
this.stopSaleListenrer(sender);
return false;
}
return true;
}
/**
* 处理玩家发送的消息
* <p>调用前,请先使用{@link SaleListener#needHandle(Player, String)}检查是否因该处理</p>
* @param pSender 消息发送者
* @param pMsg 发送的消息
*/
protected void handlePlayerMsg(Player pSender,String pMsg){
SaleParameter tParam=this.mForSale.get(pSender);
if(this.handleStep(pSender,tParam,pMsg)){
tParam.mStep=SaleStep.getNext(tParam.mStep);
}
this.showStepIntroduce(pSender,tParam);
if(tParam.mStep==SaleStep.Finish)
this.mForSale.remove(pSender);
}
public SaleParameter stopSaleListenrer(Player pPlayer){
SaleParameter removeParam= this.mForSale.remove(pPlayer);
if(removeParam==null){
//this.mPlugin.send(pPlayer,"你没有开始寄售");
}else{
this.mPlugin.send(pPlayer,C("Sale.ChatSaleExit"));
}
return removeParam;
}
public void startSaleListenrer(Player pPlayer){
SaleParameter tp=this.mForSale.get(pPlayer);
if(tp!=null){
if(tp.mStep==SaleStep.Finish){
tp.mStep=SaleStep.GoodsType;
}else{
this.mPlugin.send(pPlayer,C("Sale.ChatSaleRepartStart"));
return;
}
}else{
tp=new SaleParameter();
this.mForSale.put(pPlayer,tp);
}
this.mPlugin.send(pPlayer,C("Sale.ChatSaleStart"));
this.showStepIntroduce(pPlayer,tp);
}
/**
* 显示当前寄售步奏的提示
* @param pPlayer 用户名
* @param pStep 参数
*/
public void showStepIntroduce(Player pPlayer,SaleParameter pParam){
switch(pParam.mStep){
case GoodsType:
this.showSelect(pPlayer,this.mPlugin.getChatPrefix()+" "+C("Sale.IntroduceSellType")
,new String[]{C("Word.Item"),C("Word.Money"),C("Word.Points")}
,new String[]{"item","money","points"}
);
break;
case SingleNumb:
this.mPlugin.send(pPlayer,C("Sale.IntroduceSingleNumb"));
break;
case PartNumb:
this.mPlugin.send(pPlayer,C("Sale.IntroducePartNumb"));
break;
case PriceType:
this.showSelect(pPlayer,this.mPlugin.getChatPrefix()+" "+C("Sale.IntroducePriceType")
,new String[]{C("Word.Money"),C("Word.Points")}
,new String[]{"money","points"}
);
break;
case Price:
this.mPlugin.send(pPlayer,C("Sale.IntroducePrice"));
break;
case Finish:
this.mPlugin.send(pPlayer,C("Sale.ChatSaleFinish"));
JsonExtra chat=new JsonExtra(this.mPlugin.getChatPrefix()+" "+C("Sale.ClickSaleButtonFor"));
JsonExtra saleButton=new JsonExtra(C("Word.ForSale"),Color.blue);
saleButton.setStyle(Style.bold,Style.underline);
saleButton.setClickEvent(ClickAction.run_command,this.getSaleCommand(pParam));
saleButton.setHoverEvent(HoverAction.show_text,this.getSaleHover(pParam));
chat.addExtra(saleButton);
chat.sendToPlayer(pPlayer);
break;
}
}
private String getSaleCommand(SaleParameter pParam){
StringBuilder builder=new StringBuilder("/BS sale ");
builder.append(pParam.saleType.name()+" ");
builder.append(pParam.singleNumb+" ");
builder.append(pParam.partNumb+" ");
builder.append(pParam.priceType.name()+" ");
builder.append(pParam.price);
return builder.toString();
}
private String getSaleHover(SaleParameter pParam){
String color=C("Sale.NowSaleParameterColor");
if(!color.startsWith("§")) color="§a";
StringBuilder builder=new StringBuilder(color+C("Sale.NowSaleParameter")+"\n");
builder.append(color+C("Word.SellType")+": "+C("Word."+pParam.saleType.name())+"\n");
builder.append(color+C("Word.SigleNumb")+": "+pParam.singleNumb+"\n");
builder.append(color+C("Word.PartNumb")+": "+pParam.partNumb+"\n");
builder.append(color+C("Word.Price")+": "+pParam.price+C("Word."+pParam.priceType.name()));
return builder.toString();
}
/**
* 处理当前寄售步奏的玩家输入
* <p>
* 错误消息会在本函数中立刻显示
* </p>
* @param pPlayer 用户名
* @param pParam 已经处理的参数
* @param pMsg 当前参数的输入
* @return 是否处理成功
*/
public boolean handleStep(Player pPlayer,SaleParameter pParam,String pMsg){
SaleManager saleMan=this.mPlugin.getManager(SaleManager.class);
boolean result=false;
String successMsg=C("Sale.YouSetSaleParamTo");
switch(pParam.mStep){
case GoodsType:
if(!(result=saleMan.handleGoodsTypeInput(pParam,pPlayer,pMsg)))
this.mPlugin.send(pPlayer,pParam.errorInfo);
else{
successMsg=successMsg.replace("%param%",C("Word.SellType")).replace("%value%",C("Word."+pParam.saleType.name()));
this.mPlugin.send(pPlayer,successMsg);
}
return result;
case SingleNumb:
if(!(result=saleMan.handleSingleNumbInput(pParam,pPlayer,pMsg)))
this.mPlugin.send(pPlayer,pParam.errorInfo);
else{
successMsg=successMsg.replace("%param%",C("Word.SigleNumb")).replace("%value%",pParam.singleNumb+"");
this.mPlugin.send(pPlayer,successMsg);
}
return result;
case PartNumb:
if(!(result=saleMan.handlePartNumbInput(pParam,pPlayer,pMsg)))
this.mPlugin.send(pPlayer,pParam.errorInfo);
else{
successMsg=successMsg.replace("%param%",C("Word.PartNumb")).replace("%value%",pParam.partNumb+"");
this.mPlugin.send(pPlayer,successMsg);
}
return result;
case PriceType:
if(!(result=saleMan.handlePriceTypeInput(pParam,pPlayer,pMsg)))
this.mPlugin.send(pPlayer,pParam.errorInfo);
else{
successMsg=successMsg.replace("%param%",C("Word.PriceType")).replace("%value%",C("Word."+pParam.priceType.name()));
this.mPlugin.send(pPlayer,successMsg);
}
return result;
case Price:
if(!(result=saleMan.handlePriceInput(pParam,pPlayer,pMsg)))
this.mPlugin.send(pPlayer,pParam.errorInfo);
else{
successMsg=successMsg.replace("%param%",C("Word.Price")).replace("%value%",pParam.price+"");
this.mPlugin.send(pPlayer,successMsg);
}
return result;
case Finish:
throw new IllegalArgumentException("在聊天栏寄售状态为Finish时,不能处理输入参数");
}
return false;
}
/**
* 使用指定参数显示一个可点击的选项消息
* @param pPlayer 发送给谁
* @param pMsg 消息前缀
* @param pSelectDisName 选项显示名字
* @param pSelect 选项值
*/
protected void showSelect(Player pPlayer,String pMsg,String[] pSelectDisName,String[] pSelect){
JsonExtra main=new JsonExtra(pMsg);
JsonExtra goosType=new JsonExtra("",Color.gold);
goosType.setStyle(Style.bold,Style.underline);
for(int i=0;i<pSelectDisName.length;i++){
JsonExtra detailGoodsType=goosType.clone();
detailGoodsType.setText(pSelectDisName[i]);
detailGoodsType.setClickEvent(ClickAction.run_command,pSelect[i]);
detailGoodsType.setHoverEvent(HoverAction.show_text,Color.gold+pSelect[i]);
main.addExtra(detailGoodsType);
if(i!=pSelectDisName.length-1)
main.addNormalWords(", ",true);
}
main.sendToPlayer(pPlayer);
}
}

View File

@ -0,0 +1,656 @@
package org.black_ixx.bossshop.sale;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.black_ixx.bossshop.BossShop;
import org.black_ixx.bossshop.command.CommandSale;
import org.black_ixx.bossshop.core.BSBuy;
import org.black_ixx.bossshop.core.BSEnums;
import org.black_ixx.bossshop.core.BSShop;
import org.black_ixx.bossshop.core.BSShopManager;
import org.black_ixx.bossshop.nbt.NBTEditManager;
import org.black_ixx.bossshop.points.PointsManager;
import org.black_ixx.bossshop.core.BSEnums.BSBuyType;
import org.black_ixx.bossshop.managers.DefaultCreator;
import org.black_ixx.bossshop.managers.ItemNameManager;
import org.black_ixx.bossshop.managers.LangManager;
import org.black_ixx.bossshop.managers.WorthHandler;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import cc.util.bossshop.FBukkit;
import cc.util.bossshop.config.CommentedYamlConfig;
import cc.util.bossshop.pluginmodel.INeedConfig;
/**
* 玩家寄售系统
* @author 聪聪
*
*/
public class SaleManager implements INeedConfig{
public static final String CFG_MAIN="SaleSystem";
public static final String CFG_ShopBaseName="ShopBaseName";
public static final String CFG_ShopSize="ShopSize";
public static final String CFG_ShopMaxNumb="ShopMaxNumb";
public static final String CFG_SaleTime="SaleTime";
public static final String CFG_MoneyItem="MoneyItem";
public static final String CFG_MoneyPoundage="MoneyPoundage";
public static final String CFG_PointsItem="PointsItem";
public static final String CFG_PointsPoundage="PointsPoundage";
public static final String CFG_PerOneSaleLimit="PerOneSaleLimit";
public static final String CFG_UnsaleCost="UnsaleCost";
public static final String CFG_UnsaleCount="UnsaleCount";
public static final String CFG_SaleItemName="SaleItemName";
public static final String CFG_SaleItemLore="SaleItemLore";
private static final Pattern PATTERN = Pattern.compile("[%]([^%]+)[%]");
private final static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm");
private BossShop mPlugin;
private int mSaleTime=86400;
private int mPerOneSaleLimit=1;
private int mMoneyItem=9;
private int mPointsItem=10;
private int mShopMaxNumb=2;
private int mShopSize=54;
private int mMoneyPoundage=5;
private int mPointsPoundage=5;
private int mUnsaleCost=1000;
private int mUnsaleCount=3;
private String mShopBaseName="SYSTEM_SALE";
private String mSaleItemName="&2寄售: %bs_sale_item_sigle_count% %bs_sale_item_name%";
private final ArrayList<String> mSaleItemLore;
private final HashMap<BSBuyType,String> mLang=new HashMap<>();
public SaleManager(BossShop pplugin){
this.mPlugin=pplugin;
this.mSaleItemLore=new ArrayList<>();
this.mSaleItemLore.add("&2寄售编号: %bs_sale_item_id%");
this.mSaleItemLore.add("&3寄售者: %bs_sale_owner_name%");
this.mSaleItemLore.add("&c价格: %bs_sale_price% %bs_sale_price_type%");
this.mPlugin.registerConfigModel(this);
}
@Override
public void setConfig(){
//配置文件
CommentedYamlConfig tConfig=this.mPlugin.getConfigManager().getConfig();
ConfigurationSection sec=tConfig.getConfigurationSection(CFG_MAIN);
if(sec==null) sec=tConfig.createSection(CFG_MAIN);
this.mShopBaseName=sec.getString(CFG_ShopBaseName);
this.mMoneyItem=sec.getInt(CFG_MoneyItem,0);
if(this.mMoneyItem==0||org.bukkit.Material.getMaterial(this.mMoneyItem)==null){
this.mMoneyItem=9;
sec.set(CFG_MoneyItem,this.mMoneyItem);
}
this.mPointsItem=sec.getInt(CFG_PointsItem,0);
if(this.mPointsItem==0||org.bukkit.Material.getMaterial(this.mPointsItem)==null){
this.mPointsItem=10;
sec.set(CFG_PointsItem,this.mPointsItem);
}
this.mSaleTime=sec.getInt(CFG_SaleTime,this.mSaleTime);
this.mPerOneSaleLimit=sec.getInt(CFG_PerOneSaleLimit,this.mPerOneSaleLimit);
this.mShopSize=sec.getInt(CFG_ShopSize,this.mShopSize);
this.mShopMaxNumb=sec.getInt(CFG_ShopSize,this.mShopMaxNumb);
this.mMoneyPoundage=sec.getInt(CFG_MoneyPoundage,this.mMoneyPoundage);
this.mPointsPoundage=sec.getInt(CFG_PointsPoundage,this.mPointsPoundage);
this.mUnsaleCount=sec.getInt(CFG_UnsaleCount,this.mUnsaleCount);
this.mUnsaleCost=sec.getInt(CFG_UnsaleCost,this.mUnsaleCost);
this.mSaleItemName=sec.getString(CFG_SaleItemName,this.mSaleItemName);
List<String> list=sec.getStringList(CFG_SaleItemLore);
if(list!=null&&!list.isEmpty()){
this.mSaleItemLore.clear();
this.mSaleItemLore.addAll(list);
}
this.mPlugin.getConfigManager().saveConfig();
//语言文件
LangManager tLang=this.mPlugin.getLangManager();
this.mLang.clear();
this.mLang.put(BSBuyType.Money,tLang.get("Word.Money"));
this.mLang.put(BSBuyType.Points,tLang.get("Word.Points"));
this.mLang.put(BSBuyType.Item,tLang.get("Word.Item"));
}
/**
* 给予上架物品出售后的收获,如果所有者在线,通知所有者物品被购买
* @param pPlayer 玩家
* @param pBuy 售出的物品
*/
public void giveSaleReward(BSBuy pBuy){
if(pBuy==null) return;
if(!pBuy.hasOwner()) return;
Player player=Bukkit.getPlayer(pBuy.getOwner());
if(player==null){
this.mPlugin.warn(C("CFG.UnableFoundSaleOwner"));
return;
}
int numb=0;
WorthHandler wHandler=this.mPlugin.getManager(WorthHandler.class);
switch(pBuy.getPriceType()){
case Money:
numb=SaleManager.getActualySaleReward((Integer)pBuy.getPrice(),this.mMoneyPoundage);
wHandler.giveRewardMoney(player,numb);
break;
case Points:
numb=SaleManager.getActualySaleReward((Integer)pBuy.getPrice(),this.mPointsPoundage);
wHandler.giveRewardPoints(player,numb);
break;
default:
this.mPlugin.warn(C("CFG.UnknowSalePriceType"));
break;
}
this.mPlugin.send(player,C("Cmd.YouSaleHasSellOne")+"["+pBuy.getName()+"]");
}
private String C(String pNode){
return this.mPlugin.getLangManager().getNode(pNode);
}
/**
* 采用四舍五入发计算收取手续费后的收入
* @param pNowReward
* @param pPoundage
* @return
*/
public static int getActualySaleReward(int pNowReward,int pPoundage){
if(pPoundage<0||pPoundage>=100) return pNowReward;
int t=pNowReward*(100-pPoundage);
int unSolve=t%100;
if(unSolve==0){
return t/100;
}else{
return t/100+(unSolve<50?0:1);
}
}
public int getShopMaxCount(){
return this.mShopMaxNumb;
}
public String getShopBaseName(){
return this.mShopBaseName;
}
public int getUnsaleCount(){
return this.mUnsaleCount;
}
public int getUnSaleCost(){
return this.mUnsaleCost;
}
public BSBuy getSaleItem(String pName){
for(int i=1;i<this.mShopMaxNumb;i++){
BSShop tShop=this.mPlugin.getManager(BSShopManager.class).getShop(this.mShopBaseName+i);
if(tShop==null) continue;
BSBuy tBuy=tShop.getShopItem(pName);
if(tBuy==null||!tBuy.hasOwner()) continue;
else return tBuy;
}
return null;
}
/**
* 获取所有在寄售物品的编号
*/
public ArrayList<String> getSaleItemsName(){
return this.getSaleItemsName(null);
}
/**
* 获取指定玩家所有在寄售物品编号
* <p>如果玩家未null,将返回所有在寄售物品编号</p>
* @param pPlayer 玩家,可以为null
*/
public ArrayList<String> getSaleItemsName(Player pPlayer){
ArrayList<String> allSale=new ArrayList<>();
for(int i=1;i<this.mShopMaxNumb;i++){
BSShop tShop=this.mPlugin.getManager(BSShopManager.class).getShop(this.mShopBaseName+i);
if(tShop==null) continue;
for(BSBuy sBuy : tShop.getItems().values()){
if(!sBuy.hasOwner()) continue;
if(pPlayer==null||sBuy.getOwner().equals(pPlayer.getUniqueId()))
allSale.add(sBuy.getName());
}
}
return allSale;
}
/**
* 获取玩家寄售数量
* @param pName 玩家名
*/
public int getForSaleNumb(Player pPlayer){
int count=0;
for(int i=1;i<this.mShopMaxNumb;i++){
BSShop tShop=this.mPlugin.getManager(BSShopManager.class).getShop(this.mShopBaseName+i);
if(tShop==null) continue;
for(BSBuy sbuy : tShop.getItems().values())
if(sbuy.hasOwner()&&sbuy.getOwner().equals(pPlayer.getUniqueId())) count++;
}
return count;
}
/**
* 获取下一个可用的商店,并同时获取商店放置位置
* <p>如果shop为null,说明无可用的商店用于上架</p>
*/
public SaleParameter getAvailableShop(SaleParameter pParam){
BSShop taregt_shop=null;
BSShopManager shopMan=this.mPlugin.getManager(BSShopManager.class);
BSShop frontShop=shopMan.getShop(this.mPlugin.getConfigManager().getMainShop());
int target_loc=0,i;
for(i=1;i<=this.mShopMaxNumb;i++){
String tShopname=this.mShopBaseName+i;
taregt_shop=shopMan.getShop(tShopname);
if(taregt_shop!=null){
frontShop=taregt_shop;
target_loc=taregt_shop.getNextAvailableLoc();
if(target_loc<=0||target_loc>this.mShopMaxNumb-2) continue;
break;
}else{
taregt_shop=this.createShop(frontShop,tShopname,i);
target_loc=1;
break;
}
}
if(i<=this.mShopMaxNumb){
pParam.shop=taregt_shop;
pParam.location=target_loc;
}
return pParam;
}
/**
* 创建一个寄售商店
* @param pShopname 商店名
* @param pIndex 寄售商店索引
* @return 创建好的商店
*/
private BSShop createShop(BSShop pFrontShop,String pShopname,int pIndex){
File tFile=new File(this.mPlugin.getDataFolder().getAbsolutePath()+"/shops/"+pShopname+".yml");
CommentedYamlConfig tConfig=new CommentedYamlConfig();
tConfig.loadFromFile(tFile);
String tname=C("Word.SaleShop")+" "+pIndex;
DefaultCreator.setSettings(tConfig,tname,tname);
//设置返回键
if(pIndex==1){
String tMainShop=this.mPlugin.getConfigManager().getMainShop();
DefaultCreator.setGuidItem(tConfig,this.mShopSize-1,348,tMainShop,"RETURN_TO_FROUNT");
}else{
DefaultCreator.setGuidItem(tConfig,this.mShopSize-1,348,this.mShopBaseName+(pIndex-1),"RETURN_TO_FROUNT");
if(pFrontShop!=null){
CommentedYamlConfig tFrontConfig=pFrontShop.getConfig();
DefaultCreator.setGuidItem(tFrontConfig,this.mShopSize,331,pShopname,tname,"GOTO_TO_NEXT");
pFrontShop.saveConfig();
pFrontShop.reloadConfig();
}
}
//设置下一个按键
BSShopManager shopMan=this.mPlugin.getManager(BSShopManager.class);
if(pIndex!=this.mShopMaxNumb&&shopMan.getShop("this.mShopBaseName+(pIndex+1)")!=null)
DefaultCreator.setGuidItem(tConfig,this.mShopSize,331,this.mShopBaseName+(pIndex+1),"GOTO_TO_NEXT");
tConfig.saveToFile(tFile);
BSShop tshop=new BSShop(this.mPlugin,pShopname+".yml",pShopname);
shopMan.addShop(tshop);
return tshop;
}
/**
* 物品上架接口
* @param player 命令发送人
* @param args 参数
* @return 是否成功上架,错误消息会立刻反馈给玩家
*/
public boolean sale(Player player,String[] args){
if(args.length!=5) return this.getHelp(player);
//检查寄售上限
if(this.getForSaleNumb(player)>=this.mPerOneSaleLimit&&!player.hasPermission("BossShop.sale.unlimited"))
return this.mPlugin.send(player,C("Cmd.SaleReachPreOneLimit"));
SaleParameter param=new SaleParameter();
//获取可用的商店
this.getAvailableShop(param);
if(param.shop==null)
return this.mPlugin.send(player,C("Cmd.SaleShopIsFull"));
//格式化参数
this.formatSale(param,player,args);
if(param.errorInfo!=null)
return this.mPlugin.send(player,ChatColor.RED+param.errorInfo);
ItemStack item=player.getItemInHand();
if(param.saleType==BSBuyType.Item&&(item==null||item.getTypeId()==0))
return this.mPlugin.send(player,C("Cmd.YouShouldTakeItemInHand"));
//是否有足够的资本.此处会检查物品是否可以堆叠
if(!this.enough(param)) return false;
//查找可用的物品名字节点
ConfigurationSection sec_item_main=param.shop.getConfig().getConfigurationSection("shop");
ConfigurationSection sec_item=null;
long time=System.currentTimeMillis()/1000;
String sec_item_name=param.owner.getName()+"_"+time;
if(sec_item_main!=null){
do{
sec_item_name=param.owner.getName()+"_"+time;
time++;
}while(sec_item_main.contains(sec_item_name));
sec_item=sec_item_main.createSection(sec_item_name);
}else sec_item=param.shop.getConfig().createSection("shop."+sec_item_name);
param.mID=sec_item_name;
//替换文本变量
this.replaceInfoParam(param);
//设置上架物品到文件,并同时收取价格
//设置菜单物品到上架参数中,用于发送全服公告
this.setConfigSection(sec_item,param);
this.mPlugin.send(player,C("Cmd.ForSaleSuccessAndTisID")+sec_item_name);
//全服公告
this.sendSaleAnnoun(param);
return true;
}
/**
* 发送全服公告
*/
private void sendSaleAnnoun(SaleParameter param){
if(!param.owner.hasPermission("BossShop.sale.announce.other"))
return;
BSBuy saleBuy=param.shop.getShopItem(param.location-1);
for(Player sPlayer : FBukkit.getOnlinePlayers()){
saleBuy.getPersonalChatMenuItem(sPlayer,param.owner).sendToPlayer(sPlayer);
}
}
/**
* 根据上架参数,添加物品到商店配置文件中,并同时收取价格
* @param sec 要设置的节点
* @param param 上架参数
* @param pos 背包位置
*/
private void setConfigSection(ConfigurationSection sec,SaleParameter param){
ArrayList<String> item_info=new ArrayList<>();
String lore_prefix="&2";
for(String sStr : param.mLore) lore_prefix+="#"+sStr;
item_info.add("name:"+param.mDisplayName);
item_info.add("lore:"+lore_prefix);
ItemStack item=new ItemStack(Material.STONE);
ItemMeta meta=item.getItemMeta();
WorthHandler wHandler=this.mPlugin.getManager(WorthHandler.class);
switch(param.saleType){
case Money:
wHandler.takeMoney(param.owner,param.singleNumb*param.partNumb);
meta.setDisplayName(param.singleNumb+" "+C("Word.Money"));
item_info.add("id:"+this.mMoneyItem);
item.setTypeId(this.mMoneyItem);
item_info.add("amount:1");
sec.set("MenuItem",item_info);
sec.set("Reward",param.singleNumb);
break;
case Points:
wHandler.takePoints(param.owner,param.singleNumb*param.partNumb);
meta.setDisplayName(param.singleNumb+" "+C("Word.Points"));
item_info.add("id:"+this.mPointsItem);
item_info.add("amount:1");
sec.set("MenuItem",item_info);
sec.set("Reward",param.singleNumb);
break;
case Item:
item=param.owner.getItemInHand().clone();
ItemStack itemTake=item.clone();
itemTake.setAmount(param.singleNumb*param.partNumb);
ArrayList<ItemStack> listItem=new ArrayList<>();
listItem.add(itemTake);
wHandler.takeItems(param.owner,listItem);
item_info.add("type:"+item.getType().name());
item_info.add("durability:"+item.getDurability());
item_info.add("amount:"+param.singleNumb);
String nbtlabel=this.mPlugin.getManager(NBTEditManager.class).addItemNBTToStock(item,true);
if(nbtlabel!=null) item_info.add("nbt:"+nbtlabel);
sec.set("MenuItem",item_info);
item_info=new ArrayList<>();
if(item.getItemMeta().hasDisplayName()) item_info.add("name:"+item.getItemMeta().getDisplayName());
item_info.add("id:"+item.getTypeId());
item_info.add("durability:"+item.getDurability());
item_info.add("amount:"+param.singleNumb);
if(nbtlabel!=null) item_info.add("nbt:"+nbtlabel);
sec.set("Reward",item_info);
break;
default: break;
}
List<String> tLores=meta.getLore();
if(tLores==null) tLores=new ArrayList<String>();
tLores.add("&2"+C("Word.SaleID")+":"+param.mID);
Date date=new Date(System.currentTimeMillis()+this.mSaleTime*1000);
sec.set("TimeLimit.stop",sdf.format(date));
sec.set("HideItemFlag",this.mPlugin.getConfigManager().getHideItemFlag());
sec.set("HideNotTime",true);
sec.set("NumberLimit",param.partNumb);
tLores.add("&2"+C("Word.PartNumb")+":"+param.partNumb);
sec.set("HideNoStock",true);
sec.set("InventoryLocation",param.location);
sec.set("RewardType",param.saleType.toString());
sec.set("PriceType",param.priceType.toString());
sec.set("Price",param.price);
tLores.add("&2"+C("Word.Price")+":"+param.price+(param.priceType==BSBuyType.Money?C("Word.Money"):C("Word.Points")));
sec.set("Message",C("Word.YouBought")+param.mDisplayName);
sec.set("Owner",param.owner.getUniqueId().toString());
sec.set("OwnerOnlyForLook",param.owner.getName());
meta.setLore(tLores);
item.setItemMeta(meta);
param.shop.saveConfig();
param.shop.reloadConfig();
}
/**
* 玩家是否有足够的资本上架,如果不足会立刻发送错误消息给玩家
*/
private boolean enough(SaleParameter param){
WorthHandler wHandler=this.mPlugin.getManager(WorthHandler.class);
switch(param.saleType){
case Money:
return wHandler.hasMoney(param.owner,param.singleNumb*param.partNumb);
case Points:
return wHandler.hasPoints(param.owner,param.singleNumb*param.partNumb);
case Item:
ItemStack item=param.owner.getItemInHand().clone();
int maxCount=item.getMaxStackSize();
if(maxCount!=-1&&maxCount<param.singleNumb){
this.mPlugin.send(param.owner,C("Main.ItemCannotPileMoreThan")+maxCount);
return false;
}
item.setAmount(param.singleNumb*param.partNumb);
ArrayList<ItemStack> items=new ArrayList<>();
items.add(item);
return wHandler.hasItems(param.owner,items);
default:
break;
}
return false;
}
/**
* 从命令参数中生成上架物品的参数
* <p>如果参数错误,错误消息存储在SaleParameter.errorInfo中,
* 如果SaleParameter.errorInfo为空说明没有错误</p>
* @param pPlayer 玩家
* @param args 参数
* @return 上架物品参数
*/
private boolean formatSale(SaleParameter pParam,Player pPlayer,String[] args){
pParam.owner=pPlayer;
if(!this.handleGoodsTypeInput(pParam,pPlayer,args[0])) return false;
//单次的数量
if(!this.handleSingleNumbInput(pParam,pPlayer,args[1])) return false;
//几份
if(!this.handlePartNumbInput(pParam,pPlayer,args[2])) return false;
//价格类型
if(!this.handlePriceTypeInput(pParam,pPlayer,args[3])) return false;
//价格
if(!this.handlePriceInput(pParam,pPlayer,args[4])) return false;
return true;
}
protected boolean handleGoodsTypeInput(SaleParameter pParam,Player pPlayer,String pInput){
pParam.saleType=BSEnums.getBSBuyType(pInput);
if(pParam.saleType==null){
pParam.errorInfo=C("Cmd.UnknowSaleItemType")+"["+pInput+"]";
return false;
}
if(pParam.saleType!=BSBuyType.Item&&pParam.saleType!=BSBuyType.Money&&pParam.saleType!=BSBuyType.Points){
pParam.errorInfo=C("Cmd.UnsupportSaleItemType")+"["+pParam.saleType.toString()+"]";
return false;
}
return true;
}
protected boolean handleSingleNumbInput(SaleParameter pParam,Player pPlayer,String pInput){
try{
pParam.singleNumb=Integer.parseInt(pInput);
}catch(NumberFormatException nfexp){
pParam.errorInfo=ChatColor.RED+C("Word.SigleNumb")+" "+C("Cmd.MustBeNumb");
return false;
}
if(pParam.singleNumb<=0){
pParam.errorInfo=ChatColor.RED+C("Word.SigleNumb")+" "+C("Cmd.MustAboveZero");
return false;
}
return true;
}
protected boolean handlePartNumbInput(SaleParameter pParam,Player pPlayer,String pInput){
try{
pParam.partNumb=Integer.parseInt(pInput);
}catch(NumberFormatException nfexp){
pParam.errorInfo=ChatColor.RED+C("Word.PartNumb")+" "+C("Cmd.MustBeNumb");
return false;
}
if(pParam.partNumb<=0){
pParam.errorInfo=ChatColor.RED+C("Word.PartNumb")+" "+C("Cmd.MustAboveZero");
return false;
}
return true;
}
/**
* 处理价格类型输入
* <p>
* 处理失败,失败结果会存储在{@link SaleParameter#errorInfo}<br />
* 函数内同时会处理寄售类型和价格类型相同的情况
* </p>
* @param pParam 已经处理的参数
* @param pPlayer 输入者
* @param pInput 输入字符
* @return 是否处理成功
*/
protected boolean handlePriceTypeInput(SaleParameter pParam,Player pPlayer,String pInput){
pParam.priceType=BSEnums.getBSBuyType(pInput);
if(pParam.priceType==null){
pParam.errorInfo=C("Cmd.UnknowPriceType")+"["+pInput+"]";
return false;
}
if(pParam.priceType!=BSBuyType.Money&&pParam.priceType!=BSBuyType.Points){
pParam.errorInfo=C("Cmd.UnsupportPriceType")+"["+pParam.priceType.name()+"]";
return false;
}
//点券插件是否启用
if(pParam.priceType==BSBuyType.Points){
if(this.mPlugin.getManager(PointsManager.class)==null){
pParam.errorInfo=C("Cmd.ServerDisablePoints");
return false;
}
}
//不允许寄售物品和价格类型相同
if(pParam.priceType.name().equals(pParam.saleType.name())){
pParam.errorInfo=C("Cmd.SaleItemShouldNotSameWithPrice");
return false;
}
return true;
}
protected boolean handlePriceInput(SaleParameter pParam,Player pPlayer,String pInput){
try{
pParam.price=Integer.parseInt(pInput);
}catch(NumberFormatException nfexp){
pParam.errorInfo=ChatColor.RED+"<"+C("Word.Price")+">"+C("Cmd.MustBeNumb");
return false;
}
if(pParam.price<=0){
pParam.errorInfo=ChatColor.RED+"<"+C("Word.Price")+">"+C("Cmd.MustAboveZero");
return false;
}
return true;
}
/**
* 上架系统命令帮助
*/
public boolean getHelp(Player player){
return this.mPlugin.getCommandExc().getCommand(CommandSale.class).help(player);
}
/**
* 将寄售模板中的字符串变量替换之后放到寄售参数中
*/
public void replaceInfoParam(SaleParameter pParam){
pParam.mDisplayName=this.formatString(this.mSaleItemName,pParam);
pParam.mLore=new ArrayList<>();
for(String sStr : this.mSaleItemLore)
pParam.mLore.add(this.formatString(sStr,pParam));
}
/**
* 替换字符串中的变量,所有支持的变量:<br/>
* %bs_sale_owner_name%<br/>
* %bs_sale_item_id%<br/>
* %bs_sale_item_sigle_count%<br/>
* %bs_sale_item_part_count%<br/>
* %bs_sale_item_type%<br/>
* %bs_sale_item_name%<br/>
* %bs_sale_price%<br/>
* %bs_sale_price_type%<br/>
*/
protected String formatString(String pStr,SaleParameter pSaleParam){
Matcher tMatch=PATTERN.matcher(pStr);
while(tMatch.find()){
String tParam=tMatch.group(1);
String value=tParam;
if(tParam.equalsIgnoreCase("bs_sale_owner_name")){
value=pSaleParam.owner.getName();
}else if(tParam.equalsIgnoreCase("bs_sale_item_id")){
value=pSaleParam.mID;
}else if(tParam.equalsIgnoreCase("bs_sale_item_sigle_count")){
value=pSaleParam.singleNumb+"";
}else if(tParam.equalsIgnoreCase("bs_sale_item_part_count")){
value=pSaleParam.partNumb+"";
}else if(tParam.equalsIgnoreCase("bs_sale_item_type")){
value=this.mLang.get(pSaleParam.saleType);
}else if(tParam.equalsIgnoreCase("bs_sale_item_name")){
String tName="";
if(pSaleParam.saleType==BSBuyType.Item){
ItemStack tItem=pSaleParam.owner.getPlayer().getItemInHand();
tName=this.mPlugin.getManager(ItemNameManager.class).getDisPlayName(tItem);
}
else tName=this.mLang.get(pSaleParam.saleType);
value=tName;
}else if(tParam.equalsIgnoreCase("bs_sale_price")){
value=pSaleParam.price+"";
}else if(tParam.equalsIgnoreCase("bs_sale_price_type")){
value=this.mLang.get(pSaleParam.priceType);
}else this.mPlugin.warn(C("CFG.UnsupportSaleItemParam"));
if(tParam!=value)
pStr=pStr.replaceAll("%"+tParam+"%",value);
}
return pStr;
}
}

View File

@ -0,0 +1,41 @@
package org.black_ixx.bossshop.sale;
import java.util.ArrayList;
import org.black_ixx.bossshop.core.BSShop;
import org.black_ixx.bossshop.core.BSEnums.BSBuyType;
import org.bukkit.entity.Player;
class SaleParameter{
/**当前寄售步奏*/
public SaleStep mStep;
/**寄售物品的编号*/
public String mID;
/**所有者*/
public Player owner;
/**寄售物品类型*/
public BSBuyType saleType;
/**价格类型*/
public BSBuyType priceType;
/**价格*/
public int price;
/**单份售卖数量*/
public int singleNumb=0;
/**多少份*/
public int partNumb=0;
/**错误消息,如果无错误,此值为空*/
public String errorInfo=null;
/**寄售的商店,如果为空说明无位置可用*/
public BSShop shop=null;
/**商品放置位置,从1开始到81-2,剩余两个格子用作导航*/
public int location=1;
/**寄售物品显示的名字*/
public String mDisplayName;
/**寄售物品的lore*/
public ArrayList<String> mLore;
public SaleParameter(){
this.mStep=SaleStep.GoodsType;
}
}

View File

@ -0,0 +1,33 @@
package org.black_ixx.bossshop.sale;
public enum SaleStep{
// /BossShop sale <售卖类型> <单次数量> <份数> <价格类型> <价格>
GoodsType(1),
SingleNumb(2),
PartNumb(3),
PriceType(4),
Price(5),
Finish(6);
private final int mStepNumb;
private SaleStep(int pStepNumb){
this.mStepNumb=pStepNumb;
}
/**
* 获取基于当前步奏的下一步奏
* @param pStep
* @return
*/
public static SaleStep getNext(SaleStep pStep){
if(pStep==null) throw new IllegalArgumentException("获取下一步寄售步奏时,当前步奏不能为null");
if(pStep==SaleStep.Finish) return null;
int next=pStep.mStepNumb+1;
for(SaleStep sStep : SaleStep.values()){
if(sStep.mStepNumb==next) return sStep;
}
return null;
}
}

View File

@ -0,0 +1,67 @@
package org.black_ixx.bossshop.util;
import java.util.Collection;
import java.util.Map;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import cc.util.bossshop.ClassHelper;
import cc.util.bossshop.FBukkit;
import cc.util.bossshop.NMSHelper;
public class AttributeRemover{
private static boolean useItemFlags;
private static boolean useReflection;
public static boolean init(){
if(ClassHelper.isClassLoaded("org.bukkit.inventory.ItemFlag")){
useItemFlags=true;
}else{
FBukkit.severe("此服务器版本"+ClassHelper.getServerVersion()+"可能无法启用属性移除");
useReflection=true;
}
return true;
}
public static ItemStack hideAttributes(ItemStack item,int mFlags){
if(item==null) return null;
mFlags=mFlags & 0xFFFFFFFF;
if(useItemFlags){
ItemMeta meta=item.getItemMeta();
for(ItemFlag sFlag : ItemFlag.values()){
int pos=sFlag.ordinal();
int value=((1<<pos)&mFlags)>>pos;
if(value==1) meta.addItemFlags(sFlag);
else meta.removeItemFlags(sFlag);
//removeItemFlags
}
if(!FBukkit.isItemMetaEmpty(meta))
item.setItemMeta(meta);
return item;
}else if(useReflection&&mFlags>0){
try{
Object nmsItemstack=ClassHelper.invokeStaticMethod(NMSHelper.clazz_CraftItemStack,"asNMSCopy",ItemStack.class,item);
if(nmsItemstack==null) return item;
Object nbtCompound=ClassHelper.getFieldValue(nmsItemstack,NMSHelper.clazz_NBTTagCompound,-1);
if(nbtCompound==null){
nbtCompound=ClassHelper.getInstance(NMSHelper.clazz_NBTTagCompound);
ClassHelper.setFiledValue(nmsItemstack,NMSHelper.clazz_NBTTagCompound,nbtCompound,-1);
}
Object nbtList=ClassHelper.getInstance(NMSHelper.clazz_NBTTagList);
Map<String,Object> map=ClassHelper.getFieldValue(nbtCompound,Map.class,-1);
map.put("AttributeModifiers",nbtList);
return (ItemStack)ClassHelper.invokeStaticMethod(NMSHelper.clazz_CraftItemStack,"asCraftMirror",NMSHelper.clazz_NMSItemStack,nmsItemstack);
}catch(Exception e){}
}
return item;
}
private static boolean isNullOrEmpty(Collection<?> coll){
return coll==null||coll.isEmpty();
}
}

View File

@ -0,0 +1,13 @@
package org.black_ixx.bossshop.util;
public class Function{
public static void printStackTrace(){
StackTraceElement[] elements=Thread.currentThread().getStackTrace();
for(StackTraceElement sElement : elements){
System.out.println(sElement.toString());
}
}
}

View File

@ -0,0 +1,342 @@
package org.black_ixx.bossshop.util;
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.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.FileConfiguration;
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;
/**
* <p>自定义的Yml配置文件读取的实现</p>
* <p>读取的配置文件必须为utf8类型</p>
* <p>可显式的保存中文</p>
* <p>不能保存注释</p>
* @author 聪聪
*
*/
public class MyYamlConfig extends FileConfiguration{
protected static final String COMMENT_PREFIX="# ";
protected static final String BLANK_CONFIG="{}\n";
private static Yaml yaml;
static{
DumperOptions dumpOptions=new DumperOptions();
Representer yamlRepresenter=new YamlRepresenter();
dumpOptions.setIndent(2);
dumpOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
dumpOptions.setAllowUnicode(true);
if(!dumpOptions.isAllowUnicode()){
Class<DumperOptions> clazz=DumperOptions.class;
try{
Field field=clazz.getDeclaredField("allowUnicode");
field.setAccessible(true);
field.setBoolean(dumpOptions,true);
}catch(Exception exp){
MyYamlConfig.log("错误,无法设置文件存储为unicode编码",exp);
}
}
yamlRepresenter.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
MyYamlConfig.yaml=new Yaml(new YamlConstructor(),yamlRepresenter,dumpOptions);
}
public MyYamlConfig(){}
/**
* 在发生异常时用于输出调试信息,或输出警告信息到控制台
* @param level 错误等级
* @param msg 错误的提示消息
* @param thrown 要抛出的异常
*/
private static void log(String msg,Throwable thrown){
if(Bukkit.getServer()!=null){
ConsoleCommandSender tSender=Bukkit.getConsoleSender();
tSender.sendMessage(ChatColor.RED+"[ERROR] "+msg);
String[] lines= org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(thrown).split("\n");
for(String sLine : lines) tSender.sendMessage(ChatColor.RED+"[ERROR] "+sLine);
}else Logger.getLogger("minecraft").log(Level.SEVERE,msg,thrown);
}
@Override
public void addDefault(String path,Object value){
if(this.get(path)==null) this.set(path,value);
super.addDefault(path,value);
}
/**
* 保存当前配置内存中的数据为字符串
*/
public String saveToString(){
String header=buildHeader();
String dump=MyYamlConfig.yaml.dump(getValues(false));
if(dump.equals(BLANK_CONFIG)) dump="";
return header+dump;
}
/**
* 从字符串中载入配置
*/
public void loadFromString(String contents) throws InvalidConfigurationException{
Validate.notNull(contents,"字符串不能未null");
Map<?,?> input=null;
try{
input=(Map<?,?>)MyYamlConfig.yaml.load(contents);
}catch(YAMLException e){
throw new InvalidConfigurationException(e);
}catch(ClassCastException e){
throw new InvalidConfigurationException("配置文件顶级节点不是Map");
}
String header=parseHeader(contents);
if(header.length()>0){
options().header(header);
}
if(input!=null) convertMapsToSections(input,this);
}
/**
* 将从字符串生成的配置节点数据格式化复制到本实例中
* @param input 格式化后的数据
* @param section 本实例,用于递归
*/
protected void convertMapsToSections(Map<?,?> input,ConfigurationSection section){
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);
}
}
/**
* 构建配置文件注释头,保存到内存中
* @param input 文件内容字符串
* @return 构建完的头
*/
protected String parseHeader(String input){
String[] lines=input.split("\r?\n",-1);
StringBuilder result=new StringBuilder();
boolean readingHeader=true;
boolean foundHeader=false;
for(int i=0;(i<lines.length)&&(readingHeader);i++){
String line=lines[i];
if(line.startsWith(COMMENT_PREFIX)){
if(i>0) result.append("\n");
if(line.length()>COMMENT_PREFIX.length()){
result.append(line.substring(COMMENT_PREFIX.length()));
}
foundHeader=true;
}else if((foundHeader)&&(line.length()==0)){
result.append("\n");
}else if(foundHeader){
readingHeader=false;
}
}
return result.toString();
}
/**
* 保留配置文件的头部注释输出
*/
protected String buildHeader(){
String header=options().header();
if(header==null) return "";
StringBuilder builder=new StringBuilder();
String[] lines=header.split("\r?\n",-1);
boolean startedHeader=false;
for(int i=lines.length-1;i>=0;i--){
builder.insert(0,"\r\n");
if((startedHeader)||(lines[i].length()!=0)){
builder.insert(0,lines[i]);
builder.insert(0,COMMENT_PREFIX);
startedHeader=true;
}
}
return builder.toString();
}
/**
* 保存指定的数据到指定的文件,如果文件不存在将会自动创建
* <p>保存数据过程中的任何错误都会被记录到控制台然后忽视</p>
* @param file 指定的文件
* @param yml 指定的数据
*/
@Override
public void save(File file){
Validate.notNull(file,"配置文件不能为null");
MyYamlConfig.save(file,this);
}
/**
* 保存指定的数据到指定的文件,如果文件不存在将会自动创建
* <p>保存数据过程中的任何错误都会被记录到控制台然后忽视</p>
* @param file 指定的文件
* @param yml 指定的数据
*/
public static void save(File file,MyYamlConfig yml){
Validate.notNull(yml,"配置文件读取器不能为null");
Validate.notNull(file,"配置文件不能为null");
FileOutputStream output=null;
try{
if(!file.exists()) file.createNewFile();
output=new FileOutputStream(file,false);
output.write(yml.saveToString().getBytes("UTF-8"));
}catch(FileNotFoundException ex){
MyYamlConfig.log("未找到文件["+file+"]",ex);
}catch(IOException ex){
MyYamlConfig.log("无法保存文件["+file+"]",ex);
}finally{
if(output!=null) try{
output.close();
}catch(IOException exp){}
}
}
/**
* 为当前实例从给定的文件路径中载入数据
* <p>
* 载入配置文件过程中的任何错误都会被记录到控制台然后忽视
* 如果输入的文件不符合配置文件的格式规范,结果将返回一个空白文件
* <p>
* 编码默认使用 UTF-8
*
* @param filename 输入的文件路径
* @throws NullPointerException 如果文件名为空
*/
@Override
public void load(String filename){
MyYamlConfig.load(new File(filename),this);
}
/**
* 为当前实例从给定的文件中载入数据
* <p>
* 载入配置文件过程中的任何错误都会被记录到控制台然后忽视
* 如果输入的文件不符合配置文件的格式规范,结果将返回一个空白文件
* <p>
* 编码默认使用 UTF-8
*
* @param file 输入文件
* @throws IllegalArgumentException 如果文件为空
*/
@Override
public void load(File file){
MyYamlConfig.load(file,this);
}
/**
* 为当前实例从给定的流中载入数据,流不会自动关闭
* <p>
* 载入配置文件过程中的任何错误都会被记录到控制台然后忽视
* 如果输入的流不符合配置文件的格式规范,结果将返回一个空白文件
* <p>
* 编码默认使用 UTF-8
*
* @param stream 输入的数据流
* @param config 需要载入到的目标,可以为null
* @return 处理完后的内存中的配置文件
* @throws IllegalArgumentException 如果输入流为空
*/
@Override
public void load(InputStream stream){
MyYamlConfig.load(stream,this);
}
/**
* 创建一个新的 {@link MyYamlConfig}实例, 并从给定的文件中载入数据
* <p>
* 载入配置文件过程中的任何错误都会被记录到控制台然后忽视
* 如果输入的文件不符合配置文件的格式规范,结果将返回一个空白文件
* <p>
* 编码默认使用 UTF-8
*
* @param file 输入文件
* @param config 需要载入到的目标,可以为null
* @return 处理完后的内存中的配置文件
* @throws IllegalArgumentException 如果文件为空
*/
public static MyYamlConfig load(File file,MyYamlConfig config){
Validate.notNull(file,"文件不能为null");
if(config==null) config=new MyYamlConfig();
FileInputStream input=null;
byte[] contents=new byte[(int)file.length()];
try{
input=new FileInputStream(file);
input.read(contents);
config.loadFromString(new String(contents,"UTF-8"));
}catch(FileNotFoundException ex){
MyYamlConfig.log("无法找到文件["+file+"]",ex);
}catch(IOException ex){
MyYamlConfig.log("无法加载文件["+file+"]",ex);
}catch(InvalidConfigurationException ex){
MyYamlConfig.log("无法加载文件["+file+"] 配置文件格式错误",ex);
}finally{
if(input!=null) try{
input.close();
}catch(IOException exp){}
}
return config;
}
/**
* 创建一个新的 {@link MyYamlConfig}实例, 并从给定的流中载入数据,流不会自动关闭
* <p>
* 载入配置文件过程中的任何错误都会被记录到控制台然后忽视
* 如果输入的流不符合配置文件的格式规范,结果将返回一个空白文件
* <p>
* 编码默认使用 UTF-8
*
* @param stream 输入的数据流
* @param config 需要载入到的目标,可以为null
* @return 处理完后的内存中的配置文件
* @throws IllegalArgumentException 如果输入流为空
*/
public static MyYamlConfig load(InputStream stream,MyYamlConfig config){
Validate.notNull(stream,"输入流不能为空");
if(config==null) config=new MyYamlConfig();
try{
byte[] contents=new byte[stream.available()];
config.loadFromString(new String(contents,"UTF-8"));
}catch(IOException ex){
MyYamlConfig.log("无法从输入流加载配置",ex);
}catch(InvalidConfigurationException ex){
MyYamlConfig.log("无法从输入流加载配置",ex);
}
return config;
}
/**
* 设置输入路径的分割用字符,默认为"."
* @param value 作为分割路径用的字符
*/
public void pathSeparator(char value){
this.options().pathSeparator(value);
}
/**
* 获取路径分割用字符
* @return 分割路径用的字符
*/
public char pathSeparator(){
return this.options().pathSeparator();
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,156 @@
name: BossShop
version: 2.2.3
description: The BOSS Shop Plugin redone
author: Black_ixx
website: http://felix.neuby.de
main: org.black_ixx.bossshop.BossShop
softdepend: [PlaceholderAPI]
commands:
bs:
description: BossShop Command
bossshop:
description: BossShop Command
shop:
description: BossShop Command
permissions:
BossShop.createSign:
description: Allows to create BossShop Signs
default: op
BossShop:
description: BossShop全部权限
default: op
children:
BossShop.cmdcomplete: true
BossShop.help: true
BossShop.mail: true
BossShop.nbt: true
BossShop.open: true
BossShop.reload: true
BossShop.sale: true
BossShop.status.clear: true
BossShop.unsale: true
BossShop.cmdcomplete:
default: true
BossShop.help:
default: true
BossShop.nbt:
description: 操作BooShop NBT库存的相关权限
default: op
children:
BossShop.nbt.add: true
BossShop.nbt.clear: true
BossShop.nbt.help: true
BossShop.nbt.add:
default: op
BossShop.nbt.clear:
default: op
BossShop.nbt.help:
default: op
BossShop.mail:
description: 邮件命令的相关权限
default: op
children:
BossShop.mail.help: true
BossShop.mail.check: true
BossShop.mail.recive: true
BossShop.mail.send: true
BossShop.mail.check:
description: 检查邮件的权限
default: true
BossShop.mail.help:
description: 获取邮件命令帮助的权限
default: true
BossShop.mail.recive:
description: 接收邮件的权限
default: true
BossShop.mail.send:
description: 发送邮件的权限
default: op
BossShop.open:
description: 打开商店的权限
default: op
children:
BossShop.open.sign: true
BossShop.open.command: true
BossShop.open.item: true
BossShop.open.other: true
BossShop.open.sign:
description: 允许通过牌子打开商店
default: true
BossShop.open.command:
description: 允许通过命令打开商店
default: true
BossShop.open.other:
description: 允许打开其他玩家的商店
default: op
BossShop.open.item:
description: 允许通过物品来打开商店
default: op
BossShop.reload:
description: 重载配置
default: op
children:
BossShop.reload.all: true
BossShop.reload.help: true
BossShop.reload.lang: true
BossShop.reload.shop: true
BossShop.reload.all:
description: 重载BossShop所有配置的权限
default: op
BossShop.reload.config:
description: 重载BossShop商店配置的权限
default: op
BossShop.reload.help:
description: 获取/BS reload命令帮助的权限
default: op
BossShop.reload.lang:
description: 重载BossShop语言文件
default: op
BossShop.reload.shop:
description: 重载BossShop商店的权限
default: op
BossShop.sale:
description: BooShop 寄售系统相关权限
default: op
children:
BossShop.sale.forsale: true
BossShop.sale.unlimited: true
BossShop.sale.forsale:
description: 允许玩家寄售物品
default: op
BossShop.sale.announce.other:
description: 物品上架时发送全服公告的权限
default: op
BossShop.sale.unlimited:
description: 无视玩家寄售物品数量的上限
default: op
BossShop.status.clear:
description: 清理插件缓存数据的权限
default: op
BossShop.unsale:
description: 物品下架
default: op
children:
BossShop.unsale.user: true
BossShop.unsale.admin: true
BossShop.unsale.user:
description: 用户物品下架自己权限
default: true
BossShop.unsale.admin:
description: 管理员下架物品权限
default: op