plugin supporting

This commit is contained in:
jiahua.liu 2020-01-18 16:30:52 +08:00
parent ff74ee3ce6
commit 3a16311569
3 changed files with 200 additions and 0 deletions

View File

@ -16,4 +16,5 @@ public class MiraiConsole {
public void log(Object o){ public void log(Object o){
System.out.println(o); System.out.println(o);
} }
} }

View File

@ -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<String>,//插件的依赖
//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<String>();
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<String, PluginDescription> = mutableMapOf()
private val pluginBaseToDescriptionMap: Map<PluginBase, PluginDescription> = 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<String, PluginDescription> = mutableMapOf()
val pluginsLocation: MutableMap<String, JarFile> = 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<String>,existDepends: MutableList<String>){
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) }
}
}