🇺🇦 Українська (Ukrainian - Ukraine)
🇺🇦 Українська (Ukrainian - Ukraine)
Зовнішній вигляд
🇺🇦 Українська (Ukrainian - Ukraine)
🇺🇦 Українська (Ukrainian - Ukraine)
Зовнішній вигляд
Ця сторінка написана для версії:
1.21.4
Ця сторінка написана для версії:
1.21.4
Створення команд може дозволити розробнику мода додати функціональні можливості, які можна використовувати за допомогою команди. Ця стаття навчить вас реєструвати команди та загальну командну структуру Brigadier.
INFO
Brigadier is a command parser and dispatcher written by Mojang for Minecraft. It is a tree-based command library where you build a tree of commands and arguments.
Brigadier має відкритий вихідний код: https://github.com/Mojang/brigadier
Command
com.mojang.brigadier.Command
— це функціональний інтерфейс, який запускає певний код і створює CommandSyntaxException
у певних випадках. Він має загальний тип S
, який визначає тип джерела команд. Команда джерело надає певний контекст, у якому була виконана команда. У Minecraft джерелом команди зазвичай є a ServerCommandSource
, який може представляти сервер, командний блок, віддалене з’єднання (RCON), гравця або сутність.
Єдиний метод у Command
, run(CommandContext<S>)
приймає CommandContext<S>
як єдиний параметр і повертає ціле число. Контекст команди містить джерело вашої команди S
і дозволяє отримати аргументи, подивіться на розбір командні вузли та перегляньте вхідні дані, які використовуються в цій команді.
Як і інші функціональні інтерфейси, він зазвичай використовується як лямбда або посилання на метод:
Command<ServerCommandSource> command = context -> {
return 0;
};
Ціле число можна вважати результатом виконання команди. Зазвичай значення, менше або дорівнює нулю, означають, що команда не вдалася і буде нічого не робити. Позитивні значення означають, що команда була успішною та щось зробила. Brigadier надає константу для вказівки успішність; Команда#SINGLE_SUCCESS
.
ServerCommandSource
? ServerCommandSource
надає деякий додатковий специфічний контекст під час виконання команди. Це охоплює в собі можливість отримати сутність, яка виконала команду, світ, у якому була виконана команда, або сервер, на якому була виконана команда.
Ви можете отримати доступ до джерела команд із контексту команди, викликавши getSource()
в екземплярі CommandContext
.
Command<ServerCommandSource> command = context -> {
ServerCommandSource source = context.getSource();
return 0;
};
Команди реєструються в CommandRegistrationCallback
, наданому Fabric API.
INFO
Щоб отримати інформацію про реєстрацію зворотних викликів, перегляньте посібник Події.
Подія має бути зареєстрована у вашому ініціалізаторі мода.
Подія має бути зареєстрована у вашому ініціалізаторі мода.
CommandDispatcher<ServerCommandSource> dispatcher
- використовується для реєстрації, аналізу та виконання команд. S
- це тип джерела команди, яке підтримує диспетчер команд.CommandRegistryAccess registryAccess
- надає абстракцію до реєстрів, які можна передати певній команді методи аргументуCommandManager.RegistrationEnvironment environment
- визначає тип сервера, на якому реєструються команди на.В ініціалізаторі мода ми просто реєструємо просту команду:
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(CommandManager.literal("test_command").executes(context -> {
context.getSource().sendFeedback(() -> Text.literal("Called /test_command."), false);
return 1;
}));
});
У методі sendFeedback()
першим параметром є текст для надсилання, який є Supplier<Text>
, щоб уникнути створення екземплярів текстових об’єктів, коли вони не потрібні.
Другий параметр визначає, чи транслювати зворотний зв'язок іншим операторам. Загалом, якщо команда має запитувати щось, фактично не впливаючи на світ, наприклад поточний час або рахунок якогось гравця, має бути false
. Якщо команда щось виконує, наприклад змінює час або зміна чийогось рахунку, має бути true
.
Якщо команда не виконується, замість виклику sendFeedback()
ви можете безпосередньо викликати будь-який виняток і сервер або клієнт впорається з цим належним чином.
CommandSyntaxException
зазвичай викидається, щоб вказати на синтаксичні помилки в командах або аргументах. Ви також можете реалізувати ваш власний виняток.
Щоб виконати цю команду, ви повинні ввести /test_command
, яка чутлива до регістру.
INFO
З цього моменту ми будемо видобувати логіку, написану в лямбда-виразі, переданому в конструктори .execute()
в окремі методи. Потім ми можемо передати посилання на метод до .execute()
. Це зроблено для наочності.
Якщо потрібно, ви також можете переконатися, що команда зареєстрована лише за певних обставин, наприклад, лише в виділене середовище:
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
if (environment.dedicated) {
dispatcher.register(CommandManager.literal("dedicated_command")
.executes(FabricDocsReferenceCommands::executeDedicatedCommand));
}
});
private static int executeDedicatedCommand(CommandContext<ServerCommandSource> context) {
context.getSource().sendFeedback(() -> Text.literal("Called /dedicated_command."), false);
return 1;
}
Нехай, у вас є команда, і ви хочете, щоб її могли виконувати лише оператори. Тут знаходиться метод requires()
вступає в гру. Метод requires()
має один аргумент Predicate<S>
, який забезпечить ServerCommandSource
щоб перевірити та визначити, чи може CommandSource
виконати команду.
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(CommandManager.literal("required_command")
.requires(source -> source.hasPermissionLevel(1))
.executes(FabricDocsReferenceCommands::executeRequiredCommand));
});
private static int executeRequiredCommand(CommandContext<ServerCommandSource> context) {
context.getSource().sendFeedback(() -> Text.literal("Called /required_command."), false);
return 1;
}
Ця команда виконуватиметься, лише якщо команду використав оператор принаймні рівня 2, включаючи командні блоки. Інакше команда не реєструється.
Побічним ефектом цього є те, що ця команда не показується у tab під час завершення нікому, хто не є оператором рівня 2. Ось чому ви не можете завершити більшість команд, якщо ви не ввімкнули команди.
Щоб додати підкоманду, ви зазвичай реєструєте перший вузол літералу команди. Щоб мати підкоманду, вам потрібно додати наступний вузол літералу до існуючого вузла.
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(CommandManager.literal("command_one")
.then(CommandManager.literal("sub_command_one").executes(FabricDocsReferenceCommands::executeSubCommandOne)));
});
private static int executeSubCommandOne(CommandContext<ServerCommandSource> context) {
context.getSource().sendFeedback(() -> Text.literal("Called /command sub_command_one."), false);
return 1;
}
Подібно до аргументів, вузли підкоманд також можна встановити необов’язковими. У наступному випадку обидва /command_two
і /command_two sub_command_two
буде дійсним.
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(CommandManager.literal("command_two")
.executes(FabricDocsReferenceCommands::executeCommandTwo)
.then(CommandManager.literal("sub_command_two").executes(FabricDocsReferenceCommands::executeSubCommandTwo)));
});
private static int executeCommandTwo(CommandContext<ServerCommandSource> context) {
context.getSource().sendFeedback(() -> Text.literal("Called /command_two."), false);
return 1;
}
private static int executeSubCommandTwo(CommandContext<ServerCommandSource> context) {
context.getSource().sendFeedback(() -> Text.literal("Called /sub_command_two."), false);
return 1;
}
Fabric API містить ClientCommandManager у пакеті net.fabricmc.fabric.api.client.command.v2, який можна використовувати для реєстрації команд на стороні клієнта. Код має існувати лише в коді на стороні клієнта.
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {
dispatcher.register(ClientCommandManager.literal("clienttater").executes(context -> {
context.getSource().sendFeedback(Text.literal("Called /clienttater with no arguments."));
return 1;
}));
});
Переспрямування команд — також відоме як псевдоніми — це спосіб переспрямувати функціональність однієї команди на іншу. Це корисно, коли ви хочете змінити назву команди, але все одно бажаєте підтримувати стару назву.
WARNING
Brigadier перенаправлятиме лише командні вузли з аргументами. Якщо ви хочете перенаправити командний вузол без аргументів, надайте конструктор .executes()
із посиланням на ту саму логіку, що описана в прикладі.
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
var redirectedBy = dispatcher.register(CommandManager.literal("redirected_by").executes(FabricDocsReferenceCommands::executeRedirectedBy));
dispatcher.register(CommandManager.literal("to_redirect").executes(FabricDocsReferenceCommands::executeRedirectedBy).redirect(redirectedBy));
});
private static int executeRedirectedBy(CommandContext<ServerCommandSource> context) {
context.getSource().sendFeedback(() -> Text.literal("Called /redirected_by."), false);
return 1;
}
Перехопити або викинути CommandSyntaxException
- CommandSyntaxException
не є RuntimeException
. Якщо кинути, це повинно бути в методах, які викидають CommandSyntaxException
в сигнатурах методу, або його слід перехопити. Brigadier обробить перевірені винятки та перешле вам відповідне повідомлення про помилку в грі.
Проблеми з генериками. Час від часу у вас можуть виникати проблеми з генериками. Якщо ви реєструєте серверні команди (які в більшості випадків), переконайтеся, що ви використовуєте CommandManager.literal
або CommandManager.argument
замість LiteralArgumentBuilder.literal
або RequiredArgumentBuilder.argument
.
Перевірте метод sendFeedback() – можливо, ви забули вказати логічне значення як другий аргумент. Також запам'ятайте що, починаючи з Minecraft 1.20, першим параметром є Supplier<Text>
замість Text
.
Команда має повертати ціле число. Під час реєстрації команд метод executes()
приймає об’єкт Command
, який зазвичай є лямбда. Лямбда має повертати ціле число замість інших типів.
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
.
Після цього потрібно знову відправити дерево команд кожному гравцеві за допомогою CommandManager.sendCommandTree(ServerPlayerEntity)
.
Це потрібно, оскільки клієнт локально кешує дерево команд, яке отримує під час входу в систему (або коли пакети оператора надсилаються) для локальних повідомлень про помилки, повних завершень.
WARNING
You can also do this, however, it is much less stable than registering commands at runtime and could cause unwanted side effects.
Щоб все було просто, вам потрібно використовувати показ на Brigadier і видалити вузли. Після цього вам потрібно надіслати дерево команд кожному гравцеві за допомогою sendCommandTree(ServerPlayerEntity)
.
Якщо ви не надішлете оновлене дерево команд, клієнт може вважати, що команда все ще існує, навіть якщо сервер не зможе її виконати.