diff --git a/fabric/src/main/java/cn/evole/mods/mcbot/McBot.java b/fabric/src/main/java/cn/evole/mods/mcbot/McBot.java index 8f65a32..40498eb 100644 --- a/fabric/src/main/java/cn/evole/mods/mcbot/McBot.java +++ b/fabric/src/main/java/cn/evole/mods/mcbot/McBot.java @@ -6,11 +6,10 @@ import cn.evole.mods.mcbot.init.callbacks.IEvents; import cn.evole.mods.mcbot.config.ModConfig; import cn.evole.mods.mcbot.init.handler.CustomCmdHandler; +import cn.evole.mods.mcbot.util.FileUtil; import cn.evole.mods.mcbot.util.lib.LibUtils; import cn.evole.mods.mcbot.util.locale.I18n; import cn.evole.onebot.client.OneBotClient; -import cn.evole.onebot.sdk.util.FileUtils; -import cn.evole.onebot.sdk.util.java.Assert; import lombok.Getter; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; @@ -71,9 +70,9 @@ public void onInitialize() { public void init() { CONFIG_FOLDER = Const.gameDir.resolve("mcbot"); - FileUtils.checkFolder(CONFIG_FOLDER); + FileUtil.checkFolder(CONFIG_FOLDER); LIB_FOLDER = CONFIG_FOLDER.resolve("libs"); - FileUtils.checkFolder(LIB_FOLDER); + FileUtil.checkFolder(LIB_FOLDER); CONFIG_FILE = CONFIG_FOLDER.resolve("config.toml"); LibUtils.create(LIB_FOLDER, "libs.txt").download(); I18n.init(); diff --git a/fabric/src/main/java/cn/evole/mods/mcbot/util/ClassUtil.java b/fabric/src/main/java/cn/evole/mods/mcbot/util/ClassUtil.java new file mode 100644 index 0000000..74fd43d --- /dev/null +++ b/fabric/src/main/java/cn/evole/mods/mcbot/util/ClassUtil.java @@ -0,0 +1,164 @@ +package cn.evole.mods.mcbot.util; + + +import cn.evole.mods.mcbot.Const; + +import java.io.File; +import java.net.JarURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +/** + * ClassUtil + * + * @author cnlimiter + * @version 1.0 + * @description 获取接口的所有实现类 理论上也可以用来获取类的所有子类 + * 查询路径有限制,只局限于接口所在模块下,比如pandora-gateway,而非整个pandora(会递归搜索该文件夹下所以的实现类) + * 路径中不可含中文,否则会异常。若要支持中文路径,需对该模块代码中url.getPath() 返回值进行urldecode. + * @date 2024/3/11 13:31 + */ +public class ClassUtil { + public static ArrayList getAllClassByInterface(Class clazz) { + ArrayList list = new ArrayList<>(); + // 判断是否是一个接口 + if (clazz.isInterface()) { + try { + ArrayList allClass = getAllClass(clazz.getPackage().getName()); + /** + * 循环判断路径下的所有类是否实现了指定的接口 并且排除接口类自己 + */ + for (int i = 0; i < allClass.size(); i++) { + /** + * 判断是不是同一个接口 + */ + // isAssignableFrom:判定此 Class 对象所表示的类或接口与指定的 Class + // 参数所表示的类或接口是否相同,或是否是其超类或超接口 + if (clazz.isAssignableFrom(allClass.get(i))) { + if (!clazz.equals(allClass.get(i))) { + // 自身并不加进去 + list.add(allClass.get(i)); + } + } + } + } catch (Exception e) { + Const.LOGGER.error("出现异常{}",e.getMessage()); + throw new RuntimeException("出现异常"+e.getMessage()); + } + } + Const.LOGGER.debug("class list size :"+list.size()); + return list; + } + + + /** + * 从一个指定路径下查找所有的类 + * + * @param packagename + */ + private static ArrayList getAllClass(String packagename) { + + List classNameList = getClassName(packagename); + ArrayList list = new ArrayList<>(); + + for(String className : classNameList){ + try { + list.add(Class.forName(className)); + } catch (ClassNotFoundException e) { + Const.LOGGER.error("load class from name failed:"+className+e.getMessage()); + throw new RuntimeException("load class from name failed:"+className+e.getMessage()); + } + } + Const.LOGGER.debug("find list size :"+list.size()); + return list; + } + + /** + * 获取某包下所有类 + * @param packageName 包名 + * @return 类的完整名称 + */ + public static List getClassName(String packageName) { + + List fileNames = null; + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + String packagePath = packageName.replace(".", "/"); + URL url = loader.getResource(packagePath); + if (url != null) { + String type = url.getProtocol(); + Const.LOGGER.debug("file type : " + type); + if (type.equals("file")) { + String fileSearchPath = url.getPath(); + Const.LOGGER.debug("fileSearchPath: "+fileSearchPath); + fileSearchPath = fileSearchPath.substring(0,fileSearchPath.indexOf("/classes")); + Const.LOGGER.debug("fileSearchPath: "+fileSearchPath); + fileNames = getClassNameByFile(fileSearchPath); + } else if (type.equals("jar")) { + try{ + JarURLConnection jarURLConnection = (JarURLConnection)url.openConnection(); + JarFile jarFile = jarURLConnection.getJarFile(); + fileNames = getClassNameByJar(jarFile,packagePath); + }catch (java.io.IOException e){ + throw new RuntimeException("open Package URL failed:"+e.getMessage()); + } + + }else{ + throw new RuntimeException("file system not support! cannot load MsgProcessor!"); + } + } + return fileNames; + } + + /** + * 从项目文件获取某包下所有类 + * @param filePath 文件路径 + * @return 类的完整名称 + */ + private static List getClassNameByFile(String filePath) { + List myClassName = new ArrayList(); + File file = new File(filePath); + File[] childFiles = file.listFiles(); + for (File childFile : childFiles) { + if (childFile.isDirectory()) { + myClassName.addAll(getClassNameByFile(childFile.getPath())); + } else { + String childFilePath = childFile.getPath(); + if (childFilePath.endsWith(".class")) { + childFilePath = childFilePath.substring(childFilePath.indexOf("\\classes") + 9, childFilePath.lastIndexOf(".")); + childFilePath = childFilePath.replace("\\", "."); + myClassName.add(childFilePath); + } + } + } + + return myClassName; + } + + /** + * 从jar获取某包下所有类 + * @return 类的完整名称 + */ + private static List getClassNameByJar(JarFile jarFile ,String packagePath) { + List myClassName = new ArrayList(); + try { + Enumeration entrys = jarFile.entries(); + while (entrys.hasMoreElements()) { + JarEntry jarEntry = entrys.nextElement(); + String entryName = jarEntry.getName(); + //LOG.info("entrys jarfile:"+entryName); + if (entryName.endsWith(".class")) { + entryName = entryName.replace("/", ".").substring(0, entryName.lastIndexOf(".")); + myClassName.add(entryName); + //LOG.debug("Find Class :"+entryName); + } + } + } catch (Exception e) { + Const.LOGGER.error("发生异常:"+e.getMessage()); + throw new RuntimeException("发生异常:"+e.getMessage()); + } + return myClassName; + } +} diff --git a/fabric/src/main/java/cn/evole/mods/mcbot/util/FileUtil.java b/fabric/src/main/java/cn/evole/mods/mcbot/util/FileUtil.java new file mode 100644 index 0000000..591510a --- /dev/null +++ b/fabric/src/main/java/cn/evole/mods/mcbot/util/FileUtil.java @@ -0,0 +1,25 @@ +package cn.evole.mods.mcbot.util; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +/** + * FileUtil + * + * @author cnlimiter + * @version 1.0 + * @description + * @date 2024/3/11 19:18 + */ +public class FileUtil { + public static void checkFolder(Path folder) { + if (!folder.toFile().isDirectory()) { + try { + Files.createDirectories(folder); + } catch (IOException ignored) { + } + } + + } +} diff --git a/fabric/src/main/resources/libs.txt b/fabric/src/main/resources/libs.txt index 33f0659..fde7fd1 100644 --- a/fabric/src/main/resources/libs.txt +++ b/fabric/src/main/resources/libs.txt @@ -1,4 +1,4 @@ ===ALGORITHM SHA-256 -cn.evole.onebot:OneBot-Client:0.4.0 1b4321761f5c3a1b52bbc350b0aabc1571d3c1ef8cd3df3eee09022a25678ee6 +cn.evole.onebot:OneBot-Client:0.4.0 3990bb0791cff13a2329aac6aae8aa18df77d7dac9d673a1961fb6750a4d545e cn.evole.config:AtomConfig-Toml:0.1.5 53e0c80d6d8fc789c8bdf75764474bf4a106e355d2dd761acb5ae627e14450c1