🇪🇸 Español (Spanish)
🇪🇸 Español (Spanish)
Appearance
🇪🇸 Español (Spanish)
🇪🇸 Español (Spanish)
Appearance
This page is written for version:
1.21
This page is written for version:
1.21
La creación de comandos le permite a desarrolladores de mods añadir funcionalidad que puede ser usada mediante un comando. Este tutorial te enseñará como registrar comandos y la estructura general de comandos de Brigadier.
INFO
Brigadier es un analizador y despachador de comandos escrito por Mojang para Minecraft. Es una libraría basada en un una estructura de árbol de comandos, donde construyes un árbol de comandos y argumentos. Brigadier es de fuente abierta: https://github.com/Mojang/brigadier
Comand
(Comando) com.mojang.brigadier.Command
es una interfaz funcional, la cual corre un código específico, y tira una excepción de CommandSyntaxException
(Excepción de Syntax de Comando) en algunos casos. Tiene un tipo genérico S
, el cual define el tipo de la fuente de comando. La fuente de comando nos dá el contexto en el que se corrió un comando. En Minecraft, la fuente de comando es típicamente un ServerCommandSource
(Fuente de Comando de Servidor) el cual puede representar un servidor, un bloque de comandos, una conexión remota (RCON), un jugador o una entidad.
El método run(CommandContext<S>)
en Command
tiene un CommandContext<S>
como el único parámetro y retorna un número entero. El contexto del comando contiene la fuente de comando de S
y te permite obtener los argumentos, ver los nodos de comando analizados y ver el valor entrado en este comando.
Al igual que otras interfaces funcionales, puedes usar una expresión Lambda o una referencia de método:
Command<ServerCommandSource> command = context -> {
return 0;
};
El número entero retornado puede ser considerado el resultado del comando. Los valores iguales o menores a 0 típicamente significan que el comando ha fallado y no hará nada. Valores positivos indican que el comando fue exitoso e hizo algo. Brigadier provee una constante para indicar éxito; Command#SINGLE_SUCCESS
(Éxito Único).
ServerCommandSource
? Un ServerCommandSource
nos da contexto específico de implementación adicional cuando el comando es corrido. Esto incluye la habilidad de obtener la entidad que ejecutó el comando, el mundo o el servidor en el que el comando fue ejecutado.
Puedes acceder la fuente del comando desde un contexto de comando llamando getSource()
en la instancia de CommandContext
.
Command<ServerCommandSource> command = context -> {
ServerCommandSource source = context.getSource();
return 0;
};
Los comandos son registrados mediante la clase CommandRegistrationCallback
(Callback de Registración de Comandos) proveída por el Fabric API.
INFO
Para información sobre como registrar callbacks, por favor visita la guía de Eventos.
El evento debería ser registrado en tu inicializador de mod.
El callback tiene tres parámetros:
CommandDispatcher<ServerCommandSource> dispatcher
(Despachador de comandos) - Usado para registrar, analizar y ejecutar comandos. S
es el tipo de la fuente del comando que el despachador usa.CommandRegistryAccess registryAccess
(Acceso de registro de comandos) - Provee una abstracción sobre los registros que pueden ser dados a ciertos métodos de argumentos de comandosCommandManager.RegistrationEnvironment environment
(Ambiente de Registración) - Identifica el tipo de servidor en el que los comandos se están registrando en.En el inicializador de mod, solo registramos un comando simple:
No lines matched.
En el método sendFeedback()
, el primer parámetro es el texto a ser enviado, el cual está en un Supplier<Text>
(Proveedor) para no tener que instanciar nuevos objetos Text
(Texto) cuando no es necesario.
El segundo parámetro determina si deberíamos transmitir el feedback a otros operadores. Generalmente, si el comando solo es para verificar o consultar algo sin afectar realmente el mundo, como verificar el tiempo actual o el puntaje de un jugador, este parametro debería ser false
(falso). Si el comando hace algo, como cambiar el tiempo o modificar el puntaje de alguien, entonces debería ser true
(verdadero).
Si el comando falla, en vez de llamar sendFeedback()
, puedes directamente tirar una excepción y el servidor o cliente lo manejará apropiadamente.
CommandSyntaxException
es generalmente tirada para indicar errores en la sintaxis del comando o sus argumentos. También puedes implementar tus propias excepciones.
Para ejecutar este comando, debes escribir /foo
; aquí importan las mayúsculas y minúsculas.
Si se desea, también puedes asegurarte que un comando solo es registrado bajo ciertas circunstancias específicas, por ejemplo, solo en el ambiente dedicado:
No lines matched.
Digamos que tienes un comando y que quieres que solo los operadores puedan ejecutarlo. Aquí entra el método requires()
. El método requieres()
tiene un argumento de un Predicate<S>
(Condición) el cual proveerá un ServerCommandSource
el cual será probado con la condición data para determinar si el CommandSource
puede ejecutar el comando.
No lines matched.
Este comando solo se ejecutará si la fuente del comando es un operador nivel 2 como mínimo, incluyendo bloques de comandos. De lo contrario, el comando no es registrado.
Esto tiene el efecto secundario de que el comando no se muestra con la auto completación con la tecla Tab a personas que no tienen operador nivel 2. Esta también es la razón por la cual no puedes autocompletar comandos cuando no tienes los trucos activados.
Para agregar un sub comando, registras el primer nodo de comando normalmente. Para tener un sub comando, tienes que adjuntar el siguiente literal de nodo de comando al nodo existente.
No lines matched.
Similarmente a los argumentos, los nodos de sub comandos pueden ser opcionales. En el siguiente caso ambos comandos /subtater
y /subtater subcommand
serán válidos.
No lines matched.
El Fabric API tiene una clase ClientCommandManager
en el paquete de net.fabricmc.fabric.api.client.command.v2
que puede ser usado para registrar comandos en el lado del cliente. Este código solo debe existir en el lado del cliente.
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {
dispatcher.register(ClientCommandManager.literal("clienttater").executes(context -> {
context.getSource().sendFeedback(Text.literal("Called /clienttater with no arguments."));
return 1;
}));
});
Redireccionadores de comandos - también llamados aliases - son una manea de redireccionar la funcionalidad de un comando a otro. Esto es útil cuando quieres cambiar el nombre de un comando, pero todavía quieres mantener soporte para el nombre viejo.
No lines matched.
Atrapa o tira una excepción CommandSyntaxException
- CommandSyntaxException
no es una RuntimeException
(Excepción en Tiempo de Ejecución). Si la tiras, debe ser en métodos que tiren un CommandSyntaxException
en el signature (firma) del método, o ser atrapadas. Brigadier manejará las excepciones checked (comprobadas) y mandará el mensaje de error correspondiente en el juego para ti.
Problemas con genéricos - Puede que tengas problemas con genéricos de vez en cuando. Si estás registrando comandos de servidor (el cual es mayormente el caso), asegúrate de usar CommandManager.literal
o CommandManager.argument
en vez de LiteralArgumentBuilder.literal
o RequiredArgumentBuilder.argument
.
Verifica el método de sendFeedback()
- Puede que te hayas olvidado de dar el valor booleano al segundo argumento. También recurda que, a partir de Minecraft 1.20, el primer parámetro es un Supplier<Text>
en vez de Text
.
Un comando debería retornar un número entero - Cuando registres comandos, el método executes()
acepta un objeto Command
, el cual usualmente es una expresión Lambda. El Lambda debería retornar un número entero, en lugar de otros tipos de valores.
WARNING
You can do this, but it is not recommended. You would get the CommandManager
from the server and add anything commands you wish to its CommandDispatcher
.
Después de eso, debes enviar el árbol de comandos a cada jugador de nuevo usando CommandManager.sendCommandTree(ServerPlayerEntity)
.
Esto es necesario porque el cliente almacena en un caché el árbol de comandos que recibe durante inicio de sesión (o cuando paquetes de operador son enviados) para mensajes de error con completaciones locales.
WARNING
You can also do this, however, it is much less stable than registering commands at runtime and could cause unwanted side effects.
Para mantener las cosas simples, vas a tener que usar reflexión en Brigadier para remover nodos. Después de esto, necesitas enviar el árbol de comandos de nuevo a cada jugador usando sendCommandTree(ServerPlayerEntity)
.
Si no envias el árbol de comandos actualizado, el cliente pensará que un comando existe, aunque el servidor no podrá ejecutarlo.