Skip to content

Commit

Permalink
Improve brigardier command registration
Browse files Browse the repository at this point in the history
  • Loading branch information
jakobkmar committed Aug 23, 2021
1 parent fa71b0c commit 3ab5cbc
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 68 deletions.
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
77 changes: 12 additions & 65 deletions src/main/kotlin/net/axay/kspigot/commands/BrigardierSupport.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,80 +2,27 @@

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
* by using reflection once. Additionally, this class is
* 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
}

/**
* 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)
}
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
}

/**
* 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)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
}

/**
Expand Down

0 comments on commit 3ab5cbc

Please sign in to comment.