From 3a16311569e3903c5030af07cd60abfcde94732c Mon Sep 17 00:00:00 2001 From: "jiahua.liu" Date: Sat, 18 Jan 2020 16:30:52 +0800 Subject: [PATCH] plugin supporting --- .../net/mamoe/mirai/MiraiConsole.java | 1 + .../net/mamoe/mirai/MiraiMain.java | 0 .../net/mamoe/mirai/plugin/PluginBase.kt | 199 ++++++++++++++++++ 3 files changed, 200 insertions(+) rename mirai-console/src/main/{java => kotlin}/net/mamoe/mirai/MiraiConsole.java (99%) rename mirai-console/src/main/{java => kotlin}/net/mamoe/mirai/MiraiMain.java (100%) create mode 100644 mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt diff --git a/mirai-console/src/main/java/net/mamoe/mirai/MiraiConsole.java b/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsole.java similarity index 99% rename from mirai-console/src/main/java/net/mamoe/mirai/MiraiConsole.java rename to mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsole.java index da94d7f28..e2d0b7ed6 100644 --- a/mirai-console/src/main/java/net/mamoe/mirai/MiraiConsole.java +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsole.java @@ -16,4 +16,5 @@ public class MiraiConsole { public void log(Object o){ System.out.println(o); } + } diff --git a/mirai-console/src/main/java/net/mamoe/mirai/MiraiMain.java b/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiMain.java similarity index 100% rename from mirai-console/src/main/java/net/mamoe/mirai/MiraiMain.java rename to mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiMain.java diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt new file mode 100644 index 000000000..a391126fc --- /dev/null +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt @@ -0,0 +1,199 @@ +package net.mamoe.mirai.plugin + +import net.mamoe.mirai.utils.DefaultLogger +import java.io.File +import java.lang.Exception +import java.nio.charset.Charset +import java.util.jar.JarFile +import kotlin.math.log + + +abstract class PluginBase{ + + open fun onLoad(){ + + } + + open fun onEnable(){ + + } + + open fun onDisable(){ + + } + + fun getPluginManager():PluginManager{ + return PluginManager + } + + +} + +class PluginDescription( + val pluginName:String, + val pluginAuthor:String, + val pluginBasePath: String, + val pluginVersion: String, + val pluginInfo:String, + val depends: List,//插件的依赖 + //internal + var loaded:Boolean = false, + var noCircularDepend :Boolean = true + ) + +{ + + companion object{ + fun readFromContent(content_:String):PluginDescription{ + val content = content_.split("\n") + + var name = "Plugin" + var author = "Unknown" + var basePath = "net.mamoe.mirai.PluginMain" + var info = "Unknown" + var version = "1.0.0" + val depends = mutableListOf(); + + content.forEach{ + val line = it.trim() + val lowercaseLine = line.toLowerCase() + if(it.contains(":")) { + when{ + lowercaseLine.startsWith("name") -> { + name = line.substringAfter(":").trim() + } + lowercaseLine.startsWith("author") -> { + author = line.substringAfter(":").trim() + } + lowercaseLine.startsWith("info") || lowercaseLine.startsWith("information") -> { + info = line.substringAfter(":").trim() + } + lowercaseLine.startsWith("path") || lowercaseLine.startsWith("basepath") -> { + basePath = line.substringAfter(":").trim() + } + lowercaseLine.startsWith("version") || lowercaseLine.startsWith("ver") -> { + version = line.substringAfter(":").trim() + } + } + }else if(line.startsWith("-")){ + depends.add(line.substringAfter("-").trim()) + } + } + return PluginDescription(name,author,basePath,version,info,depends) + } + } +} + + +object PluginManager{ + private val pluginsPath = System.getProperty("user.dir") + "/plugins/".replace("//","/").also { + File(it).mkdirs() + } + + private val logger = DefaultLogger("Plugin Manager") + + //已完成加载的 + private val nameToDescriptionMap: Map = mutableMapOf() + private val pluginBaseToDescriptionMap: Map = mutableMapOf() + + + fun getPluginDataFolder(plugin: PluginBase):File{ + val name = (pluginBaseToDescriptionMap[plugin] ?: error("Plugin not loaded")).pluginName + return File(pluginsPath + name).also { + it.mkdirs() + } + } + + + /** + * 尝试加载全部插件 + */ + fun loadPlugins(){ + val pluginsFound: MutableMap = mutableMapOf() + val pluginsLocation: MutableMap = mutableMapOf() + + File(pluginsPath).listFiles()?.forEach { file -> + if (file != null) { + if (file.extension == "jar") { + val jar = JarFile(file) + val pluginYml = jar.entries().asIterator().asSequence().filter { it.name.toLowerCase().contains("resource/plugin.yml") }.firstOrNull() + if (pluginYml == null) { + logger.info("plugin.yml not found in jar " + jar.name + ", it will not be consider as a Plugin") + } else { + val description = PluginDescription.readFromContent(pluginYml.extra.toString()) + pluginsFound[description.pluginName] = description + pluginsLocation[description.pluginName] = jar + } + } + } + } + + fun checkNoCircularDepends (target:PluginDescription, needDepends: List,existDepends: MutableList){ + + if(!target.noCircularDepend){ + return + } + + if(needDepends.any { existDepends.contains(it) }){ + target.noCircularDepend = false + } + + existDepends.addAll(needDepends) + existDepends.add(target.pluginName) + + needDepends.forEach{ + if(pluginsFound.containsKey(it)){ + checkNoCircularDepends(pluginsFound[it]!!, pluginsFound[it]!!.depends, existDepends) + } + } + } + + + pluginsFound.values.forEach { + checkNoCircularDepends(it,it.depends, mutableListOf()) + } + + //load + + + fun loadPlugin(description: PluginDescription):Boolean{ + if(!description.noCircularDepend){ + return false.also { + logger.error("Failed to load plugin " + description.pluginName + " because it has circular dependency") + } + } + + //load depends first + description.depends.forEach{ + if(!pluginsFound.containsKey(it)){ + return false.also { _ -> + logger.error("Failed to load plugin " + description.pluginName + " because it need " + it + " as dependency") + } + } + val depend = pluginsFound[it]!! + //还没有加载 + if(!depend.loaded) { + if (!loadPlugin(pluginsFound[it]!!)) { + return false.also { _ -> + logger.error("Failed to load plugin " + description.pluginName + " because " + it + " as dependency failed to load") + } + } + } + } + //在这里所有的depends都已经加载了 + + //loadPlugin + + } + + + pluginsFound.values.forEach{ loadPlugin(it) } + } + + + + +} + + +