第一百四十一章 牛顿心中的Minecraft:下落的方块
前十二章,我们详细地了解了生物的共通NBT以及NBT格式。但别忘了,本卷的名字叫做:
实体与NBT
所以接下来,我们就要回归正题。
——第一节:关于下落的方块这个大类只有一种实体这档事
在第一百二十九章里,我们知道了很多关于实体的东东。比如:下落的方块是个实体。
但有没有人想过这么一个问题:
我在对下落的方块这种实体举例子的时候,为什么举了一个“下落的方块”实体的例子?
深入思考的话,我们就会得出一个神奇的结论:下落的方块这种实体只有一个实体——下落的方块(FallingSand[1.13之前]、falling_block[1.13及之后])
所以这就可以解释你在用kill清除实体时,就不会跳出来“下落的沙子”了,更不会跳出来“沙子”(因为这名字已经被掉落物占了),而是统一“下落的方块”。因为人家变成实体之后就统一成了一个实体。
再深入思考,我们又会得到一个问题:
统一成一个实体后,下落的方块是如何确定自身到底是什么方块的?
为了解决这个问题,我们可以回顾一下第一百零八章到第一百零九章对掉落物的介绍,就会得出一个对掉落物确定自己到底是什么物品的方法的结论:
用NBT存储物品的信息
按理来说,用实验法来研究生物,得出结论后也就差不多了。但我们不是在进行一个生物实验,而是在学习NBT。况且,就算我们这是一本生物书,生物学它本身也是一个:
...→观察并思考→提出问题→收集资料→作出假设→制定实验计划→实施实验并记录→得出结果→研究并思考→提出新的问题→...
所以我们可以研究这个结论,并提出一个新的问题:
为什么掉落物要用NBT来存储物品的信息呢,而不用item_<物品ID>这样子每个物品的掉落物都有一个对应的单独实体?
答案很简单:
①Mojang这个喜欢3的家伙很懒(主要原因)
②如果这样子做的话虽然也能达到目的,但游戏会更大
深入思考,我们还会得出一个震惊的结论:
这样子的话,那么掉落物这个大类也只有一个实体唉:掉落物
实际上还真是这样的,掉落物确实只有一个实体:minecraft:item
(注意!minecraft:item_frame这个实体实际上是物品展示框,而不是掉落物)
得出了这些结论,我们再来看看下落的方块。刚才我们发现下落的方块只有一个实体:下落的方块。这说明了什么?
下落的方块也是使用NBT来存储方块的信息。
这就是上面那个问题的答案。
——第二节:下落的方块的NBT
下落的方块中存储着方块信息的NBT是:
BlockState(复合标签)
意思是:Block(方块)State(状态)
这个复合标签里有两个重要的东西:
Name(字符串):这个正在下落的方块的ID
Probr /erties(复合标签):可选,这个正在下落的方块的方块状态
举个例子。比如,现在这里有一个沙子被炸飞了,那么它的BlockState很有可能是:
{BlockState:{Name:“minecraft:sand“}}
Probr /erties这个先不管,方块状态等我们以后讲到你就立马会了。
我们可以使用/summon minecraft:falling_block(1.11及之后,之前为/summon minecraft:FallingSand)来生成一个下落的方块。按照生成掉落物的经验,我们就可以搞出一些神奇的东西,比如:
/summon minecraft:falling_block ~~~{BlockState:{Name:“minecraft:diamond_block“}}
执行它,你的下半身就会立马被一个钻石块包裹。然后这个钻石块开始下落,接着就消失了!
如果你用循环命令方块来执行,建议你稍微改一下指令:
/summon minecraft:falling_block ~~2 ~{BlockState:{Name:“minecraft:diamond_block“}}
开启!你就会发现你搞出来了一个不断在空中振动(???)的没有碰撞箱(???)的钻石块(???)。
这到底是怎么一回事呢?
实际上还有更有趣的。
如果你在这个不断振动的钻石块的位置上放置一个钻石块。如果下面是空的,你就会发现:
你放置的这个钻石块给这个在不断振动的钻石块给震掉下来了!
还可以更奇葩吗?
可以!
如果下面有方块,你还放的话,你就会发现:
你放置的这个钻石块给这个在不断振动的钻石块给感染了!成了钻石块下落,每到地面就重新下落,直到下面被打掉!(建议可以的亲自去做一下这个实验)
为什么会成这个样子呢?
因为Time没填,默认为0。
Time(Int整形):该下落的方块已存在的刻数,不设置默认为0。如为0,则:
当Time从0变为1时,如该实体的位置上的方块与其存储的方块一致,则继续下落,并删除该方块。不一致,则删除该实体。(这应该就是方块开始下落时游戏的替换原理)
如不为0,当Time值大于600(30秒)或Time值大于100(5秒)时超出建筑限制(y大于255或小于0),就变为掉落物。
所以,为了让这个钻石块能够快快乐乐地下落,我们就需要:
/summon minecraft:falling_block ~~~{BlockState:{Name:“minecraft:diamond_block“},Time:1}
然后你就会发现:
钻石块竟然不浮空了,而是成功掉了下来!
(The strange laughter in Newton's coffin frightened the tourists around him.
——British Broadcast Corbr /oration rebr /ort)
BlockState和Time这两个标签是必填项。除此之外,还有一些非必填项:
TileEntityData(复合标签):该实体存储的方块的方块实体标签
Drobr /Item(Byte字节型:1或0[true|false]):该实体被破坏后是否掉落其方块的物品形式。为1时掉落,但如果其方块没有对应的物品则仍然不会有物品掉落。
HurtEntities(Byte字节型:1或0[true|false]):该实体掉落时碰到其他实体是否对其造成伤害。为1时造成。
FallHurtMax(Int整形):被砸中的实体所承受的伤害上限。一般的方块默认为40滴血(20♥)
FallHurtAmount(Float单精度浮点型):给被砸中的实体造成的伤害=FallDistance(当前实体已经坠落的距离)×FallHurtAmount(该标签)。一般的方块默认为2。
举个例子,比如你召唤一个下落的水方块(???):
/summon minecraft:falling_block ~~~{BlockState:{Name:“minecraft:water“},Time:1,Drobr /Item:0,HurtEntities:1,FallHurtMax:150,FallHurtAmount:1.1}
召唤后,你会发现你看不到下落的水方块。唯一能体现它存在的只有在它落地变为方块之后。
而如果你从25米高空扔下一个这样的下落水方块,假设下面有一个正在整理物品的有20滴血的玩家。几秒后,他就会原地去世,同时原地会凭空出现一摊水(忽然发现这可以做一些有趣的东西,因为这就像一个活生生的人其体内除了水其他物质都突然凭空消失的样子)。
而他受到了多少伤害呢?
根据“给被砸中的实体造成的伤害=FallDistance×FallHurtAmount”这个公式,我们可以轻易得出:
给被砸中的实体造成的伤害=25×1.1=27.5(13.25♥)
怪不得这名玩家会原地去世。
(TileEntityData这个标签等我以后讲方块时候再来了解)
——第三节:下落的方块的神奇用途
下落的方块有许多有趣的用途。
在第一百一十二章到第一百一十三章,我们了解了实体的通用标签。在此之中,有这么几个标签和下落的方块配合时会表现得很好:
NoGravity(Byte字节型):控制实体是否掉落
Motion(列表):记录实体在dX、dY、dZ三个轴的速度
上面我们搞出来一个神奇的不断在空中振动的没有碰撞箱的钻石块。那我们可以弄出一个静止在空中的可以穿过去的钻石块吗?
可以!
NoGravity是控制实体是否掉落的,当为1时实体不会坠落。所以我们可以:
/summon minecraft:falling_block ~~~{BlockState:{Name:“minecraft:diamond_block“},Time:1,NoGravity:1}
然后......
妈妈你快看!这个钻石块它浮在空中唉!看,我可以走过去!也可以回来!现在我头在钻石块里面!
(Newton's coffin lid suddenly shook, frightening br /assers-by.
——British Broadcast Corbr /oration rebr /ort)
只不过这有一个坏处,就是当Time过600它就会变成掉落物。
所以我们可以这样子:
重复执行/summon minecraft:falling_block ~~5 ~{BlockState:{Name:“minecraft:diamond_block“},Time:1,NoGravity:1,Drobr /Item:0,CustomName:“{\“name\“:\“diamond_block\“}“}→连锁有条件的保持开启/kill @e[tybr /e=falling_block,name=“diamond_block“]
这样子,我们就可以一直保持这个幽灵钻石块存在。
知道了如何坑朋友之后,我们还可以玩点新花样:
Motion这个标签可以让我们设置实体的运动。通过它+MC的物理运动,我们就可以弄出一些新的东西,比如一个最基础的:
/summon minecraft:falling_block ~~~{BlockState:{Name:“minecraft:redstone_block“},Time:1,Drobr /Item:0,Motion:[0.7d,0.5d,0.3d]}
(对了,当时对Motion是一笔带过,这里讲一下。Motion的值是列表,列表里有三个值:
[dX速度,dY速度,dZ速度],值类型都是双精度浮点型(Double:D),单位是米/刻。)
然后你就会发现飞出了一个红石。
好像也没什么稀奇的。但别忘了,一些全身由人类五脏中以代谢功能为主的一个器官构成的人会玩出一些新花样,比如制作一个神奇的方块动画。
如果你不是这样的人,那么你可以干些其他的实验,比如一直重复执行这条指令,命令方块会帮你造出一个很神奇的建筑。
你也可以乱改数据,这新花样是有很大的发挥空间的。
——第四节:结束
现在我们来总结一下:
[必]BlockState(复合标签)
——[必]Name(字符串):这个正在下落的方块的ID
——Probr /erties(复合标签):可选,这个正在下落的方块的方块状态
[必]Time(Int整形):该下落的方块已存在的刻数,不设置默认为0。如为0,则当Time从0变为1时,如该实体的位置上的方块与其存储的方块id一致,则继续下落,并删除该方块。不一致,则删除该实体。如不为0,当Time值大于600(30秒)或Time值大于100(5秒)时超出建筑限制(y>255或<0),就变为掉落物。
TileEntityData(复合标签):该实体存储的方块的方块实体标签
Drobr /Item(Byte字节型:1或0[true|false]):该实体被破坏后是否掉落其方块的物品形式。为1时掉落,但如果其方块没有对应的物品则仍然不会有物品掉落。
HurtEntities(Byte字节型:1或0[true|false]):该实体掉落时碰到其他实体是否对其造成伤害。为1时造成。
FallHurtMax(Int整形):被砸中的实体所承受的伤害上限。一般的方块默认为40滴血
FallHurtAmount(Float单精度浮点型):给被砸中的实体造成的伤害=FallDistance(当前实体已经坠落的距离)×FallHurtAmount(该标签)。一般的方块默认为2。
OK本章就到这里了,我们下一章再见。
===========资料============
——下落的方块历史
Java版Infdev
20100618——加入了应用于沙子和沙砾的ID FallingSand。
Java版
1.0.0——Beta 1.9 Prerelease 6——加入了可以下落的方块龙蛋。
1.4.2——12w41a——加入了可以下落的方块铁砧。
1.7.2——13w39a——加入了可以下落的方块红沙。
1.12——17w06a——加入了可以下落的方块混凝土粉末。
1.13——17w47a——重命名 FallingSand 到 falling_block。
1.14——18w45a——加入了可以下落的方块脚手架。
携带版Albr /ha
0.6.0——沙子和沙砾现在可以下落了。
0.9.0——build 1——加入了可以下落的方块红沙。
0.12.1——build 1——加入了可以下落的方块铁砧。
携带版
1.0.0——albr /ha 0.17.0.1——加入了可以下落的方块龙蛋。
1.1.0——albr /ha 1.1.0.0——加入了可以下落的方块混凝土粉末。
基岩版
1.8.0——beta 1.8.0.8——加入了可以下落的方块脚手架。
原主机版
TU1——————1.00———————————加入了可以下落的方块沙子和沙砾。
TU9——CU1——————Patch 1——————加入了可以下落的方块龙蛋。
TU14——————1.05———————1.0.1——加入了可以下落的方块铁砧。
TU31——CU19——1.22—Patch 3——————加入了可以下落的方块红沙。
TU53——CU43——1.49—Patch 23——1.0.3——加入了可以下落的方块混凝土粉末。
—————————1.83——————————加入了可以下落的方块脚手架。
New Nintendo 3DS版
0.1.0——加入了可以下落的方块沙子、沙砾、红沙和铁砧。
1.7.10——加入了可以下落的方块龙蛋。
1.9.19——加入了可以下落的方块混凝土粉末。
++++++++++++++++
王五正在翻看Minecraft Wiki中文,去学习下落的方块的使用方式。张三在旁边修理刷物机。
张三叮叮当当地把刷物机搞了一阵子后,发现得出去到主城东方的那座山里的黑市买些材料。由于他们几个的工作,导致他们的基地是在离主城很远的一座山下面。如果马不停蹄,最快也要三天才能到那里。于是他就收拾了工具,打算把这事情先放一放。
张三收拾着工具,突然发现门被打开了,走进来一个人。张三想把这人哄出去,想了一下最后站起来问:“你是谁?你从哪儿来?到这要干什么?”
他回答:“我叫刘一,从主城丁龙区来,来这是王五邀请我的。”刘一说着,眼角的余光发现王五愁眉苦脸。他很好奇,正好王五也注意到刘一来了,便招呼刘一过来。张三见是王五请来的,便不再说什么。
刘一第一句话就是:“王五啊,发生甚么事了?”
王五打开了几张游戏截图给刘一看。刘一一看,原来是刚才,有两个下落的方块,在三十多米高的高空,一个质量九百多公斤,一个质量八百多公斤。王五说,有一个是他一直重复执行弄出来的沙子,就是很奇怪一生成就消失,而且他都写了是diamond_block,大佬你能不能教教我这是怎么一回事,帮助修复一下我的下落的方块。刘一说:“可以。你在游戏里弄来弄去,不好,得灵活变通,去看看Minecraft Wiki中文。”王五反驳:“刚刚我就在看唉,这就是我按照上面弄出来的!”刘一思考了一下,回:“你把指令给我看一下,应该是Time值的问题。”
王五打开了命令方块,只见上面写着:
/summon minecraft:falling_block {BlockState:{Name:“minecraft:diamond_block“},Time:1}
刘一仔细观察,发现了一个问题:“你这没有坐标啊,应该是/summon minecraft:falling_block ~~~{BlockState:{Name:“minecraft:diamond_block“},Time:1}。”
“哦,原来如此。”王五这才想起来/summon的格式是/summon <实体id>[坐标:XYZ][NBT]。
试了试,可以正常下落,但还是沙子。
“下落的问题是解决了,但这仍然是沙子啊,不是钻石块。这该怎么办?”王五看着刘一,眼睛睁的贼大。刘一看着这个好奇宝宝,发现越看越可爱,于是摸了一下王五的头,说:“这应该是你标签名没写对或是id没对。”
王五仔细检查了一下,BlockState正确,Name正确,minecraft:diamond_block也正确。
刘一这才发现事情不简单,皱起了眉头仔细思考。他突然看到游戏界面左上角的Minecraft 1.12.2,灵光一闪,拍手叫道:“是不是版本的问题?!”
王五一听,赶紧打开Minecraft Wiki中文,点开History,发现了一个问题:下落的方块中文百科最早也已经是2020年4月13日09:31。王五试图在英文百科上找,发现页面虽早,但数据值那个页面早已不见。
这下子该如何是好?在发现Minecraft Wiki其早期记载的资料已经无法参考了之后,两人就像是热锅上的蚂蚁,因为对于这种事情两人还是第一次遇到。
张三已经整理完了工具,正无事可干打算拿起手机看一下敦煌防护林已经反转多少次时,突然发现旁边还有两个蹦来蹦去的蚂蚁,于是拿起了一个西瓜,问两人发生了什么事。
在了解了具体情况后,张三感到震惊——Minecraft Wiki对于早期的资料保护竟然这么懈怠,万一以后Minecraft30周年,新玩家想要回顾的时候,如果Minecraft Wiki还这样,那么他们或许就只知道Minecraft有猪灵和僵尸猪灵,却不知道在很久以前只有僵尸猪人。这还是比较重要的资料,如果像是更生僻的比如NBT,或许情况会更糟。
“互联网还真是没有记忆啊。”张三感叹道。感叹虽感叹,张三还是仔细想了一下。这一想,他突然想到一点:“扁平化!”
刘一愣了一下,然后赶紧打开扁平化的页面。果真,还真有这么一句:
下落的方块的Block数据和Data数据合并成了BlockState。
但这里并没有讲到“Block”和“Data”到底是个什么鬼。
进展很快就停止了。三人继续想,但再也没有了新点子。
最怕空气突然安静。
王五再一次打开下落的方块页面。他突然发现还有一个:
教程/下落的方块
点开历史,他很快从悲哀转为震惊,接着又转为惊喜,最后情绪化成了声音:“哦吼。哦吼!哦吼!!!”
三人迅速浏览了历史,得出了一些重要的结论:
①Java1.13扁平化之前,BlockState是分为两个标签:Data和Block
②Block是字符串,在里面写入方块英文id就可以指定该下落的方块代表的方块
③Data在教程/下落的方块里并未提及,但应该是和Probr /erties一样,值为复合标签,代表该方块的方块状态。
④在更早的版本(1.8以前),没有Block标签,而是使用TileID标签。TileID应该是Int整形,在值里填上方块数字id就可以指定该下落的方块所代表的方块。这就可以解释为什么现在的WIki在介绍Time标签时有这么一句话:“Time刻数在从0变为1的这段时间里,如果在它的位置上方块的 ID 和实体 TileID 都相同,那么这个方块就不会被删除......”
最终,王五得出了一个正确的指令:
/summon minecraft:falling_block ~~~{Block:“minecraft:diamond_block“,Time:1}
使用该指令,王五成功在1.12.2版本召唤出一个下落的钻石块!