对初次接触命令的玩家来说,基础概念无疑是最重要,但又最难找到教程的一部分。
在这里,我们将会介绍几个非常重要的基础概念:
- 坐标、朝向、区块
- 时间、顺序
- 命令执行
- 实体选择器
- 命令执行统计
坐标(Coordinate)
坐标为三个数字,定义了物件在当前世界内的位置。该三数值分别为x、y、z数值,分别代表物件在x、y、z轴上离参照点(Reference point)的距离,单位为米,即一般方块的长、宽、高的数值。
- x轴为东(+)西(-)。
- y轴为上(+)下(-)。
- z轴为南(+)北(-)。
绝对坐标(Absolute coordinate)
绝对坐标的参照点为游戏的原点,即(0,0,0)。
一般不特别指明的情况下都为绝对坐标、主世界。
游戏内点击F3后出现的调试界面会显示玩家当前的绝对坐标(注意是脚的坐标)、朝向等资料,对地图制作十分有用。
一般地图内的定位大多用绝对坐标,因为我们清楚所有东西的坐标,使用相对坐标则需要新的参照点并且需要一些计算,比较麻烦。
然而能够在多个地图内使用的模块则甚少使用绝对坐标,因为我们不清楚当前坐标的绝对坐标(命令没法轻易获得此数值,即使能获取也无法将它便捷地用在其他命令中)。在这情况下,我们会以某个实体为参照点,使用相对坐标。
相对坐标(Relative coordinate)
相对坐标就是相对于某个点的坐标。表达相对坐标的符号为 ~ (如~3就是+3,~就是没有变化)。比如(~5 ~ ~-3)就是某个点的(x+5, y, z-3)的位置。
相对坐标可以与绝对坐标一起使用, 比如原点为(5,5,5),坐标(~5 20 ~-3)换为绝对坐标就是(10 20 2)
相对坐标在大部分命令都充当着一个很重要的角色, 因为很多时候我们会希望对目标相对位置进行操作, 比如在玩家上方放置方块。(有时候我们也会使用绝对的Y坐标,因为Y坐标的数值有其独特含义,如64代表的是海平面的高度。相比之下我们X, Z绝对坐标的意义就不大。)
方块坐标(Block coordinate)相对坐标的原点=执行点?
(对于执行点的概念请参见章节1.3:命令执行)
在大多数使用相对坐标的情况下,是的。很大部分相对坐标是相对于执行坐标的。
然而有两个例外: tp 命令及 execute 命令。
tp 命令的其中一个格式: tp <被传送实体> <x> <y> <z> ,中的(x, y, z),原点为被传送实体的当前坐标,而不是执行点。
execute 命令的格式: execute <实体> <x1> <y1> <z1> <com mand>及 execute <实体> <x1> <y1> <z1> detect <x2> <y2> <z2> <block> <data value|block state> <command> ,中的(x1, y1, z1)以选择到的实体的坐标为原点,(x2, y2, z2)以 (x1, y1, z1) 的坐标为原点。
不过,在实际的使用情况上,除非是 tp 或 execute 命令,否则都是相对于执行坐标了。
我们常见的坐标是精确的,可以出现小数的。然而,对于方块我们并不需要那么精确,只需要到整数便可。
这便是方块坐标了。
方块坐标换为普通的坐标就是每个数值+0.5。
如(1, 2, 3)的普通坐标就是(1.5, 2.5, 3.5)。
部分命令会把坐标视为方块坐标(如果没有填写小数的话),如tp命令。
输入命令的坐标参数时,按tab就可以补全指针指着的方块的相应坐标(看你现在输入的是x, y还是z),令输入fill或clone等命令变得更加方便。(起码你不用烦着计算坐标)普通坐标的整数就是方块之间的边界。
世界
坐标体系不包括世界的参数,也就是说,我们没法在主世界里指定地狱里的东西,没法在地狱里指定主世界的东西等(不通过 execute 命令的话)。
而 tp 等命令也没法做到跨世界的传送。故此处理跨世界的问题时需要小心。
一般我们说的坐标都是说主世界,很少说别的世界的。
朝向(Facing)
Minecraft里的朝向都是以角度为单位。可以填写负数角度。
朝向分为两个: rx, ry。
rx即平面上的转轴,垂直于当前玩家的朝向。也就是说这角度决定了玩家看向上、看向前还是看向下的。
-90就是向上,0就是看向正前方,90就是向下。
ry即垂直的转轴,这决定了平面的朝向。这比较难以描述,还是直接上图就好。
区块(Chunk)值得一提的是,MC无法直接取得面向的前方的坐标,如果要做到这功能的话只能靠一些黑科技或枚举(穷举,enumerating)
区块是Minecraft世界的组成部分。每个区块的大小为16*256*16,长16格,宽16格,高256格(y=0到y=255)。
当你所在坐标(普通坐标)的 x或z mod16=0(mod为取余),你就是在区块的边缘上了。
方块的话。如果方块任意一个坐标数值 mod16= 0 或 15,就是贴近着区块边缘。
除了这个方法以外, 你还可以按下F3 + G, 这会显示区块边缘, 再按一次F3 + G就能关闭。
出生区块(Spawn chunk)
出生区块在服务器/游戏运行时会被加载。如果某区块的中心距离世界出生点距离(任意一条轴的距离,不是实际距离)小于等于128格,那么它就会被加载。所以一般加载范围是16*16个区块,也有可能是17*17(如果出生点刚好在区块中心)
可以通过/setworldspawn指令来更改世界出生点,以更改出生区块。然而需要知道的是,那个出生区块更改出生区块后需要玩家经过至少一次才会开始加载。
区块加载、卸载(load, unload)
除了出生区块以外,预设玩家附近21*21的区块会被加载(10个区块的内圆半径),然而这可以调整,内圆半径可以从3(附近7*7的区块会被加载)到15(附近31*31的区块会被加载)。其他世界的区块在没有玩家存在时是不会被加载的。
当区块不被加载,就不能通过命令直接在那个区块放置方块,同时那个区块的一切都处于暂停的状态,区块中的实体也会被视作不存在,直至该区块被加载(tp到那里的实体会等待一段时间才会被卸载)。
当区块不符合加载的条件,它会等一段时间之后才会不被加载(卸载),而不是即时的。这时间也不是固定的,大概是几十秒左右,所以一段时间就需要用特殊的方法来加载区块一次来避免它里面的东西不能正常使用。
常用区块加载方法
- spreadplayers 命令
当需要加载目的区块的时候就向该区块中的一个坐标 spreadplayer ,这样便可以把目的区块加载一段短时间。
这也是最常用的方法,因为这个并不需要先前让那个区块被加载才能使用,而且是最有弹性的,不会被坐标什么的局限。
然而如果需要长时间加载区块,那么就不建议使用这个,因为可能会不稳定。(无论任何情况也不建议需要长久加载非出生区块的区块)
这个方法不需要得知目的地的绝对坐标, 然而目的地必须有方块让传送的实体到达, 不然就会因为 spreadplayer 无法完成实体扩散而失败。 - 结构方块
结构方块放置结构时会短暂加载目标区块一段时间,只需要弄一个非常大的结构文件放置一大堆空气,然后放置到目标区块,但设置"结构完整性"(integrity)为0.0,这样就不会放置任何方块,但也会加载目标区块。
问题是这个方式需要在加载中的区块使用(因为不能在被卸下的区块放置方块),与目标区域之间的距离难以确定,因此不常使用。
时间
游戏里有两种可量度的时间: 现实时间及游戏刻。(所谓的微观延迟不可量度,而且其实就是顺序而已)
现实时间
现实时间就不用多说了,就是时、分、秒,相信大家都十分熟悉了。
然而在游戏里使用时分秒的东西真的不多,主要是因为游戏内的时间未必与现实世界同步(由于卡顿的缘故),因为游戏内的时间单位为游戏刻。
游戏刻额外知识:获取现实过去的时间
worldborder 里的时间参数是真·时间参数,以现实时间计算的。
因此我们可以通过设置长时间、大长度改变,然后以 stats 及 worldborder get 获取边界的直径,以计算过去了的时间。
游戏刻(game tick, 简写: gt)是游戏的基础时间单位。游戏会在1刻里做很多事情,如执行命令、进行一部分红石元件的更新等。一部分事情是马上进行的,如结构方块(Structure block)复制方块,或是删除实体等。
然而也有部分操作需要等待下一游戏刻才可见效,如骑乘实体的位置改变。因为游戏把那些操作放进了一个列表,我们通常称作NTE(Next Tick Entry),等待游戏刻开始/结束时的某个时段执行。所以我们对一些和实体、方块相关的更新需要特别留意,因为它们可能是需要1gt才能见效的,在同一gt进行重复性的操作是无意义的。
一般情况下是每秒20个游戏刻(最多20,可以更少),所以一般来说1游戏刻就是0.05秒(最短0.05秒)。
然而,如果电脑无法保持这个速度,每游戏刻的时间就可能延长。由于很多东西都是使用游戏刻来计算时间,所以如果游戏刻减慢,很多东西需要的时间会延长,而这也是大型命令系统中常见的卡顿。
假如1个游戏刻达到了1分钟的长度(当服务器配置不足以运行那么多命令/那命令需要的计算太多的时候可能出现), 服务器一般会崩溃。因此请注意别玩得太过。
顺序
即使是同一游戏刻执行命令,也不可能是真正的同时的。故此执行的先后次序十分重要。命令的先后次序对效果有非常大的影响。
举个例子:
- A: 先说出自己的分数,然后让自己的分数+1
- B: 先让自己的分数+1,然后说出自己的分数
假设一开始的分数为x,A的输出为x,B的输出为x+1。
故此,确定命令执行前后是十分重要的。
不肯定执行顺序的时候可以用say命令输出不同数字,通过那些数字推断执行顺序。
这是大型系统常见的一个问题,因为设计大型系统时模块执行的先后次序或许会被忽略,导致问题的发生。
命令命令就是一条文字,通过让游戏运行这条文字来执行不同的功能、操作。命令有不同参数,也就是可以改变的地方,决定了命令执行的结果,如把东西传送到什么地方、在玩家聊天栏显示什么文字等等。本文只讨论原版(无Mod无插件)、单人模式可以执行、权限等级为2的命令
根据命令的功能,我们可以大致分为几类:
- 只影响玩家的
- 影响实体的(无论能不能影响玩家)
- 影响方块的
- 显示的(只有玩家能看见、听见,不影响游戏内任何东西的)
- 记分板及检测类
- 其他(其他的几乎都自成一体系)
执行者部分命令同时属于几类,如replaceitem能影响实体及方块实体(block-entity)
本文将不会说明所有命令的用法,只会在例子中对使用的命令作出简单介绍,详细说明请见 https://minecraft.gamepedia.com/Commands (英文版,有能力者建议阅读英文版)或 https://minecraft-zh.gamepedia.com/%E5%91%BD%E4%BB%A4 (中文版,部分内容较过时)
执行者就是执行那段命令的物件,分别有几种情况:
- 管理员执行命令(于聊天栏直接输入执行或聊天信息、书本的clickEvent),执行者为管理员自己(玩家)
- 服主于后台执行命令,即服务器执行命令,执行者为服务器(非方块非实体,权限等级为4,坐标为(0, 0, 0),即能执行所有命令)
- 玩家点击牌子执行命令,执行者为玩家,权限为2(不论点击者权限为多少)
- 命令方块执行命令,执行者为命令方块(方块)。
- execute 让实体执行后方的命令,后方的命令的执行者为被选择到的实体
- function 执行 xxx.mcfunction 文件内命令, xxx.mcfunction 内所有命令的执行者为 function 的执行者。
- 游戏规则(gamerule)中 gameLoopFunction 执行的 xxx.mcfunction 文件内命令的执行者为一个虚拟执行者,权限为2,坐标为(0, 0, 0)。
例子: 让管理员(名称为admin)执行以下命令这里需要的 execute 命令的不完全语法: execute <实体> ~ ~ ~ <命令> ,即让实体执行指定命令
这里需要的目标选择器不完全语法: @e[name=xxx] ,即选择名称为xxx的实体
整条命令的执行者为玩家admin复制代码
- execute @e[name=a] ~ ~ ~ execute @e[name=b] ~ ~ ~ say hi
execute @e[name=b]... hi 这命令的执行者为实体a
say hi 这命令的执行者为实体b
执行点
默认情况下, 命令执行点就是执行者的坐标。
命令执行点对相对坐标有非常重要的影响(相对坐标大多是以执行坐标为原点计算的), 以及目标选择器选择条件、顺序也和执行坐标有关系。
有三种情况会导致执行点与执行者坐标不同:
- execute 命令,而且指定了后方的执行坐标或偏移(不是(~, ~, ~))。那时候后面的命令的执行坐标就和执行者坐标不同了。
- 牌子clickEvent。该情况下执行者是点击的玩家,然而执行坐标是牌子的坐标。
- 执行命令函数期间把执行者移位。执行点还是之前的点,然而执行者的位置已经不同了。
目标选择器
用途
命令很多时候是需要针对实体去执行的,比如 tp 命令。如果你使用玩家名来指定传送的玩家,比如 tp pca006132 0 5 0 ,你就需要针对每个玩家写一个命令。
这方法在很多情况下是不可能使用的,因为我们不一定会知道被传送的玩家是谁,而且就算知道所有玩家,我们也需要举出所有的可能(穷举),不然就有些玩家无法传送,这样做需要的命令数就会非常多。对于实体就更恐怖了,实体的UUID除非是特地指定,不然都是随机的,难道我们要穷举UUID?所以穷举玩家名的方法是接近不可能的。
所以,在针对实体执行命令的情况下,我们通常会使用目标选择器。
选择器的用途,就是根据某些条件(用选择器参数指定)来选择实体,所以选择到的数量可以是没有/一个/多个。
格式
@选择器名称
@选择器名称[参数1=值,参数2=值]
参数名称 描述 选择器名称 决定选择器行为 参数 额外选择条件。不一定要存在,但如果存在一个或多个参数则必须用方括号括住,并且以逗号分隔开不同的参数(所有符号都是英文符号,如,和[])。选择器将会选择符合一切参数的目标 值 参数所对应的数值,用来确定参数所对应的数据,与参数结合使用来选择实体。 选择器名称注: 每个参数只能出现一次,不然会被覆盖
选择器内不能出现空格
名称 描述 p 最近的一个玩家(type参数在此无效) a 全部玩家(包括死去的玩家, type参数在此无效) r 随机实体(默认为玩家)
当参数c多于一个的时候,会把选择顺序打乱,对部分随机选择系统十分重要。e 所有实体(包括玩家) s 执行者(实体,当执行者不符合要求时则不选择任何实体)
参数
格式: 参数名=数值
文字类的数值前加上!则代表选择所有非该数值的目标
数值不能出现小数。
名称 描述 x,y,z 以该坐标作为判定的起始点(默认为执行坐标)
比如你填写x=1,y=1,而你执行命令的坐标是x=5,y=5,z=5,那么那个判定的起始点就是x=1,y=1,z=5
如果只是填写其中一个/两个参数,剩下的就会默认为执行坐标(比如x=5,而执行坐标是100 5 200,那么那个判定的起始点就是 5 5 200)r,rm 离判定的起始点(参见上方x, y, z参数)的距离 (r就是判定区域的半径,rm就是不包括在判定区域内的圆形半径)
比如r=5就是选择所有在5格范围内的实体,rm=5就是选择所有5格范围外的实体
比如@p[r=10,rm=3]就是离判定的起始点的距离小于等于10米,大于3米的最近玩家m 玩家的游戏模式
s=生存,c=创造,a=冒险,sp=旁观c 数量(最多选择多少个)
这个是根据选择顺序来选择的
正数的话就是选择最先选择到的n个实体,负数就是选择最后选择到的n个实体
所以请参见下方的选择优先规则
比如@e[c=5]就是最近的5个实体,@e[c=-5]就是最远的5个实体
重要:当c=1、选择器名称不为r并且命令执行者的类型符合选择器选择到的实体类型,选择器将会选择执行者l,lm 经验等级,l是小于等于,lm是大于等于 score_变量 该变量(objective)的分数范围(小于等于)
我们可以使用score_obj=2147483647检测对象在该变量上有无分数score_变量_min 该变量(objective)的分数范围(大于等于)
我们也可以使用score_obj_min=-2147483648进行有无分数的检测team 队伍名称(可以使用!表示不等于, 如team=!blue就是选择不在blue队伍里的)
team= 就是代表没有队伍的实体(比如@e[team=])
team=!就是代表有队伍的实体name 实体的名称(可以使用!表示不等于, 如name=!pca就是选择名称不是pca的实体) dx,dy,dz 长方体的范围
由起始点(参见上方x, y, z参数)延伸出去(dx就是沿着x轴延伸的格数,如此类推。正数就向正的方向,负数就向负的方向,范围必定是完整的格子,没有任何偏移,即使执行位置不是整数)的范围内的实体
*注意: 只要实体的碰撞箱接触到这范围就会被选中,而不是看其坐标
rx,rxm 实体垂直朝向(看的方向)
0:水平;-90:向上;90:向下
rx:最大的角度;rxm:最小的角度
只会视乎角度的整数部分, 比如实体的实际方向是1.1, rx=1,rxm=0和rx=2,rxm=1都会选择到那个实体
当rx>rxm的时候, 选择到的角度范围就是rx-rxm;
当rx<rxm的时候, 范围就会断开, 也就是上一个情况的相反, 详见下方例子ry,rym 实体水平朝向(看的方向)
0:+Z方向;90:-X方向;180(-180):-Z方向;-90:+X方向
(可以使用大于180的度数)
ry:最大的角度;rym:最小的角度(如ry=50, rym=0就是50度的范围;ry=0, rym=50就是310度的范围)
当ry>rym, 选择到的角度范围=ry-rym;
当rym>ry, 选择到不到的角度范围就是ry-rym, 也就是上一个情况的相反, 详见下放例子
type 实体种类(所有summon的实体种类+player。可以使用!表示不等于,如type=!player就是所有不是玩家的实体)
type=!lightning_bolt则代表所有类型的实体(对@r相当有用)tag 选择拥有此标签的实体,
在数值前添加!将只选择不拥有此标签的实体,
提供空的标签名将选择所有没有标签的实体,
只填写“!”将选择任何拥有标签的实体。
注意: 只能检查一个tag
空间限制
如果选择器里有任何关于坐标的参数(比如r/rm/dx),那个参数的作用范围就是执行的世界(其他世界的不会被选择到)
如果那个选择器里同时有dx/dy/dz和r/rm,那么选择到的范围就是dx/dy/dz和r/rm重叠的范围
如果那个选择器里有dx/dy/dz任何一个/两个,那么剩余未声明的会默认为0
关于死去的玩家:
死去的玩家能够被@a选择器选择到,然而当我们加入了任何空间限制后就无法选择
故此我们认为死去的玩家是存在于第四维的【严肃脸】
选择顺序
选择器会优先选择在执行的世界的加载范围内的实体/玩家(先选择离判定的起始点最近的实体,当那些实体的距离一样时,它就会优先选择存在最久的),然后就是别的世界距离你现在坐标最近的实体。
选择器运行概念
常见错误
- 重复的选择器参数,比如两个 type
- 以为 score_变量名称=数值 代表选择分数 等于 数值的实体,然而事实是选择分数小于等于数值的实体
- 大小写/全型半型错误。实际上那些参数的名称都是小写,而那些数值也是大小写敏感的
- 把实体NBT当作选择器参数一样写,然而选择器参数就那几个,NBT并不是选择器参数,选择器参数也不是NBT
- 以为物品名称就是它扔出来之后的名称,然而并不是(原因:物品名称的NBT是 {Item:{tag:{display:{Name:名称}}}} ,而实体名称的NBT是 {CustomName:名称} )
- 逻辑相关错误,比如在执行这个指令的时候分数不可能在指定范围内
- @a 写成 @e[type=player] 。严格来说并不是错误,然而这个是不好的习惯因为这样子你的命令可读性就会减低,而且会导致命令长度增加,自己写也累不是?
- 开括号之后需要关括号,比如 @e[type=armor_stand.r=3 就会判断为@e,相差会很远
- 以为 testfor @a[c=x] 当人数少于x个人的时候就会失败。其实SuccessCount是即使只检测到一个人也会成功的。应该要把人数放进记分板里然后检测。
- @a 和 @p 混用。前者代表的是所有玩家,包括死去了的玩家。而后者不包括死去的玩家。
特殊情况
- c=1 时并且执行者的类型和选择器选择的实体类型吻合时,MC会有特别的选择实体方法。比如牌子点击的话就会选择点击者(尽管点击者未必与执行坐标,也就是牌子的位置最近),或者UUID碰撞/因特殊原因无法选择时能选择到该实体。然而注意,要使用此功能的话请不要填写其他参数,否则可能会导致MC不采取此方法选择实体。
- 部分命令参数的选择器 最多只能选择一个目标 ,比如是 scoreboard players operation 之后两个实体参数,其中的一个必须只选择一个目标。这种情况我们需要:
- 使用 @p @r (不设置 c 参数) @s 选择器,这样选择到的就是最多一个目标。
- 或,设置 c=1 。比如 @a 就不只选择一个目标,但 @a[c=1] 就只选择一个目标。但 @r 只选择一个目标, @r[c=10] 就不只选择一个目标。
例子
选择一个距离执行点5格以外,最近的实体
@e[rm=5,c=1]
选择所有变量(objective) X分数大于50、小于100,变量Y分数大于等于-200,小于等于0,目标Z分数等于200的实体
@e[score_X_min=51,score_X=99,score_Y_min=-200,score_Y=0,score_Z_min=200,score_Z=200]
选择随机5个实体
@r[c=5,type=!lightning_bolt]
选择ry=0至ry=90的实体(0≤ry≤90)
- @e[ry=90,rym=0]
选择ry=90至ry=0的实体(0≤ry≤90)
- @e[ry=0,rym=90]
选择rx=20至rx=-20的实体(-20≤rx≤20)
- @e[rx=20,rxm=-20]
选择rx>=20和rx<=-20的实体(rx≤-20 or rx≥20)
- @e[rxm=20,rx=-20]
执行统计
命令执行的时候会统计影响到的东西数量、成功执行次数与执行结果。
所有统计都是整数,储存在NBT里,需要时可以直接用nbt查询或以 stats 命令绑定到 指定玩家名/实体 的记分板分数。
注意: 之后的执行结果会覆盖之前的数值。这在进行 execute 命令嵌套的时候,往往会让人搞错每一层嵌套涉及到的实体的最终统计值究竟来自哪一层命令。
执行统计包括:
- 成功执行次数(SuccessCount),如 testfor @a {SelectedItem:{id:"minecraft:stone"}} 的符合玩家数量。
- 影响实体数(AffectedEntities),如 testfor @a 选择到的玩家数量。
- 影响方块数(AffectedBlocks),或是探测到的方块数。如 testforblocks 或 clone 探测/复制到的方块数。
- 影响物品数(AffectedItems),或是探测到的物品数。如 clear 成功清除/检测到(如果最大清除数量设置为0)的物品数量。
- 查询结果(QueryResult),部分查询类的命令会把结果写进这统计里,如 time query gametime 、 worldborder get 等。
命令执行过程
当游戏需要执行一条命令的时候,它会作出以下处理:
- 把命令以空格为分隔符分成不同的命令参数,然后在命令列表里搜寻第一个参数所代表的命令。即,如果命令第一个空格前的部分为 scoreboard ,则将判断这是一条记分板命令。如果没有对应的命令,则报错“未知命令”。
- 尝试判断这条命令是否对多个目标执行,实现方式是找出命令中第一个可选择多个目标的目标选择器。具体过程如下:
- 检测目标命令参数在命令的格式中是否是一个实体参数。(比如 give @a stone 的第二个参数 @a )。
- 如果是,则检查此命令参数是否是一个选择器。
- 如果是,则检查此选择器最多能选择到实体的数目是否为非1( @a 和 @e 以外的默认选择1个。如果存在 c 参数则看 c 参数的数量。)
例子: @e ≠ 1 ; @e[c=1] = 1 ; @r = 1 ; @r[c=5] ≠ 1 ; @a[c=-5] ≠ 1 - 如果是,则代表找到了第一个选择多目标的目标选择器,即该命令对多实体执行,搜寻终止;否则则以下一个命令参数为目标继续重复1-3步,直到找到满足条件的命令参数或遍历完全部命令参数。
- 如果经由第二步的判断得到这是一个多目标的命令,则根据找到的目标选择器搜寻所有满足条件的实体并排序,然后逐个替换具体实体至选择器位置。之后,尝试逐条执行替换后的命令。
比如
- give @a[tag=stone] stone
然后我们找到的第一个可选择多个目标的选择器参数就是 @a[tag=stone] 。
假设当前世界有5个玩家,都有 stone 这tag,分别为 a 、 b 、 c 、 d 、 e 。假设离执行坐标的距离是a最近,b次之,如此类推。
那么那命令会依次被替换为:
- give a stone
- give b stone
- give c stone
- give d stone
- give e stone
成功次数、实体数由于此原则,一些命令如 scoreboard players operation 就有一个很大的限制:两个目标之间必须有一个只选择一个目标,并且必须写清楚是选择一个。
虽然替换的过程在一条一般命令中只会替换一次,但在一些复合命令(命令嵌套)中会替换多次。例如 execute 嵌套,就很容易出现需要多次选择不同实体的情况。根据这个替换逻辑可以看到,实际上执行的命令数增加的很快。
好了,就算我们知道这命令执行机制,那么又如何呢?
其实SuccessCount与AffectedEntities和第一个可选择多个目标的目标选择器有关。
- AffectedEntities: 第一个可选择多个目标的目标选择器选择到的实体数。不论之后的命令是否成功执行。这个在命令执行前就会被设置。
- SuccessCount: 命令被替换后成功执行的次数。不多于AffectedEntities数值。这个在命令执行后才会被设置。
例外情况
spreadplayers 及 scoreboard teams join 命令都是例外情况,其SuccessCount最大为1,其AffectedEntities才是受影响的实体数。
因为此命令不定义所谓的选择器参数,因此游戏不会对选择器进行替换。(因为此命令有特别处理选择器的方式)
参见
会Java的朋友如果想看源码,请看mcp的
- net.minecraft.command.CommandBase 里,有一个 isUsernameIndex 的函数。这会告诉 CommandHandler 哪儿是实体目标。
- net.minecraft.command.CommandHandler 。这是上面说的命令执行逻辑部分。
- net.minecraft.command.EntitySelector 。这里的 matchesMultiplePlayers 定义了怎样的选择器才算是只选择一个目标。
[groupid=546]Command Block Logic[/groupid]