User Tools

Site Tools


ru:tutorial:commands

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
ru:tutorial:commands [2021/02/13 11:01] magicsweetru:tutorial:commands [2022/03/03 13:27] (current) furnygo
Line 1: Line 1:
-====== Создание команда ======+====== Создание команды ======
  
 Создание команд позволяет разработчику наращивать функционал и способ воздействия с пользователем через, собственно, команды. Создание команд позволяет разработчику наращивать функционал и способ воздействия с пользователем через, собственно, команды.
-Это руководство расскажет как регистрировать команды и общую инофрмацию о структуре Brigadier.+Это руководство расскажет как регистрировать команды и общую информацию о структуре Brigadier.
  
 Примечание: Весь код, описанный здесь, написан для 1.14.4. Что-то может быть изменено в yarn, но большая часть кода всё ещё применима и там. Примечание: Весь код, описанный здесь, написан для 1.14.4. Что-то может быть изменено в yarn, но большая часть кода всё ещё применима и там.
Line 12: Line 12:
 С исходным кодом Brigadier вы можете ознакомиться тут: https://github.com/Mojang/brigadier С исходным кодом Brigadier вы можете ознакомиться тут: https://github.com/Mojang/brigadier
  
-===== Что такое команда? =====+===== Что такое "команда"? =====
  
 Brigadier требует описание ''команды'' чтобы её исполнять. На самом деле, "команда" это довольно неточный термин, если мы говорим о Brigadier, но обычно он означает конечную точку для команды, т.е. то место, где исполняется ваш код. Brigadier требует описание ''команды'' чтобы её исполнять. На самом деле, "команда" это довольно неточный термин, если мы говорим о Brigadier, но обычно он означает конечную точку для команды, т.е. то место, где исполняется ваш код.
 ''Command'' - это функциональный интерфейс. Команда имеет подтип ''S'', где ''S'' - это источник команды. Источник команды может предоставить некий "контекст" для неё. В Minecraft обычно используется ''ServerCommandSource'', что представляет сервер, командный блок, соединение RCON, игрока или сущность. ''Command'' - это функциональный интерфейс. Команда имеет подтип ''S'', где ''S'' - это источник команды. Источник команды может предоставить некий "контекст" для неё. В Minecraft обычно используется ''ServerCommandSource'', что представляет сервер, командный блок, соединение RCON, игрока или сущность.
  
-Единственный метод в ''Command'' - ''run(CommandContext<S>)'' принимает один параметр ''CommandContext<S>'' и возвращает целое число. Контекст команды (CommandContext) типа ''S'' содержит в себе ''S'', позволяет увидеть используемые аргмуенты, работать с обработанными аргументами и непосредственный ввод пользователя.+Единственный метод в ''Command'' - ''run(CommandContext<S>)'' принимает один параметр ''CommandContext<S>'' и возвращает целое число. Контекст команды (CommandContext) типа ''S'' содержит в себе ''S'', позволяет увидеть используемые аргументы, работать с обработанными аргументами и посмотреть на непосредственный ввод пользователя.
  
 Вы можете создать команду несколькими образами, которые написаны ниже: Вы можете создать команду несколькими образами, которые написаны ниже:
Line 51: Line 51:
 <code java [enable_line_numbers="true"]> <code java [enable_line_numbers="true"]>
 void registerCommand() { void registerCommand() {
-    // Ignore this for nowwe will explain it next.+    // Не обращайте вниманиемы объясним про это далее.
     dispatcher.register(CommandManager.literal("foo"))     dispatcher.register(CommandManager.literal("foo"))
-        .executes(this::execute); // This refers to the "executemethod below.+        .executes(this::execute); // Это относится к приведённому ниже методу "выполнить".
 } }
  
Line 62: Line 62:
  
  
-Метод ''run(CommandContext)'' может произвести исключение ''CommandSyntaxException'', но это будет объяснено далее в руководстве. +Метод ''run(CommandContext)'' может произвести исключение ''CommandSyntaxException'', это будет объяснено далее в руководстве. 
  
 Возвращаемое число можно понимать как результат команды. В Minecraft результатом может являться силой сигнала красного камня, который выдаёт командный блок или число, которое будет передано в следующий цепной командный блок. Обычно отрицательное число значит что команда не выполнена и что-то пошло не по плану, ''0'' что команда прошла, положительные числа - что выполнена и что-то произошло.   Возвращаемое число можно понимать как результат команды. В Minecraft результатом может являться силой сигнала красного камня, который выдаёт командный блок или число, которое будет передано в следующий цепной командный блок. Обычно отрицательное число значит что команда не выполнена и что-то пошло не по плану, ''0'' что команда прошла, положительные числа - что выполнена и что-то произошло.  
Line 80: Line 80:
 ''CommandManager.literal("foo")'' даёт brigadier'у понять, что у команды только одна ветвь, это **буквальный ввод** foo. Чтобы команда была выполнена, нужно ввести ''/foo''. Если введено ''/Foo'', ''/FoO'', ''/FOO'', ''/fOO'' или ''/fooo'', команда не будет считаться верной. ''CommandManager.literal("foo")'' даёт brigadier'у понять, что у команды только одна ветвь, это **буквальный ввод** foo. Чтобы команда была выполнена, нужно ввести ''/foo''. Если введено ''/Foo'', ''/FoO'', ''/FOO'', ''/fOO'' или ''/fooo'', команда не будет считаться верной.
  
-==== Подкоманда ====+===== Статические импорты ===== 
 +Вы можете вводить ''CommandManager.literal("foo")'' каждый раз, когда хотите создать литерал. Это работает, но вы можете статически импортировать аргументы и сократить оператор до ''literal("foo")''. Это также работает для получения значения аргумента. Это сокращает ''StringArgumentType.getString(ctx, "string")'' до ''getString(ctx, "string")''
 +Это также работает для собственных типов аргументов Minecraft.
  
-Чтобы добавить команде подкоманду, сначала необходимо зарегестрировать ветвь с буквальным вводом.+И ваш импорт будет выглядеть примерно так: 
 +<code java [enable_line_numbers="true"]> 
 +// getString(ctx, "string"
 +import static com.mojang.brigadier.arguments.StringArgumentType.getString; 
 +// word() 
 +import static com.mojang.brigadier.arguments.StringArgumentType.word; 
 + // literal("foo"
 +import static net.minecraft.server.command.CommandManager.literal; 
 + // argument("bar", word()) 
 +import static net.minecraft.server.command.CommandManager.argument; 
 +// Импортировать всё 
 +import static net.minecraft.server.command.CommandManager.*; 
 +</code> 
 + 
 +Примечание: Пожалуйста, убедитесь, что вы используете ''literal'' и ''argument'' из CommandManager, иначе у вас могут возникнуть проблемы с дженериками при попытке компиляции. 
 + 
 +Аргументы Brigadier по умолчанию находятся в ''com.mojang.brigadier.arguments'' 
 + 
 +Аргументы Minecraft находятся в разделе ''net.minecraft.command.arguments''
 +CommandManager находится в ''net.minecraft.server.command'' 
 + 
 +===== Подкоманда ===== 
 + 
 +Чтобы добавить команде подкоманду, сначала необходимо зарегистрировать ветвь с буквальным вводом.
  
 <code java [enable_line_numbers="true"]> <code java [enable_line_numbers="true"]>
Line 90: Line 115:
 В целом, чтобы получить подкоманду, нужно расширить текущую ветвь следующей, уже существующей ветвью. Это можно сделать с помощью метода ''then(ArgumentBuilder)'' который принимает в себя ''ArgumentBuilder''. В целом, чтобы получить подкоманду, нужно расширить текущую ветвь следующей, уже существующей ветвью. Это можно сделать с помощью метода ''then(ArgumentBuilder)'' который принимает в себя ''ArgumentBuilder''.
  
-То, что показано ниже, создаёт команду ''foo <bar>''.+То, что показано ниже, создаёт команду ''foo <bar>'':
  
 <code java [enable_line_numbers="true", highlight_lines_extra="2"]> <code java [enable_line_numbers="true", highlight_lines_extra="2"]>
Line 98: Line 123:
 </code> </code>
  
-It is advised to indent your code as you add nodes to the commandUsually the indentation corresponds to how many nodes deep one is on the command treeThe new line also makes it visible that another node is being addedThere are alternative styles to formatting the tree command that are shown later on in this tutorial.+Рекомендуется делать отступы в вашем коде при добавлении узлов в командуОбычно отступ соответствует количеству глубоких узлов в дереве командНовая строка также делает видимым, что добавляется еще один узелСуществуют альтернативные стили для форматирования команды дерева, которые будут показаны позже в этом руководстве.
  
-**So let's try running the command**+**Итак, давайте попробуем выполнить команду**
  
-Most likely if you typed ''/foo bar'' in gamethe command will fail to runThis is because there is no code for the game to execute when all the required arguments have been metTo fix thisyou need to tell the game what to run when the command is being executed using the ''executes(Command)'' method. Below is how the command should look as an example.+Скорее всего, если вы наберете ''/foo bar'' в игрекоманда не будет выполненаЭто происходит потому, что нет кода для игры, который выполнялся бы после выполнения всех требуемых аргументовЧтобы исправить этовам нужно указать игре, что запускать, когда выполняется команда, используя метод ''executes(Command)''Ниже в качестве примера показано, как должна выглядеть команда:
  
 <code java [enable_line_numbers="true", highlight_lines_extra="3,4,5,6,7"]> <code java [enable_line_numbers="true", highlight_lines_extra="3,4,5,6,7"]>
Line 116: Line 141:
 </code> </code>
  
-===== Registering the commands =====+===== Регистрация команд =====
  
-Registering commands is done by registering a callback using the ''CommandRegistrationCallback''For information on registering callbacksplease see the [[tutorial:callbacks|callbacks article]].+Регистрация команд выполняется путем регистрации обратного вызова с помощью ''CommandRegistrationCallback''Для получения информации о регистрации обратных вызововознакомьтесь с [[ru:tutorial:callbacks|статьёй об обратных вызовах]].
  
-The event should be registered in your mod's initializerThe callback has two parametersThe ''CommmandDispatcher<S>'' is used to registerparse and execute commands. ''S'' is the type of command source the command dispatcher supportsThe second parameter is a boolean which identifies the type of server the commands are being registeredon is an ''dedicated'' or ''integrated'' (false) server.+Событие должно быть зарегистрировано в инициализаторе вашего модаОбратный вызов имеет два параметра. ''CommmandDispatcher<S>'' используется для регистрациианализа и выполнения команд. ''S'' i- это тип источника команд, который поддерживает диспетчер командВторой параметр - это логическое значение, которое определяет тип сервера, на котором регистрируются командыЭто может быть ''dedicated'' (выделенный) или ''integrated''(интегрированный) (false) сервер:
  
  
Line 134: Line 159:
 </code> </code>
  
-Inside your lambdamethod reference or whatever you have chosenyou will register your commands.+Внутри вашего лямбда-выраженияссылки на метод или чего бы вы ни выбрализарегистрируете свои команды:
  
 <code java [enable_line_numbers="true", highlight_lines_extra="5,6,7,8"]> <code java [enable_line_numbers="true", highlight_lines_extra="5,6,7,8"]>
Line 150: Line 175:
 </code> </code>
  
-If desiredyou can make sure a command is only registered on a dedicated server by checking the ''dedicated'' flag+При желании вы можете убедитьсячто команда зарегистрирована только на выделенном сервере, установив флажок ''dedicated''(выделенный):
  
  
Line 166: Line 191:
 </code> </code>
  
-And vice versa+И наоборот:
  
 <code java [enable_line_numbers="true", highlight_lines_extra="5,6,7"]> <code java [enable_line_numbers="true", highlight_lines_extra="5,6,7"]>
Line 181: Line 206:
 </code> </code>
  
-===== Arguments =====+===== Аргументы =====
  
-Arguments in Brigadier both parse and error check any inputted arguments+Аргументы в Brigadier как анализируют, так и проверяют на ошибки любые введенные аргументы
-Minecraft creates some special argument types for it's own use such as the ''EntityArgumentType'' which represents the in-game entity selectors ''@a, @r, @p, @e[type=!player, limit=1, distance=..2]'', or an ''NbtTagArgumentType'' that parses stringified nbt (snbt) and verifies that the input is the correct syntax.+Minecraft создает некоторые специальные типы аргументов для собственного использования, такие как ''EntityArgumentType'', который представляет внутриигровые селекторы сущностей ''@a, @r, @p, @e[type=!player, limit=1, distance=..2]'', или ''NbtTagArgumentType'', который анализирует строковый nbt (snbt) и проверяет правильность ввода синтаксиса.
  
-**TODO:** Go into more detail on how to use arguments+**Будет сделано позже:** Подробнее о том, как использовать аргументы.
  
-===== Static Imports ===== +====== Дополнительные концепции ======
-You could type out ''CommandManager.literal("foo")'' every time you want to create a literal. This works, but you can statically import the arguments and shorten the statement to ''literal("foo")''. This also works for getting the value of an argument. This shortens ''StringArgumentType.getString(ctx, "string")'' to ''getString(ctx, "string")''+
-This also works for Minecraft's own argument types.+
  
-And your imports would look something like this: +Ниже приведены ссылки на статьи о более сложных концепцияхиспользуемых в Brigadier.
-<code java [enable_line_numbers="true"]> +
-// getString(ctx"string"+
-import static com.mojang.brigadier.arguments.StringArgumentType.getString; +
-// word() +
-import static com.mojang.brigadier.arguments.StringArgumentType.word; +
- // literal("foo"+
-import static net.minecraft.server.command.CommandManager.literal; +
- // argument("bar", word()) +
-import static net.minecraft.server.command.CommandManager.argument; +
-// Import everything +
-import static net.minecraft.server.command.CommandManager.*; +
-</code>+
  
-NotePlease be sure you use the ''literal'' and ''argument'' from CommandManager or you may have issues with generics when trying to compile.+^ Страница                                                           ^ Описание                                                                     ^ 
 +| [[ru:tutorial:commands:requirements|Условия]]| Разрешать пользователям выполнять команды только в определенных сценариях.| 
 +| [[ru:tutorial:commands:exceptions|Исключения]]| Сбой выполнения команды с описательным сообщением и в определенных контекстах.|                                                                   
 +| [[ru:tutorial:commands:suggestions|Предложения]]| Предложение входных данных для отправки клиенту.| 
 +| [[ru:tutorial:commands:redirects_aliases|Редиректы (Разные вариации)]]| Разрешить использование разновидностей команд.| 
 +| [[ru:tutorial:commands:redirects_chaining|Редиректы (Цепочки)]]| Разрешить командам иметь повторяющиеся элементы и флаги.| 
 +| [[ru:tutorial:commands:argument_types|Свои типы аргументов]]| Анализируйте свои аргументы и возвращайте свои типы.|
  
-Brigadier's default arguments are at ''com.mojang.brigadier.arguments''+====== Часто задаваемые вопросы ======
  
-Minecraft's arguments are in ''net.minecraft.command.arguments''+===== Почему моя команда не компилируется? =====
-CommandManager is in ''net.minecraft.server.command''+
  
-====== Advanced concepts ======+Есть две непосредственные возможности того, почему это могло произойти.
  
-Below are links to the articles about more complex concepts used in brigadier.+==== Поймать или вызвать исключение CommandSyntaxException ====
  
-^ Page                                                           ^ Description                                                                     ^ +Решение этой проблемы состоит в том, чтобы заставить методы run или suggest вызывать исключение CommandSyntaxExceptionНе волнуйтесь, Brigadier обработает исключения и выдаст соответствующее сообщение об ошибке.
-| [[tutorials:commands:requirements|Requirements]]               | Only allow users to execute commands in certain scenarios                     | +
-| [[tutorials:commands:exceptions  |Exceptions]]                 | Fail execution of a command with a descriptive message and in certain contexts|                                                                   +
-| [[tutorials:commands:suggestions |Suggestions]]                | Suggesting input to be sent to the client.                                      | +
-| [[tutorials:commands:redirects_aliases|Redirects (Aliases)]]   | Allow use of aliases to execute commands.                                       | +
-| [[tutorials:commands:redirects_chaining|Redirects (Chaining)]] | Allow commands to have repeating elements and flags.                            | +
-| [[tutorials:commands:argument_types|Custom Argument Types]]    | Parse your own arguments and return your own types.                             |+
  
-**TODO:** Sections are being moved to sub categories and will be added to their respective articles as they are migrated.+==== Проблемы с дженериками ====
  
-====== FAQ ======+Время от времени у вас могут возникать проблемы с типами дженерика. Убедитесь, что вы используете ''CommandManager.literal(...)'' или ''CommandManager.argument(...)'' вместо ''LiteralArgumentBuilder'' или ''RequiredArgumentBuilder''.
  
-===== Why does my command not compile =====+===== Могу ли я зарегистрировать команды на стороне клиента? =====
  
-There are two immediate possibilities for why this could occur.+Fabric в настоящее время не поддерживает команды на стороне клиента. Существует [[https://github.com/CottonMC/ClientCommands|сторонний мод]] от команды Cotton, которая добавляет эту функциональность.
  
-==== Catch or throw a CommandSyntaxException ====+===== "Темные искусства" =====
  
-The solution to this issue is to make the run or suggest methods throw a CommandSyntaxException. Don't worrybrigadier will handle the exceptions and output the proper error message.+Несколько вещейкоторые мы не рекомендуем, но которые возможны.
  
-==== Issues with generics ====+==== Могу ли я регистрировать команды во время выполнения? ====
  
-You may have an issue with generic types once in a whileVerify you are using ''CommandManager.literal(...)'' or ''CommandManager.argument(...)'' instead ''LiteralArgumentBuilder'' or ''RequiredArgumentBuilder''.+Вы можете это сделать, но это не рекомендуетсяВы получите ''CommandManager'' с сервера и добавите любые команды, которые пожелаете, в его ''CommandDispatcher''.
  
-===== Can I register client side commands? =====+После этого вам нужно снова отправить дерево команд каждому игроку, используя ''sendCommandTree(ServerPlayerEntity)''. Это необходимо, поскольку клиент локально кэширует дерево команд, которое он получает во время входа в систему (или при отправке пакетов оператора) для локальных завершений и сообщений об ошибках.
  
-Fabric doesn't currently support client side commands. There is a [[https://github.com/CottonMC/ClientCommands|third-party mod]] by the Cotton team that adds this functionality.+==== Могу ли я отменить регистрацию команд во время выполнения? ====
  
-===== Dark Arts ===== +Вы также можете сделать этооднако это гораздо менее стабильно, чем регистрация команди может вызвать нежелательные побочные эффектыЧтобы все было простовам нужно использовать отражение для бригадира и удалить узлыПосле этого вам нужно снова отправить дерево команд каждому игрокуиспользуя ''sendCommandTree(ServerPlayerEntity)''Если вы не отправите обновленное дерево команд, клиент может подуматьчто команда все еще существуетдаже если сервер завершит выполнение с ошибкой.
- +
-A few things we don't recommendbut are possible. +
- +
-==== Can I register commands in runtime? ==== +
- +
-You can do this but it is not recommended. You would get the ''CommandManager'' from the server and add anything commands you wish to it's ''CommandDispatcher''+
- +
-After that you need to send the command tree to every player again using ''sendCommandTree(ServerPlayerEntity)''. This is required because the client locally caches the command tree it receives during login (or when operator packets are sent) for local completions rich error messages. +
- +
-==== Can I unregister commands in runtime? ==== +
- +
-You can also do thishowever it is much less stable than registering commands and could cause unwanted side effectsTo keep things simpleyou need to use reflection on brigadier and remove the nodesAfter thisyou need to send the command tree to every player again using ''sendCommandTree(ServerPlayerEntity)''If you don't send the updated command treethe client may think a command still existseven though the server will fail execution.+
  
 ---- ----
  
-====== Sorry for the mess ====== +====== Со временем будет перенесено ======
- +
-**__Currently this article is being migrated, so things may be a mess. Below is are the parts of the article that are yet to be migrated to the new format.__** +
- +
-===== Requirements ===== +
- +
-Lets say you have a command you only want operators to be able to execute. This is where the ''requires'' method comes into play. The requires method has one argument of a Predicate<ServerCommandSource> which will supply a ServerCommandSource to test with and determine if the CommandSource can execute the command. +
- +
-For example this may look like the following: +
- +
-<code java [enable_line_numbers="true"]> +
-dispatcher.register(literal("foo"+
- .requires(source -> source.hasPermissionLevel(4)) +
- .executes(ctx -> { +
- ctx.getSource().sendFeedback(new LiteralText("You are an operator", false)); +
- return 1; +
- }); +
-</code> +
- +
-This command will only execute if the Source of the command is a level 4 operator at minimum. If the predicate returns false, then the command will not execute. Also this has the side effect of not showing this command in tab completion to anyone who is not a level 4 operator. +
- +
-Nothing prevents someone from specifying calls to permissions implementations within the ''requires'' block. Just note that if permissions change, you need to re send the command tree. +
- +
-===== Exceptions ===== +
- +
-Brigadier supports command exceptions which can be used to end a command such as if an argument didn't parse properly or the command failed to execute, as well as including richer details of the failure. +
- +
-All the exceptions from Brigadier are based on the CommandSyntaxException. The two main types of exceptions Brigadier provides are Dynamic and Simple exception types, of which you must ''create()'' the exception to throw it. These exceptions also allow you to specify the context in which the exception was thrown using ''createWithContext(ImmutableStringReader)'', which builds the error message to point to where on the inputted command line the error occured. +
-Below is a coin flip command to show an example of exceptions in use. +
- +
-<code java [enable_line_numbers="true"]> +
-dispatcher.register(CommandManager.literal("coinflip"+
-    .executes(ctx -> { +
-        Random random = new Random(); +
-  +
-        if(random.nextBoolean()) { // If heads succeed. +
-            ctx.getSource().sendMessage(new TranslateableText("coin.flip.heads")) +
-            return Command.SINGLE_SUCCESS; +
-        } +
- +
-        throw new SimpleCommandExceptionType(new TranslateableText("coin.flip.tails")).create(); // Oh no tails, you lose. +
-    })); +
-</code> +
- +
-Though you are not just limited to a single type of exception as Brigadier also supplies Dynamic exceptions which take additional parameters for context. +
- +
-<code java [enable_line_numbers="true"]> +
-DynamicCommandExceptionType used_name = new DynamicCommandExceptionType(name -> { +
-    return new LiteralText("The name: " + (String) name + " has been used"); +
-}); +
-</code> +
- +
-There are more Dynamic exception types which each take a different amount of arguments into account (''Dynamic2CommandExceptionType'', ''Dynamic3CommandExceptionType'', ''Dynamic4CommandExceptionType'', ''DynamicNCommandExceptionType''). +
-You should remember that the Dynamic exceptions takes an object as an argument so you may have to cast the argument for your use. +
- +
-===== Redirects (Aliases) ===== +
- +
-Redirects are Brigadier's form of aliases. Below is how Minecraft handles /msg have an alias of /tell and /w.  +
- +
-<code java [enable_line_numbers="true"]> +
-public static void register(CommandDispatcher<ServerCommandSource> dispatcher) { +
-    LiteralCommandNode node = registerMain(dispatcher); // Registers main command +
-    dispatcher.register(literal("tell"+
-        .redirect(node)); // Alias 1, redirect to main command +
-    dispatcher.register(literal("w"+
-        .redirect(node)); // Alias 2, redirect to main command +
-+
- +
-public static LiteralCommandNode registerMain(CommandDispatcher<ServerCommandSource> dispatcher) { +
-    return dispatcher.register(literal("msg"+
-    .then(argument("targets", EntityArgumentType.players()) +
-        .then(argument("message", MessageArgumentType.message()) +
-            .executes(ctx -> { +
-                return execute(ctx.getSource(), getPlayers(ctx, "targets"), getMessage(ctx, "message")); +
-            })))); +
-+
-</code> +
- +
-The redirect tells brigadier to continue parsing the command at another command node. +
- +
-===== Redirects (Chainable Commands) ===== +
-Commands such as ''/execute as @e[type=player] in the_end run tp ~ ~ ~'' are possible because of redirects. Below is an example of a chainable command: +
- +
-<code java [enable_line_numbers="true"]> +
-LiteralCommandNode<ServerCommandSource> root = dispatcher.register(literal("fabric_test")); +
-LiteralCommandNode<ServerCommandSource> root1 = dispatcher.register(literal("fabric_test")  +
-// You can register under the same literal more than once, it will just register new parts of the branch as shown below if you register a duplicate branch an error will popup in console warning of conflicting commands but one will still work. +
-    .then(literal("extra"+
-        .then(literal("long"+
-            .redirect(root, this::lengthen)) // Return to root for chaining +
-        .then(literal("short"+
-            .redirect(root, this::shorten))) // Return to root for chaining +
-        .then(literal("command"+
-            .executes(ctx -> { +
-                ctx.getSource().sendFeedback(new LiteralText("Chainable Command"), false); +
-                return Command.SINGLE_SUCCESS; +
-}))); +
-</code> +
-The redirect can also modify the CommandSource by use of a ''redirect modifier'' which can be used for builder commands. +
- +
-<code java [enable_line_numbers="true"]> +
-.redirect(rootNode, context -> { +
-    return ((ServerCommandSource) context.getSource()).withLookingAt(Vec3ArgumentType.getVec3(context, "pos")); +
-}) +
-</code>+
  
-===== What can the ServerCommandSource do? =====+===== Что может сделать ServerCommandSource? =====
  
-A server command source provides some additional implementation specific context when a command is run. This includes the ability to get the entity that executed the commandthe world the command was ran in or the server the command was run on.+''ServerCommandSource'' предоставляет некоторый дополнительный контекстспецифичный для конкретной реализации, при выполнении командыЭто включает в себя возможность получить объект, который выполнил команду, мир, в котором была запущена команда, или сервер, на котором была запущена команда:
  
 <code java [enable_line_numbers="true"]> <code java [enable_line_numbers="true"]>
 final ServerCommandSource source = ctx.getSource();  final ServerCommandSource source = ctx.getSource(); 
-// Get the sourceThis will always work.+// Находка источникаЭто всегда будет работать.
  
 final Entity sender = source.getEntity();  final Entity sender = source.getEntity(); 
-// Uncheckedmay be null if the sender was the console.+// Непроверенныйможет быть нулевым, если отправителем была консоль.
  
 final Entity sender2 = source.getEntityOrThrow();  final Entity sender2 = source.getEntityOrThrow(); 
-// Will end the command if the source of the command was not an Entity.  +// Завершит выполнение команды, если источником команды не была не сущность.  
-// The result of this could contain a playerAlso will send feedback telling the sender of the command that they must be an entity.  +// В результате этого может появиться игрокТакже будет отправлена обратная связь, сообщающая отправителю команды, что он должен быть сущностью.  
-// This method will require your methods to throw a CommandSyntaxException.  +// Этот метод потребует, чтобы ваши методы вызывали исключение CommandSyntaxException.  
-// The entity options in ServerCommandSource could return a CommandBlock entityany living entity or a player.+// Параметры сущности в ServerCommandSource могут возвращать сущность CommandBlock, любое живое существо или игрока.
  
 final ServerPlayerEntity player = source.getPlayer();  final ServerPlayerEntity player = source.getPlayer(); 
-// Will end the command if the source of the command was not explicitly a PlayerAlso will send feedback telling the sender of the command that they must be a player This method will require your methods to throw a CommandSyntaxException+// Завершит выполнение команды, если источником команды явно не был игрокТакже будет отправлен отзыв, сообщающий отправителю команды, что он должен быть игроком. 
 +// Этот метод потребует, чтобы ваши методы вызывали исключение CommandSyntaxException
  
 source.getPosition();  source.getPosition(); 
-// Get's the sender's position as a Vec3 when the command was sentThis could be the location of the entity/command block or in the case of the consolethe world's spawn point.+// Позиция отправителя в качестве Vec3, когда была отправлена командаЭто может быть местоположение сущности/командного блока или, в случае консолиточка появления в мире.
  
 source.getWorld();  source.getWorld(); 
-// Get's the world the sender is withinThe console's world is the same as the default spawn world.+// Мир, в котором находится отправительМир консоли такой же, как и мир создания по умолчанию.
  
 source.getRotation();  source.getRotation(); 
-// Get's the sender's rotation as a Vec2f.+// Вращение отправителя как Vec2f.
  
 source.getMinecraftServer();  source.getMinecraftServer(); 
-// Access to the instance of the MinecraftServer this command was ran on.+// Доступ к экземпляру MinecraftServer, на котором была запущена эта команда.
  
 source.getName();  source.getName(); 
-// The name of the command sourceThis could be the name of the entityplayerthe name of a CommandBlock that has been renamed before being placed down or in the case of the Console, "Console"+// Имя источника командыЭто может быть имя сущностиигрокаимя командного блока, который был переименован перед размещением, или, в случае консоли, "Console".
  
 source.hasPermissionLevel(int level);  source.hasPermissionLevel(int level); 
-// Returns true if the source of the command has a certain permission levelThis is based on the operator status of the sender. (On an integrated server, the player must have cheats enabled to execute these commands)+// Возвращает значение true, если источник команды имеет определенный уровень разрешенийЭто зависит от статуса оператора отправителя. (На интегрированном сервере у игрока должны быть включены читы для выполнения этих команд)
 </code> </code>
  
-===== Some example commands examples =====+===== Некоторые примеры команд =====
  
-=== Broadcast a message ===+=== Транслировать сообщение ===
  
 <code java [enable_line_numbers="true"]>  <code java [enable_line_numbers="true"]> 
 public static void register(CommandDispatcher<ServerCommandSource> dispatcher){ public static void register(CommandDispatcher<ServerCommandSource> dispatcher){
     dispatcher.register(literal("broadcast")     dispatcher.register(literal("broadcast")
-        .requires(source -> source.hasPermissionLevel(2)) // Must be a game master to use the commandCommand will not show up in tab completion or execute to non operators or any operator that is permission level 1.+        .requires(source -> source.hasPermissionLevel(2)) // Должен быть мастером игры, чтобы использовать эту командуКоманда не будет отображаться при перебора через Tab или выполняться не для операторов или любого оператора, имеющего уровень разрешений 1.
             .then(argument("color", ColorArgumentType.color())             .then(argument("color", ColorArgumentType.color())
                 .then(argument("message", greedyString())                 .then(argument("message", greedyString())
-                    .executes(ctx -> broadcast(ctx.getSource(), getColor(ctx, "color"), getString(ctx, "message")))))); // You can deal with the arguments out here and pipe them into the command.+                    .executes(ctx -> broadcast(ctx.getSource(), getColor(ctx, "color"), getString(ctx, "message")))))); // Вы можете разобраться с приведенными здесь аргументами и передать их в команду.
 } }
  
Line 423: Line 318:
  
     source.getMinecraftServer().getPlayerManager().broadcastChatMessage(text, false);     source.getMinecraftServer().getPlayerManager().broadcastChatMessage(text, false);
-    return Command.SINGLE_SUCCESS; // Success+    return Command.SINGLE_SUCCESS; // Успех
 } }
 </code> </code>
Line 429: Line 324:
 ==== /giveMeDiamond ==== ==== /giveMeDiamond ====
  
-First the basic code where we register "giveMeDiamond" as a literal and then an executes block to tell the dispatcher which method to run.+Сначала базовый код, в котором мы регистрируем ''giveMeDiamond'' как литерал, а затем вызываем блок, чтобы сообщить диспетчеру, какой метод запускать:
  
 <code java [enable_line_numbers="true"]> <code java [enable_line_numbers="true"]>
-public static LiteralCommandNode register(CommandDispatcher<ServerCommandSource> dispatcher) { // You can also return a LiteralCommandNode for use with possible redirects+public static LiteralCommandNode register(CommandDispatcher<ServerCommandSource> dispatcher) { // Вы также можете вернуть LiteralCommandNode для использования с возможными редиректорами.
     return dispatcher.register(literal("giveMeDiamond")     return dispatcher.register(literal("giveMeDiamond")
         .executes(ctx -> giveDiamond(ctx)));         .executes(ctx -> giveDiamond(ctx)));
Line 438: Line 333:
 </code> </code>
  
-Then since we only want to give to playerswe check if the CommandSource is a playerBut we can use ''getPlayer'' and do both at the same time and throw an error if the source is not a player.+Затемпоскольку мы хотим передавать только игрокам, мы проверяем, является ли CommandSource игрокомНо мы можем использовать ''getPlayer'' и сделать и то, и другое одновременно, и выдать ошибку, если источник не является игроком:
  
 <code java [enable_line_numbers="true"]> <code java [enable_line_numbers="true"]>
Line 444: Line 339:
     final ServerCommandSource source = ctx.getSource();     final ServerCommandSource source = ctx.getSource();
   
-    final PlayerEntity self = source.getPlayer(); // If not a player than the command ends+    final PlayerEntity self = source.getPlayer(); // Если это не игрок, то команда заканчивается
 </code> </code>
  
-Then we add to the player's inventorywith a check to see if the inventory is full:+Затем мы добавляем в инвентарь игрокапроверяя, заполнен ли инвентарь:
  
 <code java [enable_line_numbers="true"]> <code java [enable_line_numbers="true"]>
Line 458: Line 353:
 </code> </code>
  
-==== Antioch ==== +==== Граната Антиоха ==== 
-...lobbest thou thy Holy Hand Grenade of Antioch towards thy foe+...брось ты свою Святую Ручную Гранату из Антиохии своему врагу
-who being naughty in My sightshall snuff it.+которыйбудучи непослушным в моих глазах, погубит его 
 +(Иностранный прикол)
  
-Aside from the joke this command summons a primed TNT to a specified location or the location of the sender's cursor.+Помимо шутки, эта команда вызывает заряженный TNT в указанное местоположение или местоположение курсора отправителя.
  
-First create an entry into the CommandDispatcher that takes a literal of antioch with an optional argument of the location to summon the entity at.+Сначала создайте запись в CommandDispatcher, которая принимает литерал antioch с необязательным аргументом местоположения для вызова сущности.
  
 <code java [enable_line_numbers="true"]> <code java [enable_line_numbers="true"]>
Line 475: Line 371:
 </code> </code>
  
-Then the creation and messages behind the joke.+Затем создайте сообщения, стоящие за шуткой:
  
 <code java [enable_line_numbers="true"]> <code java [enable_line_numbers="true"]>
 public static int antioch(ServerCommandSource source, BlockPos blockPos) throws CommandSyntaxException { public static int antioch(ServerCommandSource source, BlockPos blockPos) throws CommandSyntaxException {
     if(blockPos == null) {     if(blockPos == null) {
-        // For the case of no inputted argument we calculate the cursor position of the player or throw an error if the nearest position is too far or is outside of the world+        // В случае отсутствия введенного аргумента мы вычисляем положение курсора игрока или выдаем ошибку, если ближайшая позиция находится слишком далеко или находится за пределами мира
-        // This class is used as an example and actually doesn't exist yet.+        // Этот класс используется в качестве примера и на самом деле еще не существует.
         blockPos = LocationUtil.calculateCursorOrThrow(source, source.getRotation());         blockPos = LocationUtil.calculateCursorOrThrow(source, source.getRotation());
     }     }
Line 488: Line 384:
     tnt.setFuse(3);     tnt.setFuse(3);
                  
-    source.getMinecraftServer().getPlayerManager().broadcastChatMessage(new LiteralText("...lobbest thou thy Holy Hand Grenade of Antioch towards thy foe").formatting(Formatting.RED), false); +    source.getMinecraftServer().getPlayerManager().broadcastChatMessage(new LiteralText("...брось ты свою Святую Ручную Гранату из Антиохии своему врагу").formatting(Formatting.RED), false); 
-    source.getMinecraftServer().getPlayerManager().broadcastChatMessage(new LiteralText("who being naughty in My sightshall snuff it.").formatting(Formatting.RED), false);+    source.getMinecraftServer().getPlayerManager().broadcastChatMessage(new LiteralText("которыйбудучи непослушным в моих глазах, погубит его.").formatting(Formatting.RED), false);
     source.getWorld().spawnEntity(tnt);     source.getWorld().spawnEntity(tnt);
     return 1;     return 1;
Line 495: Line 391:
 </code> </code>
  
-==== More examples coming soon ==== +==== Скоро появятся новые примеры ====
- +
-===== Custom Argument Types ===== +
- +
-Brigadier has support for custom argument types and this section goes into showing how to create a simple argument type.  +
- +
-Warning: Custom arguments require client mod installation to be registered correctly! If you are making a server plugin, consider using existing argument type and a custom suggestions provider instead. +
- +
-For this example we will create a UuidArgumentType. +
- +
-First create a class which extends ''ArgumentType''. Note that ArgumentType is a generic, so the generic will define what type the ArgumentType will return +
- +
-<code java [enable_line_numbers="true"]> +
-public class UuidArgumentType implements ArgumentType<UUID>+
-</code> +
- +
-ArgumentType requires you to implement the ''parse'' method, the type it returns will match with the Generic type. +
-<code java> +
-@Override +
-public UUID parse(StringReader reader) throws CommandSyntaxException { +
-</code> +
- +
-This method is where all of your parsing will occur. Either this method will return the object based on the arguments provided in the command line or throw a CommandSyntaxException and parsing will fail. +
- +
-Next you will store the current position of the cursor, this is so you can substring out only the specific argument. This will always be at the beginning of where your argument appears on the command line. +
- +
-<code java [enable_line_numbers="true"]> +
-int argBeginning = reader.getCursor(); // The starting position of the cursor is at the beginning of the argument. +
-if (!reader.canRead()) { +
-    reader.skip(); +
-+
-</code> +
- +
-Now we grab the entire argument. Depending on your argument type, you may have a different criteria or be similar to some arguments where detecting a ''{'' on the command line will require it to be closed. For a UUID we will just figure out what cursor position the argument ends at. +
- +
-<code java [enable_line_numbers="true"]> +
-while (reader.canRead() && reader.peek() != ' ') { // peek provides the character at the current cursor position. +
-    reader.skip(); // Tells the StringReader to move it's cursor to the next position. +
-+
-</code> +
- +
-Then we will ask the StringReader what the current position of the cursor is an substring our argument out of the command line. +
- +
-<code java [enable_line_numbers="true"]>String uuidString = reader.getString().substring(argBeginning, reader.getCursor());</code> +
- +
-Now finally we check if our argument is correct and parse the specific argument to our liking, and throwing an exception if the parsing fails. +
- +
-<code java [enable_line_numbers="true"]> +
-try { +
-    UUID uuid = UUID.fromString(uuidString); // Now our actual logic. +
-    return uuid; // And we return our type, in this case the parser will consider this argument to have parsed properly and then move on. +
-    } catch (Exception ex) { +
-    // UUIDs can throw an exception when made by a string, so we catch the exception and repackage it into a CommandSyntaxException type. +
-    // Create with context tells Brigadier to supply some context to tell the user where the command failed at. +
-    // Though normal create method could be used. +
-    throw new SimpleCommandExceptionType(new LiteralText(ex.getMessage())).createWithContext(reader); +
-+
-</code> +
- +
-The ArgumentType is done, however your client will refuse the parse the argument and throw an error. This is because the server will tell the client what argument type the command node is. And the client will not parse any argument types it does not know how to parse. To fix this we need to register an ArgumentSerializer.  +
-Within your ModInitializer. For more complex argument types, you may need to create your own ArgumentSerializer. +
- +
-<code java [enable_line_numbers="true"]> +
-ArgumentTypes.register("mymod:uuid", UuidArgumentType.class, new ConstantArgumentSerializer(UuidArgumentType::uuid));  +
-// The argument should be what will create the ArgumentType. +
-</code> +
- +
-And here is the whole ArgumentType: +
- +
-<file java UuidArgumentType.java [enable_line_numbers="true"]> +
- +
-import com.mojang.brigadier.StringReader; +
-import com.mojang.brigadier.arguments.ArgumentType; +
-import com.mojang.brigadier.context.CommandContext; +
-import com.mojang.brigadier.exceptions.CommandSyntaxException; +
-import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +
-import net.minecraft.text.LiteralText; +
-import net.minecraft.util.SystemUtil; +
- +
-import java.util.ArrayList; +
-import java.util.Collection; +
-import java.util.UUID; +
- +
-/** +
- * Represents an ArgumentType that will return a UUID. +
- */ +
-public class UuidArgumentType implements ArgumentType<UUID>+
-    public static UuidArgumentType uuid() { +
-        return new UuidArgumentType(); +
-    } +
- +
-    public static <S> UUID getUuid(String name, CommandContext<S> context) { +
-        // Note that you should assume the CommandSource wrapped inside of the CommandContext will always be a generic type. +
-        // If you need to access the ServerCommandSource make sure you verify the source is a server command source before casting. +
-        return context.getArgument(name, UUID.class); +
-    } +
- +
-    private static final Collection<String> EXAMPLES = SystemUtil.consume(new ArrayList<>(), list -> { +
-        list.add("765e5d33-c991-454f-8775-b6a7a394c097"); // i509VCB: Username The_1_gamers +
-        list.add("069a79f4-44e9-4726-a5be-fca90e38aaf5"); // Notch +
-        list.add("61699b2e-d327-4a01-9f1e-0ea8c3f06bc6"); // Dinnerbone +
-    }); +
- +
-    @Override +
-    public UUID parse(StringReader reader) throws CommandSyntaxException { +
-        int argBeginning = reader.getCursor(); // The starting position of the cursor is at the beginning of the argument. +
-        if (!reader.canRead()) { +
-            reader.skip(); +
-        } +
- +
-        // Now we check the contents of the argument till either we hit the end of the command line (When canRead becomes false) +
-        // Otherwise we go till reach reach a space, which signifies the next argument +
-        while (reader.canRead() && reader.peek() != ' ') { // peek provides the character at the current cursor position. +
-            reader.skip(); // Tells the StringReader to move it's cursor to the next position. +
-        } +
- +
-        // Now we substring the specific part we want to see using the starting cursor position and the ends where the next argument starts. +
-        String uuidString = reader.getString().substring(argBeginning, reader.getCursor()); +
-        try { +
-            UUID uuid = UUID.fromString(uuidString); // Now our actual logic. +
-            return uuid; // And we return our type, in this case the parser will consider this argument to have parsed properly and then move on. +
-        } catch (Exception ex) { +
-            // UUIDs can throw an exception when made by a string, so we catch the exception and repackage it into a CommandSyntaxException type. +
-            // Create with context tells Brigadier to supply some context to tell the user where the command failed at. +
-            // Though normal create method could be used. +
-            throw new SimpleCommandExceptionType(new LiteralText(ex.getMessage())).createWithContext(reader); +
-        } +
-    } +
- +
-    @Override +
-    public Collection<String> getExamples() { // Brigadier has support to show examples for what the argument should look like, this should contain a Collection of only the argument this type will return. This is mainly used to calculate ambiguous commands which share the exact same  +
-        return EXAMPLES; +
-    } +
-+
-</file>+
ru/tutorial/commands.1613214103.txt.gz · Last modified: 2021/02/13 11:01 by magicsweet