Improve brigardier command registration

This commit is contained in:
Jakob K
2021-08-24 01:53:10 +02:00
parent fa71b0cc0e
commit 3ab5cbc14b
3 changed files with 18 additions and 68 deletions

View File

@@ -30,6 +30,8 @@ dependencies {
api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.2")
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1")
api("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.5.1")
api("me.lucko:commodore:1.10")
}
tasks {

View File

@@ -2,14 +2,9 @@
package net.axay.kspigot.commands
import com.mojang.brigadier.CommandDispatcher
import com.mojang.brigadier.builder.LiteralArgumentBuilder
import net.axay.kspigot.annotations.NMS_1_17
import net.axay.kspigot.annotations.NMS_General
import net.axay.kspigot.extensions.onlinePlayers
import net.axay.kspigot.extensions.server
import net.axay.kspigot.utils.reflectField
import net.minecraft.commands.CommandListenerWrapper
import com.mojang.brigadier.tree.LiteralCommandNode
import me.lucko.commodore.CommodoreProvider
import net.axay.kspigot.main.PluginInstance
/**
* This class provides Brigardier support. It does that
@@ -17,65 +12,17 @@ import net.minecraft.commands.CommandListenerWrapper
* using some obfuscated functions.
*/
object BrigardierSupport {
@PublishedApi
internal val commands = LinkedHashSet<LiteralArgumentBuilder<CommandListenerWrapper>>()
private var executedDefaultRegistration = false
/**
* The command manager is used to hold the command dispatcher,
* and to manage and dispatch the brigardier commands for
* all players on the server.
*/
@Suppress("HasPlatformType") // do not refer non-lazily to the type in this class
@NMS_General
val commandManager by lazy {
(server as org.bukkit.craftbukkit.v1_17_R1.CraftServer).server.commandDispatcher
private val provider = if (CommodoreProvider.isSupported()) CommodoreProvider.getCommodore(PluginInstance) else kotlin.run {
PluginInstance.logger.severe("Could not initialize Brigardier support on the current Minecraft version! (Requested by ${PluginInstance.name})")
null
}
/**
* The command dispatcher is used to register brigardier commands.
*/
@NMS_1_17
val commandDispatcher by lazy {
// g = the command dispatcher
commandManager.reflectField<CommandDispatcher<CommandListenerWrapper>>("g")
}
@NMS_General
internal fun registerAll() {
executedDefaultRegistration = true
if (commands.isNotEmpty()) {
commands.forEach { commandDispatcher.register(it) }
if (onlinePlayers.isNotEmpty())
updateCommandTree()
}
}
@NMS_1_17
fun updateCommandTree() {
onlinePlayers.forEach {
// send the command tree
commandManager.a((it as org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer).handle)
}
}
/**
* Registers this command at the [CommandDispatcher] of the server.
*
* @param sendToPlayers whether the new command tree should be send to
* all players, this is true by default, but you can disable it if you are
* calling this function as the server is starting
*/
@NMS_General
fun LiteralArgumentBuilder<CommandListenerWrapper>.register(sendToPlayers: Boolean = true) {
if (!executedDefaultRegistration)
commands += this
else {
commandDispatcher.register(this)
if (sendToPlayers)
updateCommandTree()
fun register(name: String, brigardierCommand: LiteralCommandNode<*>) {
val command = PluginInstance.getCommand(name)
if (command == null) {
PluginInstance.logger.severe("Could not register command '$name' of plugin ${PluginInstance.name}! Maybe it is missing from the plugin.yml?")
return
}
provider?.register(command, brigardierCommand)
}
}

View File

@@ -6,6 +6,7 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder
import com.mojang.brigadier.builder.RequiredArgumentBuilder
import com.mojang.brigadier.context.CommandContext
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType
import com.mojang.brigadier.tree.LiteralCommandNode
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
@@ -26,10 +27,10 @@ inline fun command(
name: String,
register: Boolean = true,
builder: LiteralArgumentBuilder<CommandListenerWrapper>.() -> Unit,
): LiteralArgumentBuilder<CommandListenerWrapper> =
LiteralArgumentBuilder.literal<CommandListenerWrapper>(name).apply(builder).apply {
): LiteralCommandNode<CommandListenerWrapper> =
LiteralArgumentBuilder.literal<CommandListenerWrapper>(name).apply(builder).build().apply {
if (register)
BrigardierSupport.commands += this
BrigardierSupport.register(name, this)
}
/**