Fix optional argument handling
- That was almost too easy
This commit is contained in:
parent
82d43e5b09
commit
0e39cd38e3
3 changed files with 42 additions and 20 deletions
|
@ -3,9 +3,10 @@ package buttondevteam.lib.chat
|
||||||
import buttondevteam.core.MainPlugin
|
import buttondevteam.core.MainPlugin
|
||||||
import buttondevteam.lib.ChromaUtils
|
import buttondevteam.lib.ChromaUtils
|
||||||
import buttondevteam.lib.chat.commands.*
|
import buttondevteam.lib.chat.commands.*
|
||||||
import buttondevteam.lib.chat.commands.CommandUtils.coreArgument
|
|
||||||
import buttondevteam.lib.chat.commands.CommandUtils.coreCommand
|
import buttondevteam.lib.chat.commands.CommandUtils.coreCommand
|
||||||
import buttondevteam.lib.chat.commands.CommandUtils.coreExecutable
|
import buttondevteam.lib.chat.commands.CommandUtils.coreExecutable
|
||||||
|
import buttondevteam.lib.chat.commands.CommandUtils.subcommandData
|
||||||
|
import buttondevteam.lib.chat.commands.CommandUtils.subcommandDataNoOp
|
||||||
import com.google.common.base.Defaults
|
import com.google.common.base.Defaults
|
||||||
import com.google.common.primitives.Primitives
|
import com.google.common.primitives.Primitives
|
||||||
import com.mojang.brigadier.CommandDispatcher
|
import com.mojang.brigadier.CommandDispatcher
|
||||||
|
@ -22,7 +23,6 @@ import java.lang.reflect.Method
|
||||||
import java.util.function.Function
|
import java.util.function.Function
|
||||||
import java.util.function.Predicate
|
import java.util.function.Predicate
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
import java.util.stream.Collectors
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The method name is the subcommand, use underlines (_) to add further subcommands.
|
* The method name is the subcommand, use underlines (_) to add further subcommands.
|
||||||
|
@ -196,25 +196,26 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
||||||
method
|
method
|
||||||
).executes(this::executeHelpText)
|
).executes(this::executeHelpText)
|
||||||
|
|
||||||
fun getArgNodes(parent: ArgumentBuilder<TP, *>, params: MutableList<CommandArgument>, executable: Boolean) {
|
fun getArgNodes(parent: ArgumentBuilder<TP, *>, params: MutableList<CommandArgument>): Boolean {
|
||||||
// TODO: Implement optional arguments here by making the last non-optional parameter also executable
|
// TODO: Implement optional arguments here by making the last non-optional parameter also executable
|
||||||
val param = params.removeFirst()
|
val param = params.removeFirst()
|
||||||
val argType = getArgumentType(param)
|
val argType = getArgumentType(param)
|
||||||
val arg = CoreArgumentBuilder.argument<TP, _>(param.name, argType, param.optional)
|
val arg = CoreArgumentBuilder.argument<TP, _>(param.name, argType, param.optional)
|
||||||
if (params.isEmpty() || executable) {
|
if (params.isEmpty()) {
|
||||||
arg.executes { context: CommandContext<TP> -> executeCommand(context) }
|
arg.executes { context: CommandContext<TP> -> executeCommand(context) }
|
||||||
} else {
|
} else {
|
||||||
arg.executes(::executeHelpText)
|
arg.executes(::executeHelpText)
|
||||||
}
|
}
|
||||||
if (params.isNotEmpty()) {
|
if (params.isNotEmpty()) {
|
||||||
getArgNodes(arg, params, param.optional)
|
if (getArgNodes(arg, params)) {
|
||||||
|
arg.executes { context: CommandContext<TP> -> executeCommand(context) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
parent.then(arg)
|
parent.then(arg)
|
||||||
|
return param.optional
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.isNotEmpty()) {
|
if (params.isEmpty() || getArgNodes(node, params.toMutableList())) {
|
||||||
getArgNodes(node, params.toMutableList(), false)
|
|
||||||
} else {
|
|
||||||
node.executes(::executeCommand)
|
node.executes(::executeCommand)
|
||||||
}
|
}
|
||||||
return node.build().coreExecutable() ?: throw IllegalStateException("Command node should be executable but isn't: $fullPath")
|
return node.build().coreExecutable() ?: throw IllegalStateException("Command node should be executable but isn't: $fullPath")
|
||||||
|
@ -276,8 +277,10 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
||||||
numAnn.upperLimit
|
numAnn.upperLimit
|
||||||
),
|
),
|
||||||
param.isAnnotationPresent(OptionalArg::class.java),
|
param.isAnnotationPresent(OptionalArg::class.java),
|
||||||
name, param.annotations.filterNot { it is OptionalArg || it is NumberArg || it is TextArg }.toTypedArray())
|
name, param.annotations.filterNot { it is OptionalArg || it is NumberArg || it is TextArg }.toTypedArray()
|
||||||
}, parameters[0].type)
|
)
|
||||||
|
}, parameters[0].type
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -294,7 +297,8 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
||||||
else if (ptype == String::class.java) StringArgumentType.word()
|
else if (ptype == String::class.java) StringArgumentType.word()
|
||||||
else if (ptype == Int::class.javaPrimitiveType || ptype == Int::class.java
|
else if (ptype == Int::class.javaPrimitiveType || ptype == Int::class.java
|
||||||
|| ptype == Byte::class.javaPrimitiveType || ptype == Byte::class.java
|
|| ptype == Byte::class.javaPrimitiveType || ptype == Byte::class.java
|
||||||
|| ptype == Short::class.javaPrimitiveType || ptype == Short::class.java)
|
|| ptype == Short::class.javaPrimitiveType || ptype == Short::class.java
|
||||||
|
)
|
||||||
IntegerArgumentType.integer(lowerLimit.toInt(), upperLimit.toInt())
|
IntegerArgumentType.integer(lowerLimit.toInt(), upperLimit.toInt())
|
||||||
else if (ptype == Long::class.javaPrimitiveType || ptype == Long::class.java)
|
else if (ptype == Long::class.javaPrimitiveType || ptype == Long::class.java)
|
||||||
LongArgumentType.longArg(lowerLimit.toLong(), upperLimit.toLong())
|
LongArgumentType.longArg(lowerLimit.toLong(), upperLimit.toLong())
|
||||||
|
@ -315,10 +319,7 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
||||||
* @return Vanilla command success level (0)
|
* @return Vanilla command success level (0)
|
||||||
*/
|
*/
|
||||||
private fun executeHelpText(context: CommandContext<TP>): Int {
|
private fun executeHelpText(context: CommandContext<TP>): Int {
|
||||||
println("""
|
context.source.sendMessage(context.nodes.lastOrNull()?.node?.subcommandDataNoOp()?.getHelpText(context.source))
|
||||||
Nodes:
|
|
||||||
${context.nodes.stream().map { node -> node.node.name + "@" + node.range }.collect(Collectors.joining("\n"))}
|
|
||||||
""".trimIndent())
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,11 +330,7 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
||||||
* @return Vanilla command success level (0)
|
* @return Vanilla command success level (0)
|
||||||
*/
|
*/
|
||||||
protected open fun executeCommand(context: CommandContext<TP>): Int {
|
protected open fun executeCommand(context: CommandContext<TP>): Int {
|
||||||
@Suppress("UNCHECKED_CAST")
|
val sd = context.nodes.lastOrNull()?.node?.subcommandData<_, TC>() ?: throw IllegalStateException("Could not find suitable command node for command ${context.input}")
|
||||||
val sd = context.nodes.lastOrNull()?.node?.let {
|
|
||||||
it.coreArgument()?.commandData as SubcommandData<TC, TP>?
|
|
||||||
?: it.coreCommand<_, SubcommandData<TC, TP>>()?.data
|
|
||||||
} ?: throw IllegalStateException("Could not find suitable command node for command ${context.input}")
|
|
||||||
val sender = context.source
|
val sender = context.source
|
||||||
|
|
||||||
if (!sd.hasPermission(sender)) {
|
if (!sd.hasPermission(sender)) {
|
||||||
|
|
|
@ -70,4 +70,14 @@ object CommandUtils {
|
||||||
fun <TP : Command2Sender> CommandNode<TP>.isExecutable(): Boolean {
|
fun <TP : Command2Sender> CommandNode<TP>.isExecutable(): Boolean {
|
||||||
return coreCommand<TP, NoOpSubcommandData>()?.data is SubcommandData<*, *>
|
return coreCommand<TP, NoOpSubcommandData>()?.data is SubcommandData<*, *>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
fun <TP : Command2Sender, TC : ICommand2<TP>> CommandNode<TP>.subcommandData(): SubcommandData<TC, TP>? {
|
||||||
|
return coreArgument()?.commandData as SubcommandData<TC, TP>?
|
||||||
|
?: coreCommand<_, SubcommandData<TC, TP>>()?.data
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <TP : Command2Sender> CommandNode<TP>.subcommandDataNoOp(): NoOpSubcommandData? {
|
||||||
|
return subcommandData() ?: coreCommand<_, NoOpSubcommandData>()?.data
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -86,6 +86,11 @@ class Command2MCTest {
|
||||||
runFailingCommand(sender, "/erroringtest")
|
runFailingCommand(sender, "/erroringtest")
|
||||||
runCommand(sender, "/multiargtest hmm mhm", MultiArgTestCommand, "hmmmhm")
|
runCommand(sender, "/multiargtest hmm mhm", MultiArgTestCommand, "hmmmhm")
|
||||||
runCommand(sender, "/multiargtest test2 true 19", MultiArgTestCommand, "true 19")
|
runCommand(sender, "/multiargtest test2 true 19", MultiArgTestCommand, "true 19")
|
||||||
|
runCommand(sender, "/multiargtest testoptional", MultiArgTestCommand, "false")
|
||||||
|
runCommand(sender, "/multiargtest testoptional true", MultiArgTestCommand, "true")
|
||||||
|
runCommand(sender, "/multiargtest testoptionalmulti true teszt", MultiArgTestCommand, "true teszt")
|
||||||
|
runCommand(sender, "/multiargtest testoptionalmulti true", MultiArgTestCommand, "true null")
|
||||||
|
runCommand(sender, "/multiargtest testoptionalmulti", MultiArgTestCommand, "false null")
|
||||||
// TODO: Add expected failed param conversions and missing params
|
// TODO: Add expected failed param conversions and missing params
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,6 +149,16 @@ class Command2MCTest {
|
||||||
fun test2(sender: Command2MCSender, btest: Boolean, ntest: Int) {
|
fun test2(sender: Command2MCSender, btest: Boolean, ntest: Int) {
|
||||||
testCommandReceived = "$btest $ntest"
|
testCommandReceived = "$btest $ntest"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Command2.Subcommand
|
||||||
|
fun testOptional(sender: Command2MCSender, @Command2.OptionalArg opt: Boolean) {
|
||||||
|
testCommandReceived = "$opt"
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command2.Subcommand
|
||||||
|
fun testOptionalMulti(sender: Command2MCSender, @Command2.OptionalArg opt1: Boolean, @Command2.OptionalArg opt2: String?) {
|
||||||
|
testCommandReceived = "$opt1 $opt2"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
Loading…
Reference in a new issue