Add brigardier support

This commit is contained in:
Jakob K
2021-06-27 23:41:34 +02:00
parent 979353ac85
commit ecbbfb5a71
2 changed files with 116 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
package net.axay.kspigot.commands
import com.mojang.brigadier.CommandDispatcher
import com.mojang.brigadier.builder.LiteralArgumentBuilder
import net.axay.kspigot.extensions.server
import net.minecraft.commands.CommandListenerWrapper
import org.bukkit.craftbukkit.v1_17_R1.CraftServer
object BrigardierSupport {
@PublishedApi
internal val commands = ArrayList<LiteralArgumentBuilder<CommandListenerWrapper>>()
fun registerAll() {
val commandManager = (server as CraftServer).server.commandDispatcher
val dispatcherField = net.minecraft.commands.CommandDispatcher::class.java.getDeclaredField("g")
dispatcherField.isAccessible = true
@Suppress("UNCHECKED_CAST")
val dispatcher = dispatcherField.get(commandManager) as CommandDispatcher<CommandListenerWrapper>
commands.forEach { dispatcher.register(it) }
}
}

View File

@@ -0,0 +1,93 @@
package net.axay.kspigot.commands
import com.mojang.brigadier.arguments.ArgumentType
import com.mojang.brigadier.builder.ArgumentBuilder
import com.mojang.brigadier.builder.LiteralArgumentBuilder
import com.mojang.brigadier.builder.RequiredArgumentBuilder
import com.mojang.brigadier.context.CommandContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.future.asCompletableFuture
import net.minecraft.commands.CommandListenerWrapper
/**
* Create a new command.
*
* @param name the name of the root command
* @param register if true, the command will automatically be registered
*/
inline fun command(
name: String,
register: Boolean = true,
builder: LiteralArgumentBuilder<CommandListenerWrapper>.() -> Unit
): LiteralArgumentBuilder<CommandListenerWrapper> =
LiteralArgumentBuilder.literal<CommandListenerWrapper>(name).apply(builder).apply {
if (register)
BrigardierSupport.commands += this
}
/**
* Add custom execution logic for this command.
*/
inline fun <S> ArgumentBuilder<S, *>.simpleExecutes(
crossinline executor: (CommandContext<S>) -> Unit
) {
executes wrapped@{
executor.invoke(it)
return@wrapped 1
}
}
/**
* Add a new literal to this command.
*
* @param name the name of the literal
*/
inline fun ArgumentBuilder<CommandListenerWrapper, *>.literal(
name: String,
builder: LiteralArgumentBuilder<CommandListenerWrapper>.() -> Unit
) {
then(command(name, false, builder))
}
/**
* Add an argument.
*
* @param name the name of the argument
* @param type the type of the argument - e.g. IntegerArgumentType.integer() or StringArgumentType.string()
*/
inline fun <T> ArgumentBuilder<CommandListenerWrapper, *>.argument(
name: String,
type: ArgumentType<T>,
builder: RequiredArgumentBuilder<CommandListenerWrapper, T>.() -> Unit
) {
then(RequiredArgumentBuilder.argument<CommandListenerWrapper, T>(name, type).apply(builder))
}
private val argumentCoroutineScope = CoroutineScope(Dispatchers.IO)
/**
* Add custom suspending suggestion logic for an argument.
*/
fun <S> RequiredArgumentBuilder<S, *>.simpleSuggests(
suggestionBuilder: suspend (CommandContext<S>) -> Iterable<Any?>?
) {
suggests { context, builder ->
argumentCoroutineScope.async {
suggestionBuilder.invoke(context)?.forEach {
if (it is Int)
builder.suggest(it)
else
builder.suggest(it.toString())
}
builder.build()
}.asCompletableFuture()
}
}
/**
* Get the value of this argument.
*/
inline fun <reified T> CommandContext<CommandListenerWrapper>.getArgument(name: String): T =
getArgument(name, T::class.java)