跳到主要内容

实体和玩家参数

本节描述的参数与可用于检索实体的参数有关。它们的主要用途是选择命令目标。 所有这些参数都接受实体选择器(@a@e@n 等)作为有效输入,但需要 minecraft.command.selector 权限才能 使用。特定的参数可能允许或禁止某些选择器。

由于选择器需要权限,建议在命令中添加 requires 语句:

.requires(ctx -> ctx.getSender().hasPermission("minecraft.command.selector"))

你可以在这里找到更多关于要求的信息。

Entity 参数

此参数在解析其返回的 EntitySelectorArgumentResolver 后,返回恰好一个实体的列表,不多也不少。可以安全地 调用 List#getFirst() 来检索该实体。你可以使用 ArgumentResolver#resolve(CommandSourceStack) 来解析它。

使用示例

public static LiteralCommandNode<CommandSourceStack> entityArgument() {
return Commands.literal("entityarg")
.then(Commands.argument("arg", ArgumentTypes.entity())
.executes(ctx -> {
final EntitySelectorArgumentResolver entitySelectorArgumentResolver = ctx.getArgument("arg", EntitySelectorArgumentResolver.class);
final List<Entity> entities = entitySelectorArgumentResolver.resolve(ctx.getSource());

ctx.getSource().getSender().sendRichMessage("找到 <green><entityname>",
Placeholder.component("entityname", entities.getFirst().name())
);

return Command.SINGLE_SUCCESS;
}))
.build();
}

游戏内预览

如果执行玩家没有 minecraft.command.selector 权限:

如果执行玩家有 minecraft.command.selector 权限:

Entities 参数

与单个实体参数相比,这个多实体参数接受任意数量的实体,最小实体数量为 1。它们同样可以使用 ArgumentResolver#resolve(CommandSourceStack) 来解析, 返回一个 List<Entity>

使用示例

public static LiteralCommandNode<CommandSourceStack> entitiesArgument() {
return Commands.literal("entitiesarg")
.then(Commands.argument("arg", ArgumentTypes.entities())
.executes(ctx -> {
final EntitySelectorArgumentResolver entitySelectorArgumentResolver = ctx.getArgument("arg", EntitySelectorArgumentResolver.class);
final List<Entity> entities = entitySelectorArgumentResolver.resolve(ctx.getSource());

final Component foundEntities = Component.join(JoinConfiguration.commas(true), entities.stream().map(Entity::name).toList());

ctx.getSource().getSender().sendRichMessage("找到 <green><entitynames>",
Placeholder.component("entitynames", foundEntities)
);

return Command.SINGLE_SUCCESS;
}))
.build();
}

游戏内预览

Player 参数

player 参数允许为玩家参数检索 PlayerSelectorArgumentResolver。 对于这个"单个玩家"参数,你可以通过运行 PlayerSelectorArgumentResolver.resolve(ctx.getSource()).getFirst() 安全地获取目标玩家, 它返回一个 Player 对象。

使用示例

这个命令会将目标玩家抛向空中!

public static LiteralCommandNode<CommandSourceStack> playerArgument() {
return Commands.literal("player")
.then(Commands.argument("target", ArgumentTypes.player())
.executes(ctx -> {
final PlayerSelectorArgumentResolver targetResolver = ctx.getArgument("target", PlayerSelectorArgumentResolver.class);
final Player target = targetResolver.resolve(ctx.getSource()).getFirst();

target.setVelocity(new Vector(0, 100, 0));
target.sendRichMessage("<rainbow>起飞!!!");

ctx.getSource().getSender().sendRichMessage("将 <target> 抛向天空!",
Placeholder.component("target", target.name())
);
return Command.SINGLE_SUCCESS;
}))
.build();
}

游戏内预览

Players 参数

"多玩家"参数的工作方式与"单个玩家"参数类似,也返回一个 PlayerSelectorArgumentResolver。不同的是,它不仅仅解析为一个 Player,而是 可以解析为多个玩家 - 在使用此参数时应该考虑到这一点。PlayerSelectorArgumentResolver.resolve(ctx.getSource()) 返回一个 List<Player>,你可以直接遍历它。

使用示例

扩展"单个玩家"抛掷命令以支持多个目标可以这样写:

public static LiteralCommandNode<CommandSourceStack> playersArgument() {
return Commands.literal("players")
.then(Commands.argument("targets", ArgumentTypes.players())
.executes(ctx -> {
final PlayerSelectorArgumentResolver targetResolver = ctx.getArgument("targets", PlayerSelectorArgumentResolver.class);
final List<Player> targets = targetResolver.resolve(ctx.getSource());
final CommandSender sender = ctx.getSource().getSender();

for (final Player target : targets) {
target.setVelocity(new Vector(0, 100, 0));
target.sendRichMessage("<rainbow>起飞!!!");

sender.sendRichMessage("将 <target> 抛向天空!",
Placeholder.component("target", target.name())
);
}
return Command.SINGLE_SUCCESS;
}))
.build();
}

游戏内预览

Player profiles 参数

player profiles 参数是一个非常强大的参数,可以检索离线和在线玩家。它将参数的结果作为 PlayerProfileListResolver 返回, 解析为 Collection<PlayerProfile>。可以遍历此集合以获取结果配置文件。通常,如果通过名称检索玩家,它只返回一个 PlayerProfile, 但如果使用实体选择器(如在线玩家的 @a),它可以返回多个。因此,最好在集合中的所有条目上运行你想要运行的操作,而不是只在第一个条目上运行。

此参数将调用 Mojang 服务器的 API 来检索从未加入服务器的玩家信息。由于这个操作有时 需要较长时间,建议在异步上下文中解析此参数,以避免造成服务器延迟。

有时,这些 API 调用可能会失败。这在下面的游戏内预览中也可以看到。这种行为也是 /whitelist add 有时失败的原因。

使用示例 - 玩家查找命令

public static LiteralCommandNode<CommandSourceStack> playerProfilesArgument() {
return Commands.literal("lookup")
.then(Commands.argument("profile", ArgumentTypes.playerProfiles())
.executes(ctx -> {
final PlayerProfileListResolver profilesResolver = ctx.getArgument("profile", PlayerProfileListResolver.class);
final Collection<PlayerProfile> foundProfiles = profilesResolver.resolve(ctx.getSource());

for (final PlayerProfile profile : foundProfiles) {
ctx.getSource().getSender().sendPlainMessage("找到 " + profile.getName());
}

return Command.SINGLE_SUCCESS;
}))
.build();
}

游戏内预览