MC命令教程“真”从零开始 (六) /tag指令,与进阶选择器参数
Dahesor
2024年05月30日 10:19
收录于文集
共16篇

这是原载于MCbbs论坛上的命令教程。随着论坛的消失,这系列教程经修缮(可能需要几天时间)后被迁移至此。

作者不保证对本教程的维护和更新(全随兴致),请您自行判断内容是否过时。不过,若有更多问题欢迎在评论区提出

教程声明:

  1. 系列教程默认读者是按照顺序阅读的

  2. 教程默认读者有对Minecraft的基础了解

  3. 教程主要注重基础原理,实践内容极少

  4. 本篇教程适用于Java 1.20.4,但大部分内容也适用于1.13+


前言

我们的指令教程已经有了5篇了。

但是,在前5篇中,你可能一直在冒出关于选择器的的疑问。

喂,别告诉我你忘了什么是选择器,那个在第一帖就讲了。

我们当前接触到的选择器只有六种*:@a(选择所有玩家)@p(选择最近玩家)@r(选择随机玩家)@e(选择所有实体)@n(选择最近实体)@s(选择执行者)

好像够用了?

好吧,一点都不够用。

仅仅使用上面5个选择器,我们无法选择单一一只苦力怕,不知道如何选择处于特定位置的玩家——一点都不够用。

所以今天,我们就来探讨一下——如何更精确的选择?

这就是本帖的内容——选择器参数(Selector parameter)

*教育版的选择器不考虑在内

参考:Minecraft:目标选择器 (https://zh.minecraft.wiki/w/%E7%9B%AE%E6%A0%87%E9%80%89%E6%8B%A9%E5%99%A8)

Bilibili Wiki镜像:目标选择器​

标签 /tag

让我们从一个实例开始:

随机分队

第4帖我们讲了队伍指令,相信你已经......有一些队伍竞技地图的构思了吧!

那,今天的问题就是,如何,随机的,把玩家添加至数个不同的队伍中?

假设,我们有10个玩家进行随机分队,分成红蓝两队,每队5人——你该怎么办?

找一下上方的选择器,涉及到随机的是@r(选择1个随机玩家)。

看起来我们是要用这个选择器喽!

不错嘛,10位玩家,把指令:

代码块
HTML
自动换行
复制代码
/team join @r red 
复制成功

运行5次就可以把五名玩家添加进红队(red)了......是吗?

选择器@r全称应该是“在所有玩家中随机选择一名”,那......如果重复运行上述指令,有可能重复选择。@r可能抽中已经加入了红队的玩家,这样就无法确定肯定有5名玩家在红队中。

如果你运气不好,甚至可能从始至终都抽中一人。

我们该如何以一种更精确的方式区分不同玩家?

容我介绍下面这一条指令——

标签/tag

这条指令可以为实体添加标签,并可以使用选择器参数来选择拥有特定标签的实体——

注意,本指令在Java1.12.2及以前,与基岩版中仍为/scoreboard命令的一部分。你可以前往Wiki获得相关信息​

首先,让我们添加一个标签:

格式:

代码块
HTML
自动换行
复制代码
/tag <目标> add <名称>
复制成功

<名称>处填写一个任意英文字符串,只要你能分得清而且不重复就好。

举个例子:

代码块
HTML
自动换行
复制代码
/tag @r add choose
复制成功

本指令会为一名随机玩家添加一个叫做choose的标签。

任何实体都可以插入数个(1024上限)不同的标签。

嗯嗯,你可能到这里看得有点迷糊,标签是干嘛用的?

你可以使用选择器参数来选择拥有特定标签的玩家。

代码块
HTML
自动换行
复制代码
@a
复制成功

这是我们的选择器,选择所有玩家。

想要添加一个参数,紧接着它打上中括号“[]” 中括号内部打上你要的参数:

啊啊,翻译一下:

我们的选择标准是标签:tag

我们要选择的标签是前面添加的choose。

两者联起来就是“tag=choose”。

添加到选择器后的中括号内:

代码块
HTML
自动换行
复制代码
@a[tag=choose]
复制成功

本选择器会选择所有带有choose标签的玩家

你当然可以使用其他选择器:

代码块
HTML
自动换行
复制代码
@r[tag=choose]
复制成功

本选择器会从所有带有choose标签的玩家中选择一位

代码块
HTML
自动换行
复制代码
@p[tag=win]
复制成功

本选择器会选择带有win标签的最近的玩家

把tag添加到以前讲过的指令中:

代码块
HTML
自动换行
复制代码
/kill @a
复制成功

杀死所有玩家

代码块
HTML
自动换行
复制代码
/kill @a[tag=dead]
复制成功

杀死所有带有dead标签的玩家(若你之前使用/tag ... add dead 添加过这个标签)

代码块
HTML
自动换行
复制代码
/scoreboard players add @r[tag=add] score 10
复制成功

为一名带有add标签的随机玩家在score计分板上添加10分(如果存在)

代码块
HTML
自动换行
复制代码
/tp @e[tag=teleport] 0 0 0
复制成功

将所有带有teleport标签的实体传送至世界中心(0,0,0)(如果存在)

所有用选择器的地方都可以使用选择器变量。

我应该讲明白了。

标签会持续保持在实体身上,直至被删除——

删除标签格式:

代码块
HTML
自动换行
复制代码
/tag <目标> remove <名称>
复制成功

本指令可以删除一个dead标签:

代码块
HTML
自动换行
复制代码
/tag @p remove dead
复制成功

删除最近的带有dead标签的玩家。

代码块
HTML
自动换行
复制代码
/tag @a[tag=delet] remove choose
复制成功

将所有带有delet标签的玩家身上的choose标签移除。

接下来,如果你忘了自己添加过什么标签,可以使用list子指令:

代码块
HTML
自动换行
复制代码
/tag <目标> list
复制成功

本指令会列出<目标>身上带有的所有标签。

那么,有了这种进阶的选择器,再回头看向原来的问题就很好解决了:

如何随机分队?

简单。

首先,为所有玩家加入choose标签:

代码块
HTML
自动换行
复制代码
/tag @a add choose
复制成功

接下来,准备一个小空间,设置在一个离分队大厅比较远的地方,用于隔离正在被操作的玩家。

这个大厅......就放在坐标(0, 100, 0)上吧。

那么接下来,随机将一名带有choose标签的玩家从所有玩家身边传送至这个空间:

代码块
HTML
自动换行
复制代码
/tp @r[tag=choose] 0 100 0
复制成功

接下来,在本房间内运行命令方块,内容为,将最近的玩家添加至红队:

代码块
HTML
自动换行
复制代码
/team join @p red
复制成功

因为这名玩家已经被传送至这个空间,所以“@p”会选择是Ta——命令方块就在旁边嘛。

最后,把他的choose标签移除:

代码块
HTML
自动换行
复制代码
/tag @p remove choose
复制成功

再传送回大厅:

代码块
HTML
自动换行
复制代码
/tp @p <x> <y> <z>
复制成功

"

由于这名玩家的choose标签已经被移除,就不再会被选择器“@r[tag=choose]”选中,也就不会出现重复的问题了。

重复运行上述指令5次,就可以获得五名随机的红队玩家了。

嗯......好麻烦啊......又得弄个独立空间,又要传送来传送去的......

当然,我们有简单的办法。

用一个标签来判定玩家有没有被选过实在是太麻烦了。有没有一种方法,或者说,一种选择器参数可以直接检测玩家有没有加入队伍,但不使用标签辅助?

看一下我们的选择器:

代码块
HTML
自动换行
复制代码
@r[tag=choose]
复制成功

@r,选择器,代表随机玩家

tag,选择器条件,是标签的意思,

choose,要检测的值,是我们自定的标签

现在,我们要改变的是选择器条件,也就是“tag”:

既然有tag=(标签=),当然也可以有其他等于,比如,team=(队伍=)。

换言之,我们筛选目标的条件不只有tag。游戏还提供了大量其他的条件可供选择:

通过队伍选择目标

除了通过标签选择玩家,还可以通过队伍选择玩家:

代码块
HTML
自动换行
复制代码
[team=<队伍>]
复制成功

这个选择器会选取所有属于指定队伍的玩家:

代码块
HTML
自动换行
复制代码
@r[team=red]
复制成功

随机选择一名红队玩家

如果不填“<队伍>”,会选择所有没有队伍的玩家:

代码块
HTML
自动换行
复制代码
@r[team=]
复制成功

随机选择一名不属于任何队伍的玩家

也就是说,我们根本就用不上使用标签费尽力气地判断一名玩家是否拥有队伍,可以省去上面所有的关于独立小房间的步骤,只运行这一条指令5次就好了:

代码块
JavaScript
自动换行
复制代码
/team join @r[team=] red
复制成功

将一个不属于任何队伍的随机玩家加入红队

怎么样?

反选

除此之外,游戏还提供反向选择:

你可以将“!”放在值的前面来表示它不成立:

  • @a[tag=abc]为所有拥有abc标签的玩家。

  • @a[tag=!abc]为所有没有abc标签的玩家。

  • @r[team=red]的含义是随机的红队玩家。

  • @r[team=!red]即为随机的非红队玩家。

所以在将随机5名玩家加入红队后,很简单的就可以把剩下的玩家通通加入蓝队了:

代码块
HTML
自动换行
复制代码
/team join @a[team=!red] blue
复制成功

将所有不属于红队的玩家加入蓝队

这样简单多了哈。

但是......还是有一个麻烦的地方,就是我需要把 /team join @r[team=] red 运行五遍才能将五名玩家加入红队......那,我们不能直接用一条指令解决么?

这个问题实际上是,@r这个选择器只能随机选择1名玩家,我们有办法让它直接随机选择5名玩家么?

调整数量

当然可以。我们需要使用一个新的选择器参数(或者说选择条件):

最大数量:"limit"

这个选择器参数会更改选择器的默认人数(对于@a或@e减少,@r或@p或@n增加)。

代码块
HTML
自动换行
复制代码
@a[limit=3]
复制成功

这个平常会选择所有玩家的@a如今只会选择3个玩家

代码块
HTML
自动换行
复制代码
@r[limit=5]
复制成功

这个平常只随机抽选一人的@r,如今会随机选择5人

所以,这就简单多了,我们只需要直接随机选择5人加入红队就好了:

代码块
HTML
自动换行
复制代码
/team join @r[limit=5] red
复制成功

将5个随机的玩家加入红队

limit=对@s是无效的哦!因为虽然@s在/execute指令中有可能,但“执行者本身”永远只有一人。

多个条件(与)

你也可以在同一时间使用多个参数。使用逗号“,”可以连接多个参数。此时必须所有参数都成立才符合要求:

代码块
HTML
自动换行
复制代码
@<选择器>[<参数>=<值>,<参数>=<值>,…]
复制成功

比如:

代码块
HTML
自动换行
复制代码
@a[team=blue,tag=!dead]
复制成功

选择所有蓝队的,没有dead标签的玩家

代码块
HTML
自动换行
复制代码
/kill @p[team=!,limit=3]
复制成功

杀死最近的3名加入了任意队伍的玩家

(“team=”是指无队伍玩家,反转后的“team=!”也就是加入了任意队伍的玩家了。)

好,以上我们已经讲了三种参数了——队伍“team=”标签“tag=”数量“limit=”。但还有更多,我们要加快速度了。

通过分数选择目标

我们还可以使用以前讲过的记分板来选择目标:

代码块
HTML
自动换行
复制代码
@a[scores={<记分板ID>=<值>,...}]
复制成功

本参数会选择所有在<记分板ID>上的分数符合<值>的玩家。

代码块
HTML
自动换行
复制代码
@a[scores={test=5}]
复制成功

选择所有在记分板test上的分数为5的玩家

这里有一个很方便的事情就是,你可以用".."来表示一个范围的分数:

代码块
HTML
自动换行
复制代码
@e[scores={test=10..15}]
复制成功

选择所有在记分板test上的分数为10到15之间(包含)的实体

你也可以在一侧留空来表示大于等于或小于等于:

代码块
HTML
自动换行
复制代码
@e[scores={test=12..}]
复制成功

选择所有在记分板test上的分数大于等于12的实体

这里还有一个比较方便的地方,就是当你要同时判断多个记分板时:

代码块
HTML
自动换行
复制代码
@e[scores={test=5..10},scores={abc=7}]
复制成功

这个分成了两个条件并以","相连的选择器可以被简化为这样:

代码块
HTML
自动换行
复制代码
@e[scores={test=5..10,abc=7}]
复制成功

选择test分数5~10,且abc上分数等于7的所有实体

你可以在花括号中添加“,”连接不同条件来判断多个不同的记分板。

通过位置选择玩家

本参数可以选择位于特定坐标的玩家

有两种方法可以这么做。一来可以指定一个长方体判定区来判定目标的位置是否在其内,二来可以指定一个球体范围做同样的判定。、

两种都首先要指定一个基准点。

基准点是哪里?

额,就是,从哪里开始算。

我们有两种方法,一种是指定离基准点的距离,一种是指定一个对角形成长方体:

指定距离:

代码块
HTML
自动换行
复制代码
@a[x=<值>,y=<值>,z=<值>,distance=<值>]
复制成功

其中,“x=”,“y=”,“z=”就是基准点的坐标,而“distance=”即是以基准点为中心,离基准点多远的目标:

代码块
HTML
自动换行
复制代码
@a[x=100,y=100,z=100,distance=10]
复制成功

这个选择器会选择以基准点(100, 100, 100)为中心,精确地距离10格远的目标

distance同样适用范围选择:

代码块
HTML
自动换行
复制代码
@a[x=100,y=100,z=100,distance=4..9]
复制成功

这个选择器会选择以基准点(100, 100, 100)为中心,距离4至9格远的目标

代码块
HTML
自动换行
复制代码
@a[x=100,y=100,z=100,distance=..5]
复制成功

这个选择器会选择距离基准点(100, 100, 100)5格以内的目标

除此之外还可以进行体积选取

确定一个根据基准点向三维延伸的第二个坐标“dx,dy,dz”,并选择两个坐标所形成的长方体区域:

代码块
HTML
自动换行
复制代码
@a[x=100, y=100,z=100,dx=10,dy=-5,dz=5]
复制成功

这会选择两个点,基准点(100,100,100)与经过延伸后的目标点(100+10,100-5,100+5)之间的长方体内的目标。

是不是看糊涂了?

一般来说这种时候后面肯定有图:

这样,图中画的就是@a[x=100,y=100,z=100,dx=10,dy=-5,dz=5]的选择区域。

通过类型选择实体

@e 这个选择器是可以选择除了其他玩家的生物的,但就麻烦在它是“选择所有实体”这个巨大的范围。

而本参数可以选择不同类型的实体:

代码块
HTML
自动换行
复制代码
[type=<实体类型>]
复制成功

“<实体类型>”需要填写任意一个实体的ID,比如creeper是苦力怕,那么:

代码块
HTML
自动换行
复制代码
@e[type=creeper]
复制成功

本选择器会选择所有苦力怕

如果你不知道实体ID是什么的话,可以查找Wiki的这个页面​

此外,你还可以使用标签(Tag)来选取所有处于该标签下的实体:

代码块
HTML
自动换行
复制代码
@e[type=#impact_projectiles]
复制成功

选择所有弹射物

这包含了箭矢,雪球,火球,末影珍珠等所有弹射物。

在这里寻找标签列表​

注意!这个“标签”和上面的指令/tag的“标签”不是一个东西,别搞混!

排序

到这里我们可能有几个问题:

1. @a是所有玩家,但是如果加入了前面说的“limit=”,就会限制选择的玩家数量,比如“@a[limit=3]”最多只能选择3个玩家了——那么,这三个玩家是如何选择出来的?随机的?有某种规律?我们能否调整?

2. 如何选择一名随机的实体?@r是选择随机玩家,并能选择非玩家实体。

以上这两个疑问都可以使用“sort”来解决。

sort,即排序,可以决定“如何排序”选择的目标。

我们有4种选择:

sort=nearest: 靠近近者优先

代码块
HTML
自动换行
复制代码
@e[limit=1,sort=nearest]
复制成功

选择最近的一名实体

代码块
HTML
自动换行
复制代码
@a[limit=2,sort=nearest]
复制成功

选择最近的两名玩家

额,本选择器与“@p[limit=2]”是等价的。

sort=furthest  由远到近

代码块
HTML
自动换行
复制代码
@e[limit=2,sort=furthest]
复制成功

选择最远的2名实体

sort=random 随机选择

代码块
HTML
自动换行
复制代码
@e[limit=3,sort=random,type=creeper]
复制成功

选择随机的3只苦力怕

sort=arbitrary 不排序

也就是@a与@e的默认情况。

这个参数没有啥用:

@r[limit=3,sort=arbitrary] 与 @a[limit=3] 是等价的

注:@p,@r,@n,@s已经有内置的排序规则,不可以使用sort覆盖

注:现在已经无法直接在@r上使用type=来指定类型。@r只能指定玩家。必须使用@e配合sort=random

其他选择器

以下是一些不需要讲解,但为了完整性又必须放上来的选择器参数:

以下选择器均支持使用"!"。

指定目标的经验等级过滤目标(仅玩家)

代码块
HTML
自动换行
复制代码
[level=<值>]
复制成功

注意,这是“经验等级”,等级。

代码块
HTML
自动换行
复制代码
@a[level=12]
复制成功

选择所有经验12级的玩家

本选择器参数支持使用“..”作为范围:

代码块
HTML
自动换行
复制代码
@a[level=5..]
复制成功

选择所有大于等于5级的玩家

通过游戏模式选择目标

我们还可以通过游戏模式选择目标——这种方式经常用来在地图里对付开创造作弊的熊孩子们。

代码块
HTML
自动换行
复制代码
[gamemode=<模式>]
复制成功

选择所有处于指定游戏模式的玩家。‌‌

<模式>的值可以参考第三帖的内容。‌‌

这会自动过滤非玩家目标

代码块
HTML
自动换行
复制代码
@a[gamemode=creative]‌‌
复制成功

选择所有创造模式的玩家

名称选择

代码块
HTML
自动换行
复制代码
[name=<ID>]
复制成功

选择所有符合ID的目标

这是一个字符串,应当用双引号括起,但注意,这不是JSON。

代码块
HTML
自动换行
复制代码
@a[name=Steve]
复制成功

选择所有叫Steve的玩家

通过旋转选择目标

代码块
HTML
自动换行
复制代码
[x_rotation=<值>]

[y_rotation=<值>]
复制成功

这可以选择朝向指定方向的目标,关于如何填入数值,请去第2帖查阅/tp指令或这去找Wiki。

这里注意,有一个和你印象不符的事情是,y_rotation指的是“沿y旋转”,也就是水平旋转。x_rotation反而是仰角。

此选择器支持使用范围:

代码块
HTML
自动换行
复制代码
@e[y_rotation=0..90]
复制成功

选择所有看向正南到正西的目标

代码块
HTML
自动换行
复制代码
@e[y_rotation=0..90,x_rotation=0]
复制成功

选择所有看向正南到正西的,而且平视的目标

以上就是今天的全部内容了。

除了我们提到的选择器限制条件以外,还有类似于进度,NBT与谓词等选择器——这些我们会在讲到时再详细说