实体和玩家参数
本节描述的参数与可用于检索实体的参数有关。它们的主要用途是选择命令目标。
所有这些参数都接受实体选择器(@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();
}