
这是原载于MCbbs论坛上的命令教程。随着论坛的消失,这系列教程经修缮(可能需要几天时间)后被迁移至此。
作者不保证对本教程的维护和更新(全随兴致),请您自行判断内容是否过时。不过,若有更多问题欢迎在评论区提出
教程声明:
系列教程默认读者是按照顺序阅读的
教程默认读者有对Minecraft的基础了解
教程主要注重基础原理,实践内容极少
本篇教程适用于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位玩家,把指令:
/team join @r red 运行5次就可以把五名玩家添加进红队(red)了......是吗?
选择器@r全称应该是“在所有玩家中随机选择一名”,那......如果重复运行上述指令,有可能重复选择。@r可能抽中已经加入了红队的玩家,这样就无法确定肯定有5名玩家在红队中。
如果你运气不好,甚至可能从始至终都抽中一人。
我们该如何以一种更精确的方式区分不同玩家?
容我介绍下面这一条指令——
标签/tag
这条指令可以为实体添加标签,并可以使用选择器参数来选择拥有特定标签的实体——
注意,本指令在Java1.12.2及以前,与基岩版中仍为/scoreboard命令的一部分。你可以前往Wiki获得相关信息
首先,让我们添加一个标签:
格式:
/tag <目标> add <名称> <名称>处填写一个任意英文字符串,只要你能分得清而且不重复就好。
举个例子:
/tag @r add choose 本指令会为一名随机玩家添加一个叫做choose的标签。
任何实体都可以插入数个(1024上限)不同的标签。
嗯嗯,你可能到这里看得有点迷糊,标签是干嘛用的?
你可以使用选择器参数来选择拥有特定标签的玩家。
@a 这是我们的选择器,选择所有玩家。
想要添加一个参数,紧接着它打上中括号“[]” 中括号内部打上你要的参数:
啊啊,翻译一下:
我们的选择标准是标签:tag
我们要选择的标签是前面添加的choose。
两者联起来就是“tag=choose”。
添加到选择器后的中括号内:
@a[tag=choose] 本选择器会选择所有带有choose标签的玩家
你当然可以使用其他选择器:
@r[tag=choose] 本选择器会从所有带有choose标签的玩家中选择一位
@p[tag=win] 本选择器会选择带有win标签的最近的玩家
把tag添加到以前讲过的指令中:
/kill @a 杀死所有玩家
/kill @a[tag=dead] 杀死所有带有dead标签的玩家(若你之前使用/tag ... add dead 添加过这个标签)
/scoreboard players add @r[tag=add] score 10 为一名带有add标签的随机玩家在score计分板上添加10分(如果存在)
/tp @e[tag=teleport] 0 0 0 将所有带有teleport标签的实体传送至世界中心(0,0,0)(如果存在)
所有用选择器的地方都可以使用选择器变量。
我应该讲明白了。
标签会持续保持在实体身上,直至被删除——
删除标签格式:
/tag <目标> remove <名称> 本指令可以删除一个dead标签:
/tag @p remove dead 删除最近的带有dead标签的玩家。
/tag @a[tag=delet] remove choose 将所有带有delet标签的玩家身上的choose标签移除。
接下来,如果你忘了自己添加过什么标签,可以使用list子指令:
/tag <目标> list 本指令会列出<目标>身上带有的所有标签。
那么,有了这种进阶的选择器,再回头看向原来的问题就很好解决了:
如何随机分队?
简单。
首先,为所有玩家加入choose标签:
/tag @a add choose 接下来,准备一个小空间,设置在一个离分队大厅比较远的地方,用于隔离正在被操作的玩家。
这个大厅......就放在坐标(0, 100, 0)上吧。
那么接下来,随机将一名带有choose标签的玩家从所有玩家身边传送至这个空间:
/tp @r[tag=choose] 0 100 0 接下来,在本房间内运行命令方块,内容为,将最近的玩家添加至红队:
/team join @p red 因为这名玩家已经被传送至这个空间,所以“@p”会选择是Ta——命令方块就在旁边嘛。
最后,把他的choose标签移除:
/tag @p remove choose 再传送回大厅:
/tp @p <x> <y> <z> "
由于这名玩家的choose标签已经被移除,就不再会被选择器“@r[tag=choose]”选中,也就不会出现重复的问题了。
重复运行上述指令5次,就可以获得五名随机的红队玩家了。
嗯......好麻烦啊......又得弄个独立空间,又要传送来传送去的......
当然,我们有简单的办法。
用一个标签来判定玩家有没有被选过实在是太麻烦了。有没有一种方法,或者说,一种选择器参数可以直接检测玩家有没有加入队伍,但不使用标签辅助?
看一下我们的选择器:
@r[tag=choose] @r,选择器,代表随机玩家
tag,选择器条件,是标签的意思,
choose,要检测的值,是我们自定的标签
现在,我们要改变的是选择器条件,也就是“tag”:
既然有tag=(标签=),当然也可以有其他等于,比如,team=(队伍=)。
换言之,我们筛选目标的条件不只有tag。游戏还提供了大量其他的条件可供选择:
通过队伍选择目标
除了通过标签选择玩家,还可以通过队伍选择玩家:
[team=<队伍>] 这个选择器会选取所有属于指定队伍的玩家:
@r[team=red] 随机选择一名红队玩家
如果不填“<队伍>”,会选择所有没有队伍的玩家:
@r[team=] 随机选择一名不属于任何队伍的玩家
也就是说,我们根本就用不上使用标签费尽力气地判断一名玩家是否拥有队伍,可以省去上面所有的关于独立小房间的步骤,只运行这一条指令5次就好了:
/team join @r[team=] red 将一个不属于任何队伍的随机玩家加入红队
怎么样?
反选
除此之外,游戏还提供反向选择:
你可以将“!”放在值的前面来表示它不成立:
@a[tag=abc]为所有拥有abc标签的玩家。
@a[tag=!abc]为所有没有abc标签的玩家。
@r[team=red]的含义是随机的红队玩家。
@r[team=!red]即为随机的非红队玩家。
所以在将随机5名玩家加入红队后,很简单的就可以把剩下的玩家通通加入蓝队了:
/team join @a[team=!red] blue 将所有不属于红队的玩家加入蓝队
这样简单多了哈。
但是......还是有一个麻烦的地方,就是我需要把 /team join @r[team=] red 运行五遍才能将五名玩家加入红队......那,我们不能直接用一条指令解决么?
这个问题实际上是,@r这个选择器只能随机选择1名玩家,我们有办法让它直接随机选择5名玩家么?
调整数量
当然可以。我们需要使用一个新的选择器参数(或者说选择条件):
最大数量:"limit"
这个选择器参数会更改选择器的默认人数(对于@a或@e减少,@r或@p或@n增加)。
@a[limit=3] 这个平常会选择所有玩家的@a如今只会选择3个玩家
@r[limit=5] 这个平常只随机抽选一人的@r,如今会随机选择5人
所以,这就简单多了,我们只需要直接随机选择5人加入红队就好了:
/team join @r[limit=5] red 将5个随机的玩家加入红队
limit=对@s是无效的哦!因为虽然@s在/execute指令中有可能,但“执行者本身”永远只有一人。
多个条件(与)
你也可以在同一时间使用多个参数。使用逗号“,”可以连接多个参数。此时必须所有参数都成立才符合要求:
@<选择器>[<参数>=<值>,<参数>=<值>,…] 比如:
@a[team=blue,tag=!dead] 选择所有蓝队的,没有dead标签的玩家
/kill @p[team=!,limit=3] 杀死最近的3名加入了任意队伍的玩家
(“team=”是指无队伍玩家,反转后的“team=!”也就是加入了任意队伍的玩家了。)
好,以上我们已经讲了三种参数了——队伍“team=”标签“tag=”数量“limit=”。但还有更多,我们要加快速度了。
通过分数选择目标
我们还可以使用以前讲过的记分板来选择目标:
@a[scores={<记分板ID>=<值>,...}] 本参数会选择所有在<记分板ID>上的分数符合<值>的玩家。
@a[scores={test=5}] 选择所有在记分板test上的分数为5的玩家
这里有一个很方便的事情就是,你可以用".."来表示一个范围的分数:
@e[scores={test=10..15}] 选择所有在记分板test上的分数为10到15之间(包含)的实体
你也可以在一侧留空来表示大于等于或小于等于:
@e[scores={test=12..}] 选择所有在记分板test上的分数大于等于12的实体
这里还有一个比较方便的地方,就是当你要同时判断多个记分板时:
@e[scores={test=5..10},scores={abc=7}] 这个分成了两个条件并以","相连的选择器可以被简化为这样:
@e[scores={test=5..10,abc=7}] 选择test分数5~10,且abc上分数等于7的所有实体
你可以在花括号中添加“,”连接不同条件来判断多个不同的记分板。
通过位置选择玩家
本参数可以选择位于特定坐标的玩家
有两种方法可以这么做。一来可以指定一个长方体判定区来判定目标的位置是否在其内,二来可以指定一个球体范围做同样的判定。、
两种都首先要指定一个基准点。
基准点是哪里?
额,就是,从哪里开始算。
我们有两种方法,一种是指定离基准点的距离,一种是指定一个对角形成长方体:
指定距离:
@a[x=<值>,y=<值>,z=<值>,distance=<值>] 其中,“x=”,“y=”,“z=”就是基准点的坐标,而“distance=”即是以基准点为中心,离基准点多远的目标:
@a[x=100,y=100,z=100,distance=10] 这个选择器会选择以基准点(100, 100, 100)为中心,精确地距离10格远的目标
distance同样适用范围选择:
@a[x=100,y=100,z=100,distance=4..9] 这个选择器会选择以基准点(100, 100, 100)为中心,距离4至9格远的目标
@a[x=100,y=100,z=100,distance=..5] 这个选择器会选择距离基准点(100, 100, 100)5格以内的目标
除此之外还可以进行体积选取
确定一个根据基准点向三维延伸的第二个坐标“dx,dy,dz”,并选择两个坐标所形成的长方体区域:
@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 这个选择器是可以选择除了其他玩家的生物的,但就麻烦在它是“选择所有实体”这个巨大的范围。
而本参数可以选择不同类型的实体:
[type=<实体类型>] “<实体类型>”需要填写任意一个实体的ID,比如creeper是苦力怕,那么:
@e[type=creeper] 本选择器会选择所有苦力怕
如果你不知道实体ID是什么的话,可以查找Wiki的这个页面
此外,你还可以使用标签(Tag)来选取所有处于该标签下的实体:
@e[type=#impact_projectiles] 选择所有弹射物
这包含了箭矢,雪球,火球,末影珍珠等所有弹射物。
注意!这个“标签”和上面的指令/tag的“标签”不是一个东西,别搞混!
排序
到这里我们可能有几个问题:
1. @a是所有玩家,但是如果加入了前面说的“limit=”,就会限制选择的玩家数量,比如“@a[limit=3]”最多只能选择3个玩家了——那么,这三个玩家是如何选择出来的?随机的?有某种规律?我们能否调整?
2. 如何选择一名随机的实体?@r是选择随机玩家,并能选择非玩家实体。
以上这两个疑问都可以使用“sort”来解决。
sort,即排序,可以决定“如何排序”选择的目标。
我们有4种选择:
sort=nearest: 靠近近者优先
@e[limit=1,sort=nearest] 选择最近的一名实体
@a[limit=2,sort=nearest] 选择最近的两名玩家
额,本选择器与“@p[limit=2]”是等价的。
sort=furthest 由远到近
@e[limit=2,sort=furthest] 选择最远的2名实体
sort=random 随机选择
@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
其他选择器
以下是一些不需要讲解,但为了完整性又必须放上来的选择器参数:
以下选择器均支持使用"!"。
指定目标的经验等级过滤目标(仅玩家)
[level=<值>] 注意,这是“经验等级”,等级。
@a[level=12] 选择所有经验12级的玩家
本选择器参数支持使用“..”作为范围:
@a[level=5..] 选择所有大于等于5级的玩家
通过游戏模式选择目标
我们还可以通过游戏模式选择目标——这种方式经常用来在地图里对付开创造作弊的熊孩子们。
[gamemode=<模式>] 选择所有处于指定游戏模式的玩家。
<模式>的值可以参考第三帖的内容。
这会自动过滤非玩家目标
@a[gamemode=creative] 选择所有创造模式的玩家
名称选择
[name=<ID>] 选择所有符合ID的目标
这是一个字符串,应当用双引号括起,但注意,这不是JSON。
@a[name=Steve] 选择所有叫Steve的玩家
通过旋转选择目标
[x_rotation=<值>]
[y_rotation=<值>] 这可以选择朝向指定方向的目标,关于如何填入数值,请去第2帖查阅/tp指令或这去找Wiki。
这里注意,有一个和你印象不符的事情是,y_rotation指的是“沿y旋转”,也就是水平旋转。x_rotation反而是仰角。
此选择器支持使用范围:
@e[y_rotation=0..90] 选择所有看向正南到正西的目标
@e[y_rotation=0..90,x_rotation=0] 选择所有看向正南到正西的,而且平视的目标
以上就是今天的全部内容了。
除了我们提到的选择器限制条件以外,还有类似于进度,NBT与谓词等选择器——这些我们会在讲到时再详细说