mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-11 02:50:15 +08:00
CompositeCommand supported
This commit is contained in:
parent
a7eaf788ac
commit
8b56924601
@ -11,17 +11,15 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.command
|
package net.mamoe.mirai.console.command
|
||||||
|
|
||||||
|
import net.mamoe.mirai.console.command.description.*
|
||||||
import net.mamoe.mirai.console.command.description.CommandParam
|
import net.mamoe.mirai.console.command.description.CommandParam
|
||||||
import net.mamoe.mirai.console.command.description.CommandParserContext
|
import net.mamoe.mirai.console.command.hasAnnotation
|
||||||
import net.mamoe.mirai.console.command.description.EmptyCommandParserContext
|
|
||||||
import net.mamoe.mirai.console.command.description.plus
|
|
||||||
import net.mamoe.mirai.console.plugins.MyArg
|
|
||||||
import net.mamoe.mirai.message.data.PlainText
|
import net.mamoe.mirai.message.data.PlainText
|
||||||
import net.mamoe.mirai.message.data.SingleMessage
|
import net.mamoe.mirai.message.data.SingleMessage
|
||||||
|
import java.lang.Exception
|
||||||
import kotlin.reflect.KAnnotatedElement
|
import kotlin.reflect.KAnnotatedElement
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.full.declaredFunctions
|
import kotlin.reflect.full.*
|
||||||
import kotlin.reflect.full.findAnnotation
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指令
|
* 指令
|
||||||
@ -30,6 +28,9 @@ import kotlin.reflect.full.findAnnotation
|
|||||||
*/
|
*/
|
||||||
interface Command {
|
interface Command {
|
||||||
val names: Array<out String>
|
val names: Array<out String>
|
||||||
|
|
||||||
|
fun getPrimaryName():String = names[0]
|
||||||
|
|
||||||
val usage: String
|
val usage: String
|
||||||
val description: String
|
val description: String
|
||||||
val permission: CommandPermission
|
val permission: CommandPermission
|
||||||
@ -57,6 +58,10 @@ abstract class CompositeCommand @JvmOverloads constructor(
|
|||||||
override val prefixOptional: Boolean = false,
|
override val prefixOptional: Boolean = false,
|
||||||
overrideContext: CommandParserContext = EmptyCommandParserContext
|
overrideContext: CommandParserContext = EmptyCommandParserContext
|
||||||
) : Command {
|
) : Command {
|
||||||
|
|
||||||
|
class IllegalParameterException(message:String): Exception(message)
|
||||||
|
|
||||||
|
|
||||||
override val names: Array<out String> =
|
override val names: Array<out String> =
|
||||||
names.map(String::trim).filterNot(String::isEmpty).map(String::toLowerCase).toTypedArray()
|
names.map(String::trim).filterNot(String::isEmpty).map(String::toLowerCase).toTypedArray()
|
||||||
val context: CommandParserContext = CommandParserContext.Builtins + overrideContext
|
val context: CommandParserContext = CommandParserContext.Builtins + overrideContext
|
||||||
@ -70,7 +75,7 @@ abstract class CompositeCommand @JvmOverloads constructor(
|
|||||||
/** 标记一个函数为子指令 */
|
/** 标记一个函数为子指令 */
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
@Target(AnnotationTarget.FUNCTION)
|
@Target(AnnotationTarget.FUNCTION)
|
||||||
annotation class SubCommand(val name: String)
|
annotation class SubCommand(vararg val name: String)
|
||||||
|
|
||||||
/** 指令描述 */
|
/** 指令描述 */
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
@ -102,14 +107,54 @@ abstract class CompositeCommand @JvmOverloads constructor(
|
|||||||
|
|
||||||
internal val subCommands: Array<SubCommandDescriptor> by lazy {
|
internal val subCommands: Array<SubCommandDescriptor> by lazy {
|
||||||
this::class.declaredFunctions.filter { it.hasAnnotation<SubCommand>() }.map { function ->
|
this::class.declaredFunctions.filter { it.hasAnnotation<SubCommand>() }.map { function ->
|
||||||
|
|
||||||
|
val overridePermission = function.findAnnotation<Permission>()//optional
|
||||||
|
|
||||||
|
val subDescription = function.findAnnotation<Description>()?.description
|
||||||
|
if(subDescription == null && owner is PluginCommandOwner){
|
||||||
|
(owner as PluginCommandOwner).plugin.logger.warning("A description for sub commend is recommend for command " + this.getPrimaryName())
|
||||||
|
}
|
||||||
|
|
||||||
|
if((function.returnType.classifier as? KClass<*>)?.isSubclassOf(Boolean::class) != true){
|
||||||
|
throw IllegalParameterException("Return Type of SubCommand must be Boolean")
|
||||||
|
}
|
||||||
|
|
||||||
|
val parameter = function.parameters
|
||||||
|
if (
|
||||||
|
parameter.isEmpty() ||
|
||||||
|
parameter[0].isVararg ||
|
||||||
|
((parameter[0].type.classifier as? KClass<*>)?.isSubclassOf(CommandSender::class)!=true)
|
||||||
|
){
|
||||||
|
throw IllegalParameterException("First parameter (receiver for kotlin) for sub commend " + function.name + " from " + this.getPrimaryName() + " should be <out CommandSender>")
|
||||||
|
}
|
||||||
|
|
||||||
|
val commandName = function.findAnnotation<SubCommand>()!!.name.map {
|
||||||
|
if(!it.isValidSubName()){
|
||||||
|
error("SubName $it is not valid")
|
||||||
|
}
|
||||||
|
it
|
||||||
|
}.toTypedArray()
|
||||||
|
|
||||||
|
//map parameter
|
||||||
|
val parms = parameter.subList(1,parameter.size).map {
|
||||||
|
if(it.isVararg){
|
||||||
|
throw IllegalParameterException("parameter for sub commend " + function.name + " from " + this.getPrimaryName() + " should not be var arg")
|
||||||
|
}
|
||||||
|
if(it.isOptional){
|
||||||
|
throw IllegalParameterException("parameter for sub commend " + function.name + " from " + this.getPrimaryName() + " should not be var optional")
|
||||||
|
}
|
||||||
|
CommandParam(
|
||||||
|
it.findAnnotation<Name>()?.name?:it.name?:"unknown",
|
||||||
|
(parameter[0].type.classifier as? KClass<*>)?: throw IllegalParameterException("unsolved type reference from param " + it.name + " in " + function.name + " from " + this.getPrimaryName()))
|
||||||
|
}.toTypedArray()
|
||||||
|
|
||||||
SubCommandDescriptor(
|
SubCommandDescriptor(
|
||||||
arrayOf(function.name),
|
commandName,
|
||||||
arrayOf(CommandParam("p", MyArg::class)),
|
parms,
|
||||||
"",
|
subDescription?:"unknown",
|
||||||
CommandPermission.Default,
|
overridePermission?.permission?.getInstance() ?: permission,
|
||||||
onCommand = block { sender: CommandSender, args: Array<out Any> ->
|
onCommand = block { sender: CommandSender, args: Array<out Any> ->
|
||||||
println("subname finally gor args: ${args.joinToString()}")
|
function.callSuspend(sender,*args) as Boolean
|
||||||
true
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}.toTypedArray()
|
}.toTypedArray()
|
||||||
@ -234,3 +279,7 @@ internal fun Any.flattenCommandComponents(): ArrayList<Any> {
|
|||||||
|
|
||||||
internal inline fun <reified T : Annotation> KAnnotatedElement.hasAnnotation(): Boolean =
|
internal inline fun <reified T : Annotation> KAnnotatedElement.hasAnnotation(): Boolean =
|
||||||
findAnnotation<T>() != null
|
findAnnotation<T>() != null
|
||||||
|
|
||||||
|
internal inline fun <T:Any> KClass<out T>.getInstance():T {
|
||||||
|
return this.objectInstance ?: this.createInstance()
|
||||||
|
}
|
||||||
|
@ -13,7 +13,7 @@ sealed class CommandOwner
|
|||||||
|
|
||||||
object TestCommandOwner : CommandOwner()
|
object TestCommandOwner : CommandOwner()
|
||||||
|
|
||||||
abstract class PluginCommandOwner(plugin: PluginBase) : CommandOwner()
|
abstract class PluginCommandOwner(val plugin: PluginBase) : CommandOwner()
|
||||||
|
|
||||||
// 由前端实现
|
// 由前端实现
|
||||||
internal abstract class ConsoleCommandOwner : CommandOwner()
|
internal abstract class ConsoleCommandOwner : CommandOwner()
|
||||||
|
Loading…
Reference in New Issue
Block a user