zh_cn:tutorial:commands
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| zh_cn:tutorial:commands [2023/11/18 09:57] – [ServerCommandSource 是做什么的?] solidblock | zh_cn:tutorial:commands [2025/07/06 07:10] (current) – [静态导入] solidblock | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | |||
| 条款:本文中的代码适用于“Creative Commons Zero v1.0 Universial”条款,允许您将文中的代码示例用于自己的模组中。 | 条款:本文中的代码适用于“Creative Commons Zero v1.0 Universial”条款,允许您将文中的代码示例用于自己的模组中。 | ||
| Line 6: | Line 5: | ||
| ====== 创建命令 ====== | ====== 创建命令 ====== | ||
| - | 创建命令允许模组开发者添加可以使用命令实现的功能。本教程将会教你如何注册命令,以及Brigadier的基本命令结构。 | + | 创建命令允许模组开发者添加可以使用命令实现的功能。本教程将会教你如何注册命令,以及 Brigadier 的基本命令结构。 |
| - | + | ||
| - | 注意:本文的所有代码都是用于 1.19.2 的。对于旧的版本,一些版本和映射可能不同。 | + | |
| ===== Brigadier 是什么? ===== | ===== Brigadier 是什么? ===== | ||
| Line 29: | Line 26: | ||
| }; | }; | ||
| </ | </ | ||
| - | |||
| - | 在原版 Minecraft 中,命令通常用作方法引用,例如原版的 '' | ||
| 这个整数相当于命令的结果。在 Minecraft 中。通常来说,负值表示命令执行失败,什么也不做,'' | 这个整数相当于命令的结果。在 Minecraft 中。通常来说,负值表示命令执行失败,什么也不做,'' | ||
| Line 36: | Line 31: | ||
| ==== ServerCommandSource 是做什么的? ==== | ==== ServerCommandSource 是做什么的? ==== | ||
| - | '' | + | '' |
| <code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
| Line 95: | Line 90: | ||
| CommandRegistrationCallback.EVENT.register((dispatcher, | CommandRegistrationCallback.EVENT.register((dispatcher, | ||
| .executes(context -> { | .executes(context -> { | ||
| - | // 对于 1.19 以下的版本,把“Text.literal”替换为“new LiteralText”。 | + | // 对于 1.19 之前的版本,把“Text.literal”替换为“new LiteralText”。 |
| - | context.getSource().sendMessage(Text.literal(" | + | // 对于 1.20 之前的版本,请移除“() ->”。 |
| + | context.getSource().sendFeedback(() -> Text.literal(" | ||
| return 1; | return 1; | ||
| Line 104: | Line 100: | ||
| </ | </ | ||
| - | '' | + | **请确保你导入了正确的静态方法。**方法 '' |
| + | |||
| + | 在 '' | ||
| + | |||
| + | 如果命令失败,可以不必调用 '' | ||
| 要执行命令,必须输入 ''/ | 要执行命令,必须输入 ''/ | ||
| + | ===== 注册环境 ===== | ||
| 如有需要,你可以确保命令仅在一些特定情形下注册,例如仅在专用服务器上: | 如有需要,你可以确保命令仅在一些特定情形下注册,例如仅在专用服务器上: | ||
| - | <code java [enable_line_numbers=" | + | <yarncode |
| public class ExampleCommandMod implements ModInitializer { | public class ExampleCommandMod implements ModInitializer { | ||
| @Override | @Override | ||
| public void onInitialize() { | public void onInitialize() { | ||
| CommandRegistrationCallback.EVENT.register((dispatcher, | CommandRegistrationCallback.EVENT.register((dispatcher, | ||
| - | if (environment.dedicated) { | + | if (environment.field_25423) { |
| ...; | ...; | ||
| } | } | ||
| Line 121: | Line 122: | ||
| } | } | ||
| } | } | ||
| - | </code> | + | </yarncode> |
| ===== 静态导入 ===== | ===== 静态导入 ===== | ||
| - | 在上面的例子中,使用了静态导入以简化代码。对于字面值,语句会简化为 '' | + | 在上面的例子中,使用了静态导入以简化代码。对于字面值,语句会简化为 '' |
| - | Below is an example of some static imports: | + | 以下是一些静态导入的例子。 |
| <code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
| // getString(ctx, | // getString(ctx, | ||
| Line 140: | Line 141: | ||
| </ | </ | ||
| - | 注意:请确保使用了 '' | + | 注意:请确保使用了 '' |
| Brigadier 的默认参数位于 '' | Brigadier 的默认参数位于 '' | ||
| Line 146: | Line 147: | ||
| Minecraft 的参数位于 '' | Minecraft 的参数位于 '' | ||
| - | ===== 条件 ===== | + | ===== 添加条件 ===== |
| 有时你希望命令只有管理员(OP)可以执行,这时就要用到 '' | 有时你希望命令只有管理员(OP)可以执行,这时就要用到 '' | ||
| Line 154: | Line 155: | ||
| <code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
| dispatcher.register(literal(" | dispatcher.register(literal(" | ||
| - | .requires(source -> source.hasPermissionLevel(4)) | + | |
| .executes(ctx -> { | .executes(ctx -> { | ||
| - | ctx.getSource().sendFeedback(Text.literal(" | + | ctx.getSource().sendFeedback(() -> Text.literal(" |
| return 1; | return 1; | ||
| }); | }); | ||
| </ | </ | ||
| - | 此时命令只会在命令源为 | + | 此时命令只会在命令源为 |
| + | |||
| + | 要创建只有 4 级管理员(不包括命令方块)可以执行的命令,请使用 '' | ||
| ===== 参数 ===== | ===== 参数 ===== | ||
| - | Brigadier 中的参数会解析任何输入的参数,并检查错误。Minecraft 创建了一些特殊的参数类型以用于自己使用,例如 '' | + | 大多数命令都使用了参数。一些参数是可选的,也就是说如果你不提供此参数,命令仍能运行。一个节点可以有多个参数类型,但是注意有可能出现二义性,这是需要避免的。 |
| - | **TODO:**详细介绍如何使用参数 | + | 在这个例子中。我们添加一个整数参数。并计算整数的平方。 |
| - | ===== 子命令 ===== | + | <code java> |
| + | dispatcher.register(literal(" | ||
| + | .then(argument(" | ||
| + | .executes(context -> { | ||
| + | final int value = IntegerArgumentType.getInteger(context, | ||
| + | final int result | ||
| + | context.getSource().sendFeedback(() -> Text.literal(" | ||
| + | return result; | ||
| + | }))); | ||
| + | </ | ||
| - | 要添加子命令,你需要先照常注册注册第一个字面节点。 | + | 在这个例子中,在 ''/ |
| - | <code java [enable_line_numbers="true"]> | + | 注意:为了简便,'' |
| - | dispatcher.register(literal(" | + | |
| + | 然后我们添加可选的第二个参数: | ||
| + | <code java> | ||
| + | dispatcher.register(literal(" | ||
| + | .then(argument(" | ||
| + | .executes(context -> { | ||
| + | final int value = IntegerArgumentType.getInteger(context, | ||
| + | final int result = value * value; | ||
| + | context.getSource().sendFeedback(() -> Text.literal(" | ||
| + | | ||
| + | }) | ||
| + | | ||
| + | .executes(context -> { | ||
| + | final int value = IntegerArgumentType.getInteger(context, | ||
| + | final int value2 = IntegerArgumentType.getInteger(context, | ||
| + | final int result = value * value2; | ||
| + | context.getSource().sendFeedback(() -> Text.literal(" | ||
| + | return result; | ||
| + | })))); | ||
| </ | </ | ||
| - | 为拥有子命令,需要把下一个节点追加到已经存在的节点后面,这是利用 '' | + | 现在你可以输入一个或者两个整数了。如果给一个整数,会计算这个整数的平方。如果提供两个整数,会计算这两个整数的积。你可能发现,两次指定类似的执行内容有些不太必要。因此,我们可以创建一个在两个执行中都使用的方法。 |
| - | 如下所示,创建命令 '' | + | <code java> |
| + | public class ExampleMod implements ModInitializer { | ||
| + | @Override | ||
| + | public void onInitialize() { | ||
| + | CommandRegistrationCallback.EVENT.register((dispatcher, | ||
| + | .then(argument(" | ||
| + | .executes(context -> executeMultiply(IntegerArgumentType.getInteger(context, | ||
| + | .then(argument(" | ||
| + | .executes(context -> executeMultiply(IntegerArgumentType.getInteger(context, | ||
| + | } | ||
| - | <code java [enable_line_numbers=" | + | private static int executeMultiply(int value, int value2, CommandContext< |
| - | dispatcher.register(literal(" | + | final int result = value * value2; |
| - | | + | context.getSource().sendFeedback(() -> Text.literal(" |
| - | ); | + | return result; |
| + | } | ||
| + | } | ||
| </ | </ | ||
| - | 建议给命令添加节点时缩进你的代码,通常来说缩进对应了命令树中有多少节点的深度,每一次换行也可以看出添加了一个节点。本教程后面会展示格式化树状命令的几种可选样式。 | + | ===== 子命令 |
| - | **那就开始尝试运行命令** | + | 要添加子命令,你需要先照常注册第一个字面节点。 |
| - | 通常如果你在游戏内输入了 '' | + | < |
| + | dispatcher.register(literal(" | ||
| + | </code> | ||
| + | |||
| + | 为拥有子命令,需要把下一个节点追加到已经存在的节点后面。 | ||
| + | |||
| + | 如下所示,创建命令 '' | ||
| <code java [enable_line_numbers=" | <code java [enable_line_numbers=" | ||
| Line 197: | Line 244: | ||
| .executes(context -> { | .executes(context -> { | ||
| // 对于 1.19 以下的版本,使用 '' | // 对于 1.19 以下的版本,使用 '' | ||
| - | context.getSource().sendMessage(Text.literal(" | + | |
| + | | ||
| return 1; | return 1; | ||
| Line 205: | Line 253: | ||
| </ | </ | ||
| + | 建议给命令添加节点时缩进你的代码,通常来说缩进对应了命令树中有多少节点的深度,每一次换行也可以看出添加了一个节点。本教程后面会展示格式化树状命令的几种可选样式。 | ||
| + | |||
| + | 类似于参数,子命令节点也可以设置为可选的。在下面这个例子中,''/ | ||
| + | <code java [enable_line_numbers=" | ||
| + | dispatcher.register(literal(" | ||
| + | .executes(context -> { | ||
| + | context.getSource().sendFeedback(() -> Text.literal(" | ||
| + | return 1; | ||
| + | }) | ||
| + | .then(literal(" | ||
| + | .executes(context -> { | ||
| + | context.getSource().sendFeedback(() -> Text.literal(" | ||
| + | return 1; | ||
| + | }) | ||
| + | ) | ||
| + | ); | ||
| + | </ | ||
| ====== 高级概念 ====== | ====== 高级概念 ====== | ||
| Line 219: | Line 284: | ||
| ====== 常见问题 ====== | ====== 常见问题 ====== | ||
| - | ===== 命令为什么不编译 ===== | + | ===== 代码为什么不编译 ===== |
| + | 此问题可能有一些常见的原因。 | ||
| - | 有两种可能的原因。 | + | * **捕获或抛出 CommandSyntaxException:**'' |
| - | + | * **泛型问题:**你可能遇到了泛型问题。如果你在注册服务器命令(大多数情况都是如此),确保你在静态导入中使用 '' | |
| - | ==== 捕获或抛出 CommandSyntaxException | + | * **检查 '' |
| - | + | * **'' | |
| - | 这个问题的解决方法就是让 | + | |
| - | + | ||
| - | ==== 泛型问题 | + | |
| - | + | ||
| - | 你可能有时出现了泛型问题,请检查你的静态导入里面用的是不是 | + | |
| ===== 可以注册客户端命令吗? ===== | ===== 可以注册客户端命令吗? ===== | ||
| - | Fabric 有个 ClientCommandManager,可以注册客户端命令。 | + | Fabric |
| - | ===== 黑科技 ===== | + | <code java> |
| + | ClientCommandRegistrationCallback.EVENT.register((dispatcher, | ||
| + | .executes(context -> { | ||
| + | context.getSource().sendFeedback(Text.literal(" | ||
| + | return 1; | ||
| + | } | ||
| + | ))); | ||
| + | </ | ||
| - | 一些可行但是不推荐的做法: | + | 如果你需要在客户端命令执行过程中打开屏幕,不要直接调用 '' |
| - | ==== 可以运行时注册命令吗? ==== | + | ===== 可以运行时注册命令吗? |
| 可以这么做但是不推荐,你可以从服务器中获取 '' | 可以这么做但是不推荐,你可以从服务器中获取 '' | ||
| Line 245: | Line 313: | ||
| 然后你需要通过 '' | 然后你需要通过 '' | ||
| - | ==== 可以在运行时取消注册命令吗? ==== | + | ===== 可以在运行时取消注册命令吗? |
| 可以这么做,但是这更不稳定,并且可能造成未预料的副作用。为简化事情,你需要在 brigadier 中使用反射并移除这个节点,然后还需要再次使用 '' | 可以这么做,但是这更不稳定,并且可能造成未预料的副作用。为简化事情,你需要在 brigadier 中使用反射并移除这个节点,然后还需要再次使用 '' | ||
zh_cn/tutorial/commands.1700301435.txt.gz · Last modified: 2023/11/18 09:57 by solidblock