Commit fc99e972 authored by Him188's avatar Him188

update

parent 298d0139
...@@ -3,7 +3,8 @@ apply plugin: "java" ...@@ -3,7 +3,8 @@ apply plugin: "java"
dependencies { dependencies {
api project(':mirai-core') api project(':mirai-core')
runtimeOnly files(':mirai-core-timpc') api project(':mirai-core-timpc')
runtimeOnly files('../mirai-core-timpc/build/classes/kotlin/jvm/main')
runtimeOnly files('../mirai-core/build/classes/kotlin/jvm/main') runtimeOnly files('../mirai-core/build/classes/kotlin/jvm/main')
// classpath is not set correctly by IDE // classpath is not set correctly by IDE
} }
...@@ -18,34 +18,27 @@ fun main() { ...@@ -18,34 +18,27 @@ fun main() {
println("\"login qqnumber qqpassword \" to login a bot") println("\"login qqnumber qqpassword \" to login a bot")
println("\"login qq号 qq密码 \" 来登陆一个BOT") println("\"login qq号 qq密码 \" 来登陆一个BOT")
thread { processNextCommandLine() }
thread { PluginManager.loadPlugins()
loop@ while (true) { }
var command = readLine()
if (command != null) { tailrec fun processNextCommandLine() {
var commandArgs = command.split(" ") val commandArgs = readLine()?.split(" ") ?: return
when (commandArgs[0]) { when (commandArgs[0]) {
"login" -> { "login" -> {
if (commandArgs.size < 3) { if (commandArgs.size < 3) {
println("\"login qqnumber qqpassword \" to login a bot") println("\"login qqnumber qqpassword \" to login a bot")
println("\"login qq号 qq密码 \" 来登陆一个BOT") println("\"login qq号 qq密码 \" 来登录一个BOT")
continue@loop return processNextCommandLine()
} }
val qqNumber = commandArgs[1].toLong() val qqNumber = commandArgs[1].toLong()
val qqPassword = commandArgs[2] val qqPassword = commandArgs[2]
println("login...") println("login...")
GlobalScope.launch { GlobalScope.launch {
Bot(qqNumber, qqPassword) Bot(qqNumber, qqPassword)
}
}
}
} }
} }
} }
return processNextCommandLine()
PluginManager.loadPlugins()
} }
package net.mamoe.mirai.plugin package net.mamoe.mirai.plugin
import net.mamoe.mirai.utils.DefaultLogger import net.mamoe.mirai.utils.DefaultLogger
import java.io.BufferedReader import net.mamoe.mirai.utils.io.encodeToString
import java.io.File import java.io.File
import java.io.InputStream
import java.io.InputStreamReader
import java.net.JarURLConnection
import java.net.URL import java.net.URL
import java.util.jar.JarFile import java.util.jar.JarFile
abstract class PluginBase constructor() { abstract class PluginBase constructor() {
val dataFolder by lazy {
File(PluginManager.pluginsPath + pluginDescription.name).also { it.mkdir() }
}
open fun onLoad() { open fun onLoad() {
...@@ -24,38 +24,27 @@ abstract class PluginBase constructor() { ...@@ -24,38 +24,27 @@ abstract class PluginBase constructor() {
} }
fun getPluginManager(): PluginManager {
return PluginManager
}
private lateinit var pluginDescription: PluginDescription private lateinit var pluginDescription: PluginDescription
internal fun init(pluginDescription: PluginDescription) { internal fun init(pluginDescription: PluginDescription) {
this.pluginDescription = pluginDescription this.pluginDescription = pluginDescription
this.onLoad() this.onLoad()
} }
fun getDataFolder(): File {
return File(PluginManager.pluginsPath + pluginDescription.pluginName).also {
it.mkdirs()
}
}
} }
class PluginDescription( class PluginDescription(
val pluginName: String, val name: String,
val pluginAuthor: String, val author: String,
val pluginBasePath: String, val basePath: String,
val pluginVersion: String, val version: String,
val pluginInfo: String, val info: String,
val depends: List<String>,//插件的依赖 val depends: List<String>,//插件的依赖
internal var loaded: Boolean = false, internal var loaded: Boolean = false,
internal var noCircularDepend: Boolean = true internal var noCircularDepend: Boolean = true
) { ) {
override fun toString(): String { override fun toString(): String {
return "name: $pluginName\nauthor: $pluginAuthor\npath: $pluginBasePath\nver: $pluginVersion\ninfo: $pluginInfo\ndepends: $depends" return "name: $name\nauthor: $author\npath: $basePath\nver: $version\ninfo: $info\ndepends: $depends"
} }
companion object { companion object {
...@@ -69,11 +58,11 @@ class PluginDescription( ...@@ -69,11 +58,11 @@ class PluginDescription(
var version = "1.0.0" var version = "1.0.0"
val depends = mutableListOf<String>(); val depends = mutableListOf<String>();
content.forEach{ content.forEach {
val line = it.trim() val line = it.trim()
val lowercaseLine = line.toLowerCase() val lowercaseLine = line.toLowerCase()
if(it.contains(":")) { if (it.contains(":")) {
when{ when {
lowercaseLine.startsWith("name") -> { lowercaseLine.startsWith("name") -> {
name = line.substringAfter(":").trim() name = line.substringAfter(":").trim()
} }
...@@ -83,26 +72,26 @@ class PluginDescription( ...@@ -83,26 +72,26 @@ class PluginDescription(
lowercaseLine.startsWith("info") || lowercaseLine.startsWith("information") -> { lowercaseLine.startsWith("info") || lowercaseLine.startsWith("information") -> {
info = line.substringAfter(":").trim() info = line.substringAfter(":").trim()
} }
lowercaseLine.startsWith("main") || lowercaseLine.startsWith("path") || lowercaseLine.startsWith( lowercaseLine.startsWith("main") ||
"basepath" lowercaseLine.startsWith("path") ||
) -> { lowercaseLine.startsWith("basepath") -> {
basePath = line.substringAfter(":").trim() basePath = line.substringAfter(":").trim()
} }
lowercaseLine.startsWith("version") || lowercaseLine.startsWith("ver") -> { lowercaseLine.startsWith("version") || lowercaseLine.startsWith("ver") -> {
version = line.substringAfter(":").trim() version = line.substringAfter(":").trim()
} }
} }
}else if(line.startsWith("-")){ } else if (line.startsWith("-")) {
depends.add(line.substringAfter("-").trim()) depends.add(line.substringAfter("-").trim())
} }
} }
return PluginDescription(name,author,basePath,version,info,depends) return PluginDescription(name, author, basePath, version, info, depends)
} }
} }
} }
object PluginManager{ object PluginManager {
internal val pluginsPath = System.getProperty("user.dir") + "/plugins/".replace("//", "/").also { internal val pluginsPath = System.getProperty("user.dir") + "/plugins/".replace("//", "/").also {
File(it).mkdirs() File(it).mkdirs()
} }
...@@ -113,49 +102,37 @@ object PluginManager{ ...@@ -113,49 +102,37 @@ object PluginManager{
private val nameToPluginBaseMap: MutableMap<String, PluginBase> = mutableMapOf() private val nameToPluginBaseMap: MutableMap<String, PluginBase> = mutableMapOf()
/** /**
* 尝试加载全部插件 * 尝试加载全部插件
*/ */
fun loadPlugins(){ fun loadPlugins() {
val pluginsFound: MutableMap<String, PluginDescription> = mutableMapOf() val pluginsFound: MutableMap<String, PluginDescription> = mutableMapOf()
val pluginsLocation: MutableMap<String, JarFile> = mutableMapOf() val pluginsLocation: MutableMap<String, JarFile> = mutableMapOf()
File(pluginsPath).listFiles()?.forEach { file -> File(pluginsPath).listFiles()?.forEach { file ->
if (file != null) { if (file != null && file.extension == "jar") {
if (file.extension == "jar") { val jar = JarFile(file)
val jar = JarFile(file) val pluginYml =
val pluginYml = jar.entries().asSequence().filter { it.name.toLowerCase().contains("plugin.yml") }.firstOrNull()
jar.entries().asSequence().filter { it.name.toLowerCase().contains("plugin.yml") }.firstOrNull() if (pluginYml == null) {
if (pluginYml == null) { logger.info("plugin.yml not found in jar " + jar.name + ", it will not be consider as a Plugin")
logger.info("plugin.yml not found in jar " + jar.name + ", it will not be consider as a Plugin") } else {
} else { val description =
val url = URL("jar:file:" + file.absoluteFile + "!/" + pluginYml.name) PluginDescription.readFromContent(URL("jar:file:" + file.absoluteFile + "!/" + pluginYml.name).openConnection().inputStream.readAllBytes().encodeToString())
val jarConnection: JarURLConnection = url println(description)
.openConnection() as JarURLConnection pluginsFound[description.name] = description
val inputStream: InputStream = jarConnection.getInputStream() pluginsLocation[description.name] = jar
val br = BufferedReader(InputStreamReader(inputStream, "UTF-8"))
var con: String?
val sb = StringBuffer()
while (br.readLine().also { con = it } != null) {
sb.append(con).append("\n")
}
val description = PluginDescription.readFromContent(sb.toString())
println(description)
pluginsFound[description.pluginName] = description
pluginsLocation[description.pluginName] = jar
}
} }
} }
} }
fun checkNoCircularDepends (target:PluginDescription, needDepends: List<String>,existDepends: MutableList<String>) { fun checkNoCircularDepends(target: PluginDescription, needDepends: List<String>, existDepends: MutableList<String>) {
if (!target.noCircularDepend) { if (!target.noCircularDepend) {
return return
} }
existDepends.add(target.pluginName) existDepends.add(target.name)
if (needDepends.any { existDepends.contains(it) }) { if (needDepends.any { existDepends.contains(it) }) {
target.noCircularDepend = false target.noCircularDepend = false
...@@ -172,65 +149,58 @@ object PluginManager{ ...@@ -172,65 +149,58 @@ object PluginManager{
pluginsFound.values.forEach { pluginsFound.values.forEach {
checkNoCircularDepends(it,it.depends, mutableListOf()) checkNoCircularDepends(it, it.depends, mutableListOf())
} }
//load //load
fun loadPlugin(description: PluginDescription):Boolean{ fun loadPlugin(description: PluginDescription): Boolean {
if (!description.noCircularDepend) { if (!description.noCircularDepend) {
return false.also { logger.error("Failed to load plugin " + description.name + " because it has circular dependency")
logger.error("Failed to load plugin " + description.pluginName + " because it has circular dependency") return false
}
} }
//load depends first //load depends first
description.depends.forEach { dependent -> description.depends.forEach { dependentName ->
if (!pluginsFound.containsKey(dependent)) { val dependent = pluginsFound[dependentName]
return false.also { _ -> if (dependent == null) {
logger.error("Failed to load plugin " + description.pluginName + " because it need " + dependent + " as dependency") logger.error("Failed to load plugin " + description.name + " because it need " + dependentName + " as dependency")
} return false
} }
val depend = pluginsFound[dependent]!!
//还没有加载 //还没有加载
if (!depend.loaded) { if (!dependent.loaded && !loadPlugin(dependent)) {
if (!loadPlugin(pluginsFound[dependent]!!)) { logger.error("Failed to load plugin " + description.name + " because " + dependentName + " as dependency failed to load")
return false.also { _ -> return false
logger.error("Failed to load plugin " + description.pluginName + " because " + dependent + " as dependency failed to load")
}
}
} }
} }
//在这里所有的depends都已经加载了 //在这里所有的depends都已经加载了
//real load //real load
logger.info("loading plugin " + description.pluginName) logger.info("loading plugin " + description.name)
try { try {
this.javaClass.classLoader.loadClass(description.pluginBasePath) this.javaClass.classLoader.loadClass(description.basePath)
return try { return try {
val subClass = javaClass.asSubclass(PluginBase::class.java) val subClass = javaClass.asSubclass(PluginBase::class.java)
val plugin: PluginBase = subClass.getDeclaredConstructor().newInstance() val plugin: PluginBase = subClass.getDeclaredConstructor().newInstance()
description.loaded = true description.loaded = true
logger.info("successfully loaded plugin " + description.pluginName) logger.info("successfully loaded plugin " + description.name)
logger.info(description.pluginInfo) logger.info(description.info)
nameToPluginBaseMap[description.pluginName] = plugin nameToPluginBaseMap[description.name] = plugin
plugin.init(description) plugin.init(description)
true true
} catch (e: ClassCastException) { } catch (e: ClassCastException) {
false.also { logger.error("failed to load plugin " + description.name + " , Main class does not extends PluginBase ")
logger.error("failed to load plugin " + description.pluginName + " , Main class does not extends PluginBase ") false
}
} }
} catch (e: ClassNotFoundException) { } catch (e: ClassNotFoundException) {
e.printStackTrace() e.printStackTrace()
return false.also { logger.error("failed to load plugin " + description.name + " , Main class not found under " + description.basePath)
logger.error("failed to load plugin " + description.pluginName + " , Main class not found under " + description.pluginBasePath) return false
}
} }
} }
...@@ -240,8 +210,6 @@ object PluginManager{ ...@@ -240,8 +210,6 @@ object PluginManager{
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment