第一百一十二章 实体的通用标签 上
看,这是一头有胡子的粉红羊!
(在哪?我怎么没看到?)
它作为一个实体,肯定也有自己的NBT标签。
在这些NBT标签中,有很大一部分是大部分实体通用的。
具体是哪些呢?
首先,和物品一样,游戏也会通过实体的NBT来识别该实体到底是什么实体,这就需要用到id这个标签。id标签的数据类型是文本(String字符串),它存储着这个实体的命名空间ID。比如这只羊的id标签就是:
{id:“minecraft:sheebr /“}
需要注意,id标签由于是用来判断实体类型的,十分重要,所以我们在游戏中无法通过指令来获取并修改它,也就是说你并不能把这只羊变成一只猪。另外,玩家虽然也是实体,但没有id标签。
id可以判断实体的类型,但如果游戏还想更精确地判断这个实体到底是哪个个体,就需要使用到UUID。实体的UUID数据也存储在自身的NBT中,也就是说我们可以通过NBT来获取到实体甚至玩家的UUID。
UUID的NBT存储方式在Java1.16版本中迎来了巨大改变,这件事我们已经在第一百一十章了解过了。在Java1.16之前,实体的UUID在NBT中是以『高低位』的方式存储,也就是像下面这样子:
{UUIDMost:1783197533150072793L,UUIDLeast:-7109092977889688726L}
其中,值后面的大写字符『L』代表这两个标签的数据类型都是Long长整型。目前你只需要知道这种整型能够存储很大的数字即可。需要注意的是由于计分板数据类型是Int整型,所以你并不能直接将实体的UUID高低位存进计分板中。
在Java1.16更新后,实体的UUID改成了用Int整形数组来存储:
{UUID:[I;-985669504,-1477950631,-1338504796,372293997]}
由于改成了Int整型数组的存储方式,所以在Java1.16版本更新后,你就可以直接将实体的UUID存入计分板。
一个实体除了自身的类型和UUID,还有许许多多的数据。让我们仔细思考一下,可能还会有哪些数据。
一个实体肯定会有位置,所以NBT中自然也要存储实体的位置数据。Pos标签就是干这个的。
Pos的数据类型是『Double双精度浮点数列表』,列表内的三个元素从左到右分别存储着该实体的X、Y、Z坐标数据。比如:
{Pos:[14.294485503905866d,72.0d,133.22538953931465d]}
这代表着该实体处于(14.294485503905866,72,133.22538953931465)这个位置。
和Pos作用类似的标签还有Rotation。Rotation标签的数据类型是『Float单精度浮点数列表』,列表内的两个元素分别记录着这个实体的水平旋转和垂直旋转角度。比如:
{Rotation:[322.82275f,0.0f]}
这代表着该实体正水平地朝向南偏东37.17725°的方向。等等!『322.82275』?!
还记得本书在第二十六章曾经写过这么几句话吗:
『等等,我们在讲tbr /时,不是说水平旋转角度是:「以实体为中心,以正南(z轴正方向)为0°,顺时针下来,实体朝向和正南方向的夹角(也或者说实体在真南方位角体系中朝向的角度),就是该实体的水平旋转角度。」
那这怎么跑出来负数了?
其实在Minecraft中,水平旋转角度虽然可以像我们之前在第九章讲tbr /时那么用,但大多数时候,你都得这么用:
以正南(z轴正方向)为0°,顺时针旋转180°通过正西至正北,用正数,逆时针旋转180°通过正东至正北,用负数。比如-45°,就代表以正南为基准,逆时针旋转45°的方向;30°,就代表以正南为基准,顺时针旋转30°的方向。
也就是说,在Minecraft中,水平旋转角度的正确范围是-180°~180°,而不是0°~360°。至于为什么我要在第九章那么讲,只是怕一下子就把负数搬出来会吓你们一跳。』
现在,我们要纠正这里的一个疏漏之处:在Minecraft中,水平旋转角度其实有两套标准——一个就是我们在第九章讲到的『真南方位角』,也就是0°~360°这个标准;另外一个就是第二十六章讲到的-180~180°这套标准。
你可能已经有些晕了——两套标准,怎么判断什么时候要用什么标准?
其实很简单,我们只需要记住三个关键点就行:
①在目标选择器中,必须采用『-180~180°』这套标准。
②在指令中,除了目标选择器和NBT外,其他地方基本上两个标准都能用。
③在实体NBT中,玩家采用的是『-180~180°』这套标准,而非玩家实体采用的是类似『真南方位角』的0°~360°标准。
其中的第三点,这边得好好讲一下。回去看看上面那个Rotation标签,你会发现那里采用的是『真南方位角』的标准,这说明了什么?
这说明,这个实体,不是一个玩家。
没错,上面那个Rotation标签,是作者从Java1.12.2版本中的一只猪上扒下来的。(不用担心,即使在目前最新的Java1.19.1版本中,这个特性也没有被Mojang改变)
那玩家的呢?让我们使用/data指令获取一下:
/data get entity @s Rotation
\\适用于Java1.13及以上版本\\
data指令本书还没讲到,如果你感兴趣的话可以去Minecraft Wiki上了解了解。在这边你只需要知道,上面那条指令可以获取到你自己(执行者)的Rotation标签数据。
运行一下,游戏返回了以下数据:
→XXXXXX拥有以下实体数据:[-71.16943f,29.864527f]
不难注意到,上面的数据中,水平旋转角度是『-71.16943f』,采用的是与非玩家实体不一样的标准。
So,你学会了吗?Rotation标签就这样子,如果能的话你可以探究一下把实体的水平旋转角度设成负数会发生什么。接下来让我们继续了解更多的实体NBT标签。
实体肯定能够运动,因此必然具有速度属性。那游戏是怎样存储实体速度的呢?
我们在小学二年级就学过:一个物体的速度,可以被分解为该物体在X、Y、Z三个轴上的速度。Minecraft中存储实体速度的方式就和这差不多。在实体NBT中,用来存储实体速度的标签是Motion标签,它的数据类型是『Double双精度浮点数列表』,列表内的三个元素从左到右分别是该实体在X、Y、Z三个轴上的速度向量,单位是『米/秒』。举个简单的例子:
{Motion:[1.2990381056d,-0.75d,0.0d]}
这代表着该实体正朝着正东、水平向下约30°的方向以约1.5米每秒的速度前进。需要注意的是,Motion的值并不会固定不变,而是会受到游戏模拟的阻力的影响。
(注:0.75倍根号3就约为1.2990381056,因此你可以把1.2990381056看作0.75√3)
由于本书并不是一个物理教材,所以关于Motion我们就不继续深入,你大概知道是这么一回事就行。如果你没有看懂,可以去求助你的物理老师。
或者你可以去找一下那位屎尿屁专家?帮他完成屎尿屁大统一理论?
实体的NBT还有许多标签,好消息是这些标签相对上面的内容来说很简单。
air标签用于储存实体的『空气值』,它的数据类型为Short短整型,允许的最高值为300,实体在水中每刻都会减去1,小于等于0时(对于大多数生物来说)会开始扣血。
FallDistance标签很有趣。如果你玩过JAVA版的老版本,那你可能知道在旧版本中,从高空落下而不被摔死的方法,除了落地水,还可以挑战手速按ESC暂停游戏,然后再继续游戏。这个时候你的再掉下去就只会或几乎没有伤害。这个BUG的核心就在于实体的FallDistance标签。
FallDistance标签的数据类型是单精度浮点型,它用来记录实体已经掉了多远的距离,然后在实体落地时计算会扣多少滴血。老版本暂停游戏的话,这个值就会清零,所以才会导致这个BUG(于是Mojang修复了)。
Passengers标签是一个比较常用的标签,它的数据类型是『复合标签列表』,作用是记录骑着该实体的其他实体的NBT数据。没错,这东西可以用来套娃!OOC也就是用这个标签来制作的。
需要注意,在Java1.9版本之前,实体并没有『Passengers标签』,而是有『Riding标签』。它的用法和新版本的『Passengers标签』一模一样。
Fire标签的数据类型是Short短整型,它的作用是决定实体着火或不会着火的时长。如果它的值是正数,就是决定实体身上的火距离熄灭还有多少游戏刻,如果它的值是一个负数,则代表着该实体在接触到火后,不会着火的刻数。比如:
{Fire:-40s}
这代表着当该实体接触到火时,需要两秒才会燃起来。
PortalCooldown标签的数据类型是Int整型,作用是记录这个实体还有多长时间(单位为游戏刻)才可以再次穿越下界传送门。比如这只粉红羊刚刚穿过下界传送门,它就需要等至少300刻(15秒)才能再次传送,因为它的PortalCooldow标签被设定为了300。
Dimension标签的数据类型是Int整型[Java1.16以下]或文本(String字符串)[Java1.16更新后],它的作用是记录该实体所处的维度。
举个例子:
{Dimension:“minecraft:overworld“}
\\Java1.16更新后\\
{Dimension:0}
\\Java1.16更新前\\
这代表着该实体所处的维度为『主世界』。对了,『下界』的维度数字ID为-1,『末地』为1。
需要注意,似乎自从Java1.16版本开始,Dimension就不再是实体的通用标签之一,而是变成仅玩家拥有该标签。所以对于Java1.16及以上版本的实体来说,并没有Dimension这个标签。
这一章到此为止。
附录:实体通用标签的部分历史
Java
1.9——Riding标签改为Passengers标签
1.16——Dimension标签不再是实体通用标签,数据类型从Int整型改为String字符串。
1.17——实体数据的储存位置被改变