From d78d477e1429902fb7fbe2806262d5b5ae9cbbf7 Mon Sep 17 00:00:00 2001 From: "jiahua.liu" Date: Sat, 21 Mar 2020 01:59:26 +0800 Subject: [PATCH] solve #12 --- .../net/mamoe/mirai/console/MiraiConsole.kt | 139 ++++++++-------- .../mirai/console/command/CommandManager.kt | 148 ++++++++++++++---- .../mirai/console/command/CommandProcessor.kt | 14 -- 3 files changed, 189 insertions(+), 112 deletions(-) delete mode 100644 mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandProcessor.kt diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt index 50d13701b..be4cc194f 100644 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt @@ -10,12 +10,9 @@ package net.mamoe.mirai.console import kotlinx.coroutines.* -import kotlinx.coroutines.channels.Channel import net.mamoe.mirai.Bot -import net.mamoe.mirai.console.MiraiConsole.CommandProcessor.processNextCommandLine import net.mamoe.mirai.console.command.CommandManager import net.mamoe.mirai.console.command.CommandSender -import net.mamoe.mirai.console.command.ConsoleCommandSender import net.mamoe.mirai.console.command.DefaultCommands import net.mamoe.mirai.console.plugins.PluginManager import net.mamoe.mirai.console.utils.MiraiConsoleUI @@ -42,7 +39,7 @@ object MiraiConsole { /** * 与前端交互所使用的Logger */ - var logger = MiraiConsoleLogger + internal var logger = MiraiConsoleLogger /** * Console运行路径 @@ -55,12 +52,12 @@ object MiraiConsole { lateinit var frontEnd: MiraiConsoleUI - /** - * 启动Console - */ var start = false + /** + * 启动Console + */ fun start( frontEnd: MiraiConsoleUI, coreVersion: String = "0.0.0", @@ -91,7 +88,7 @@ object MiraiConsole { /* 依次启用功能 */ DefaultCommands() PluginManager.loadPlugins() - CommandProcessor.start() + CommandManager.start() /* 通知启动完成 */ logger("Mirai-console 启动完成") @@ -99,6 +96,9 @@ object MiraiConsole { logger("\"/login qq号 qq密码 \" 来登录一个BOT") } + /** + * 关闭Console + */ fun stop() { PluginManager.disableAllPlugins() try { @@ -110,85 +110,82 @@ object MiraiConsole { } } - - object CommandProcessor : Job by { - GlobalScope.launch(start = CoroutineStart.LAZY) { - processNextCommandLine() - } - }() { - - internal class FullCommand( - val sender: CommandSender, - val commandStr: String + @Deprecated("Please use CommandManager directly, this will be removed in later release") + object CommandProcessor{ + @Deprecated("Please use CommandManager directly, this will be removed in later release", ReplaceWith( + "CommandManager.runConsoleCommand(command)", + "net.mamoe.mirai.console.command.CommandManager" + ) ) - - private val commandChannel: Channel = Channel() - suspend fun runConsoleCommand(command: String) { - commandChannel.send( - FullCommand(ConsoleCommandSender, command) - ) + CommandManager.runConsoleCommand(command) } - + @Deprecated("Please use CommandManager directly, this will be removed in later release", ReplaceWith( + "CommandManager.runCommand(sender, command)", + "net.mamoe.mirai.console.command.CommandManager" + ) + ) suspend fun runCommand(sender: CommandSender, command: String) { - commandChannel.send( - FullCommand(sender, command) - ) + CommandManager.runCommand(sender,command) } - fun runConsoleCommandBlocking(command: String) = runBlocking { runConsoleCommand(command) } + @Deprecated("Please use CommandManager directly, this will be removed in later release", ReplaceWith( + "CommandManager.runConsoleCommand(command)", + "net.mamoe.mirai.console.command.CommandManager" + ) + ) + fun runConsoleCommandBlocking(command: String) = runBlocking { runConsoleCommand(command)} + @Suppress("unused") + @Deprecated("Please use CommandManager directly, this will be removed in later release", ReplaceWith( + "CommandManager.runCommand(sender, command)", + "net.mamoe.mirai.console.command.CommandManager" + ) + ) fun runCommandBlocking(sender: CommandSender, command: String) = runBlocking { runCommand(sender, command) } + } +} - private suspend fun processNextCommandLine() { - for (command in commandChannel) { - var commandStr = command.commandStr - if (!commandStr.startsWith("/")) { - commandStr = "/$commandStr" - } - if (!CommandManager.runCommand(command.sender, commandStr)) { - command.sender.sendMessage("未知指令 $commandStr") - } - } +/** + * Mirai Console的logger + * 它用于适配不同的Console前段 + */ +internal object MiraiConsoleLogger { + operator fun invoke(any: Any? = null) { + invoke( + "[Mirai ${MiraiConsole.version} ${MiraiConsole.build}]", + 0L, + any + ) + } + + operator fun invoke(priority: LogPriority, identityStr: String, identity: Long, any: Any? = null) { + if (any != null) { + MiraiConsole.frontEnd.pushLog(priority, identityStr, identity, "$any") } } - object MiraiConsoleLogger { - operator fun invoke(any: Any? = null) { - invoke( - "[Mirai $version $build]", - 0L, - any - ) - } - - operator fun invoke(priority: LogPriority, identityStr: String, identity: Long, any: Any? = null) { - if (any != null) { - frontEnd.pushLog(priority, identityStr, identity, "$any") - } - } - - operator fun invoke(priority: LogPriority, identityStr: String, identity: Long, e: Exception? = null) { - if (e != null) { - frontEnd.pushLog(priority, identityStr, identity, "${e.stackTrace}") - } - } - - // 设置默认的pushLog输出为 INFO 类型 - operator fun invoke(identityStr: String, identity: Long, any: Any? = null) { - if (any != null) { - frontEnd.pushLog(LogPriority.INFO, identityStr, identity, "$any") - } - } - - operator fun invoke(identityStr: String, identity: Long, e: Exception? = null) { - if (e != null) { - frontEnd.pushLog(LogPriority.INFO, identityStr, identity, "${e.stackTrace}") - } + operator fun invoke(priority: LogPriority, identityStr: String, identity: Long, e: Exception? = null) { + if (e != null) { + MiraiConsole.frontEnd.pushLog(priority, identityStr, identity, "${e.stackTrace}") } } + // 设置默认的pushLog输出为 INFO 类型 + operator fun invoke(identityStr: String, identity: Long, any: Any? = null) { + if (any != null) { + MiraiConsole.frontEnd.pushLog(LogPriority.INFO, identityStr, identity, "$any") + } + } + + operator fun invoke(identityStr: String, identity: Long, e: Exception? = null) { + if (e != null) { + MiraiConsole.frontEnd.pushLog(LogPriority.INFO, identityStr, identity, "${e.stackTrace}") + } + + + } } diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt index 437489ee2..3bff9bbd3 100644 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt @@ -11,9 +11,19 @@ package net.mamoe.mirai.console.command +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.Channel +import net.mamoe.mirai.console.command.CommandManager.processCommandQueue +import net.mamoe.mirai.console.plugins.PluginBase import net.mamoe.mirai.console.plugins.PluginManager +import java.util.concurrent.Executors -object CommandManager { + +object CommandManager : Job by { + GlobalScope.launch(start = CoroutineStart.LAZY) { + processCommandQueue() + } +}() { private val registeredCommand: MutableMap = mutableMapOf() val commands: Collection get() = registeredCommand.values @@ -33,38 +43,122 @@ object CommandManager { fun unregister(command: Command) { (command.alias.asSequence() + command.name).forEach { registeredCommand.remove(it) - } // label compilation failed + } } fun unregister(commandName: String): Boolean { return registeredCommand.remove(commandName) != null } - /* - * Index: MiraiConsole - */ - internal suspend fun runCommand(sender: CommandSender, fullCommand: String): Boolean { - val blocks = fullCommand.split(" ") - val commandHead = blocks[0].replace("/", "") - if (!registeredCommand.containsKey(commandHead)) { - return false + + /** + * 指令是单线程运行的 + */ + private val commandDispatcher = Executors.newFixedThreadPool(1).asCoroutineDispatcher() + + /** + * 执行一个指令, 但是如果你想模拟一个指令的执行 + * 请向下看 + * + * 返回一个指令是否执行成功 + */ + internal suspend fun processCommand(sender: CommandSender, fullCommand: String):Boolean { + return withContext(commandDispatcher) { + _processCommand(sender, fullCommand) } - val args = blocks.drop(1) - registeredCommand[commandHead]?.run { - try { - if (onCommand(sender, blocks.drop(1))) { - PluginManager.onCommand(this, sender, args) - } else { - sender.sendMessage(this.usage) - } - } catch (e: Exception) { - sender.sendMessage("在运行指令时出现了未知错误") - e.printStackTrace() - } finally { - (sender as CommandSenderImpl).flushMessage() - } - } - return true } -} \ No newline at end of file + private suspend fun _processCommand(sender: CommandSender, fullCommand: String): Boolean { + val blocks = fullCommand.split(" ") + val commandHead = blocks[0].replace("/", "") + val args = blocks.drop(1) + return registeredCommand[commandHead]?.run { + try { + return onCommand(sender, blocks.drop(1)).also { + if (it) { + PluginManager.onCommand(this, sender, args) + } else { + sender.sendMessage(this.usage) + } + } + }catch (e: Exception){ + sender.sendMessage("在运行指令时出现了未知错误") + e.printStackTrace() + false + }finally { + (sender as CommandSenderImpl).flushMessage() + } + }?: throw UnknownCommandException(commandHead) + } + + + internal class FullCommand( + val sender: CommandSender, + val commandStr: String + ) + + private val commandChannel: Channel = Channel(Channel.UNLIMITED) + + private tailrec suspend fun processCommandQueue() { + val command = commandChannel.receive() + try { + processCommand(command.sender, command.commandStr) + }catch (e:UnknownCommandException){ + command.sender.sendMessage("未知指令 " + command.commandStr) + }catch (e:Throwable){//should never happen + e.printStackTrace() + } + processCommandQueue() + } + + /** + * runCommand()是最基础的执行指令的方式 + * 指令将会被加入队列,依次执行 + * 方法由0.27.0的阻塞模式改为不阻塞(鉴于commandChannel大小无限) + */ + fun runCommand(sender: CommandSender, command: String) { + runBlocking {//it wont be blocking + commandChannel.send( + FullCommand(sender, command) + ) + } + } + + @Suppress("unused") + fun runConsoleCommand(command: String) = runCommand(ConsoleCommandSender,command) + + /** + * runCommandAnsyc()执行一个指令并返回deferred + * 为插队执行 + */ + fun runCommandAsync(pluginBase: PluginBase, sender: CommandSender, command: String):Deferred{ + return pluginBase.async{ + processCommand(sender,command) + } + } + + fun runConsoleCommandAsync(pluginBase: PluginBase, command: String):Deferred = runCommandAsync(pluginBase,ConsoleCommandSender,command) + + /** + * dispatchCommand()执行一个指令并等到完成 + * 为插队执行 + */ + suspend fun dispatchCommand(sender: CommandSender,command: String):Boolean{ + return processCommand(sender,command) + } + + suspend fun dispatchConsoleCommand(command: String):Boolean = dispatchCommand(ConsoleCommandSender,command) + + + fun dispatchCommandBlocking(sender: CommandSender,command: String):Boolean = runBlocking { dispatchCommand(sender, command) } + + fun dispatchConsoleCommandBlocking(command: String):Boolean = runBlocking { dispatchConsoleCommandBlocking(command) } +} + +fun PluginBase.runCommandAsnyc(sender: CommandSender, command: String):Deferred = CommandManager.runCommandAsync(this,sender,command) + +fun PluginBase.runConsoleCommandAsync(command: String):Deferred = CommandManager.runConsoleCommandAsync(this,command) + + + +class UnknownCommandException(command: String):Exception("unknown command \"$command\"") \ No newline at end of file diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandProcessor.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandProcessor.kt deleted file mode 100644 index b692b2e13..000000000 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandProcessor.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.mamoe.mirai.console.command - -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.asCoroutineDispatcher -import java.util.concurrent.Executors - -object CommandProcessor { - val commandDispatcher = Executors.newFixedThreadPool(1).asCoroutineDispatcher() - - suspend fun runCommand(){ - Dispatchers.IO - } -} -