2.4.1 标签命令
在实际的工程中,我们总是希望对一些符合我们所给出的条件的玩家进行一些标记,以便让他们执行后续命令。比如,标记存活的玩家、或者标记一个满足了非常苛刻条件的玩家、标记扔出雪球的玩家等等。
使用标签的必要性
例如,你可能很早之前就听说过“雪球菜单”——这是一类玩家扔出雪球就对其触发菜单的功能,玩家可能通过抬头低头等操作选择物品。对于这种复杂场景,如何确定哪个玩家扔出了雪球是很重要的。常用的方法是在雪球扔出的一瞬间,使用@p确定最近的玩家是扔出雪球的玩家,然后立刻销毁雪球(因为这东西会动,不能让它影响到沿途没有扔雪球的玩家)。对于这种瞬间的判定和玩家持续的选择之间的矛盾,我们就可以先标记一下哪个玩家使用了雪球,毕竟这些条件后续将不复存在。
面对这种类似的复杂需求的时候,就难免需要进行标签。何时使用标签,在你的实际工程中视情况而定,当需要用到标签的时候,你自会意识到这一点。
标记命令/tag的语法
我们可以使用/tag命令来对特定的实体添加标签,从而进行标记。
/tag <实体: target> <add|remove> <名称: string>
/tag <实体: target> list

这些语法是很直观的。第一个语法的含义是,为实体添加(add)或移除(remove)名为名称的标签。第二个语法,则是在聊天栏返回实体的所有标签。添加这些标签不会对实体的运行有任何影响和变化,它仅仅作为在命令或底层上的标记。
执行命令/tag @e add testTag,它将为所有实体添加一个名为testTag的标签。你可以观察这些实体是否发生变化。
然后,执行命令/tag @e list。
下面是执行结果。你可以看到,执行这条命令对实体的行为并没有任何影响,只是简单地添加了一个标记。

目标选择器参数tag
既然标签并不会对实体有任何的影响,而只是添加一个标记,那么我们就需要一个方法来检测并选中有特定标签的实体。这就是我们接下来的重点:目标选择器参数tag。它的语法为
tag=<标签: string>
例如,查找所有具有testTag标签的实体,就是@e[tag=testTag]。

tag是支持反选的。例如@e[tag=!testTag]就寻找没有testTag标签的实体。
现在假设我们有一个需求,对脚下 5 格均为玻璃的玩家执行若干条命令。传统的方法,是使用execute if block进行检测并执行命令,例如:
execute as @a at @s if block ~~-1~ glass if block ~~-2~ glass if block ~~-3~ glass if block ~~-4~ glass if block ~~-5~ glass run say 1
execute as @a at @s if block ~~-1~ glass if block ~~-2~ glass if block ~~-3~ glass if block ~~-4~ glass if block ~~-5~ glass run say 2
execute as @a at @s if block ~~-1~ glass if block ~~-2~ glass if block ~~-3~ glass if block ~~-4~ glass if block ~~-5~ glass run say 3
execute as @a at @s if block ~~-1~ glass if block ~~-2~ glass if block ~~-3~ glass if block ~~-4~ glass if block ~~-5~ glass run say 4
execute as @a at @s if block ~~-1~ glass if block ~~-2~ glass if block ~~-3~ glass if block ~~-4~ glass if block ~~-5~ glass run say 5
然而,我们可以使用标签简化它们。对比上面和下面的命令,你也可以试执行之以体验使用标签的意义,效果是一样的。
tag @a remove glassBelow
execute as @a at @s if block ~~-1~ glass if block ~~-2~ glass if block ~~-3~ glass if block ~~-4~ glass if block ~~-5~ glass run tag @s add glassBelow
execute as @a[tag=glassBelow] run say 1
execute as @a[tag=glassBelow] run say 2
execute as @a[tag=glassBelow] run say 3
execute as @a[tag=glassBelow] run say 4
execute as @a[tag=glassBelow] run say 5
在这里,我们用glassBelow标签来表示玩家脚下有玻璃。
- 第 1 行,用于清除所有玩家的
glassBelow标签,防止上一次执行这个逻辑时,有玩家脚下为玻璃而现在没有,导致的执行错误。 - 第 2 行,检查脚下为玻璃的玩家并加上
glassBelow标签,这样有这个标签的玩家就是满足这些条件的玩家,后续就不需要再写这些条件了。 - 第 3~7 行,则是以前的写法执行的命令。
之后,在模块 2 学习函数的时候,你可以了解到一种更简单的执行方式。
运用标签的实例
其中一个常用的实例,是检测存活的玩家。你是否还记得我们在第一章时曾讲过,@a会选中存活的玩家,而@e[type=player]并不会。那么,我们以isAlive作为存活玩家的标签,有这个标签代表存活,而没有这个标签则代表处于死亡状态。和实验 2.4-2 类似,我们先进行初始化,无论死活,移除标签:
tag @a remove isAlive
然后,通过@e[type=player]只对存活的玩家添加回标签:
tag @e[type=player] add isAlive
这两条命令一般通过命令方块或函数循环执行。
总结
- 标签可以对实体进行一些特殊标记,常常用于一些分类情况或者复杂情形。
- 标签命令的语法有两条:
/tag <实体: target> <add|remove> <名称: string>:为实体添加(add)或移除(remove)名为名称的标签。/tag <实体: target> list:在聊天栏返回实体的所有标签。
- 使用目标选择器参数
tag来检测具有特定标签的实体,支持反选。
练习
- 写两条命令,为雪球附近 2 格的一名玩家添加标签
menu,然后移除雪球。
命令 1:_____
命令 2:_____ - 写 3 条命令,当有玩家死亡后,在(56,43,-79)放置红石块。
命令 1:_____
命令 2:_____
命令 3:_____ - 写 2 条命令,当玩家拥有
hasPickaxeUpgrade标签时,给予其一把钻石镐,否则给予一把铁镐。
命令 1:_____
命令 2:_____
练习题答案
- 命令 1:
/execute as @e[type=snowball] at @s run tag @p[r=2] add menu
命令 2:/kill @e[type=snowball] - 命令 1:
/tag @a remove isAlive
命令 2:/tag @e[type=player] add isAlive
命令 3:/execute if entity @e[tag=!isAlive] run setblock 56 43 -79 redstone_block - 命令 1:
give @a[tag=hasPickaxeUpgrade] diamond_pickaxe
命令 2:give @a[tag=!hasPickaxeUpgrade] iron_pickaxe