第一百五十九章 深入了解NBT樹和NBT路徑
在上一章,你應(yīng)該已經(jīng)理解了什么叫作NBT樹,但理解不代表會(huì)運(yùn)用。要真正搞懂NBT樹的理念,我們得投入實(shí)踐,學(xué)會(huì)閱讀NBT樹甚至表示出一個(gè)NBT樹。
NBT數(shù)據(jù)樹常常會(huì)表示成下面這樣的格式:
<數(shù)據(jù)類型>[root或其他具體名稱]:根、父級(jí)標(biāo)簽或其他具體的名稱或描述
│
├<數(shù)據(jù)類型>[名稱]:值或描述
......
└<數(shù)據(jù)類型>[名稱]:值或描述
注:在上面的格式中,<>代表必定會(huì)出現(xiàn),[]代表可能會(huì)出現(xiàn)(含義跟指令格式中的一樣)。
許多網(wǎng)站和程序,比如Minecraft Wiki、常用的Java版NBT編輯器NBTExplorer,都采用了上述格式來表示NBT。
舉個(gè)簡(jiǎn)單的例子,在Minecraft Wiki上,Java版書與筆的物品NBT是這么表示出來的:
? tag:父級(jí)標(biāo)簽
└? pages:書與筆的各個(gè)頁(yè)面。
空└?:一個(gè)單頁(yè)。每一頁(yè)是一個(gè)字符串,不能超過32767個(gè)字符。
在上面的這個(gè)例子中,由于Minecraft Wiki使用一個(gè)圖片標(biāo)識(shí)來表示數(shù)據(jù)類型,所以這里用一些特殊符號(hào)來代替:
?——Compound復(fù)合標(biāo)簽
?——List列表
?——String字符串
仔細(xì)觀察Minecraft Wiki給出的NBT樹,結(jié)合我們前面所學(xué)的知識(shí),你應(yīng)該不難得出上面這個(gè)例子所表示的意思:
『對(duì)于物品書與筆,在其物品NBT標(biāo)簽中的tag復(fù)合標(biāo)簽下,有一個(gè)名為pages的列表型標(biāo)簽。這個(gè)pages列表是一個(gè)由多個(gè)字符串類型的值組成的列表,每個(gè)值都代表著書與筆中的一頁(yè),且每個(gè)值都不得擁有超過32767個(gè)字符?!?p> 什么?你很難理解?或許我們需要睜大眼睛,逐行研究上面的例子。
第一行:? tag:父級(jí)標(biāo)簽
根據(jù)上面的格式『<數(shù)據(jù)類型>[root或其他具體名稱]:根、父級(jí)標(biāo)簽或其他具體的名稱或描述』,我們不難知道這在表示一個(gè)名為tag的復(fù)合標(biāo)簽。同時(shí),它被解釋為『父級(jí)標(biāo)簽』,說明Minecraft Wiki在這里給出的NBT樹是在描述這個(gè)標(biāo)簽的孩子(也就是值)。
等等,為什么Minecraft Wiki不直接從根開始,而是從這個(gè)tag標(biāo)簽開始呢?
回憶一下第十一卷的內(nèi)容,tag標(biāo)簽是物品通用標(biāo)簽內(nèi)的一個(gè)標(biāo)簽,用來儲(chǔ)存物品的額外信息。所有額外的物品標(biāo)簽都在tag標(biāo)簽內(nèi),因此Minecraft Wiki不從根開始描述的原因也就不難理解——使文章詳略得當(dāng)。
問題解決,我們來看看第二行:└? pages:書與筆的各個(gè)頁(yè)面。
最開始的└意味著在這里,NBT數(shù)據(jù)樹的這條樹枝上有一個(gè)節(jié)點(diǎn),而且由于└沒有繼續(xù)向下延伸,因此這個(gè)節(jié)點(diǎn)是該樹枝上最后一個(gè)節(jié)點(diǎn)。第二個(gè)?代表的意思很明確,即該節(jié)點(diǎn)對(duì)應(yīng)的NBT標(biāo)簽是個(gè)列表。『pages』是該列表的標(biāo)簽名,而后面的『書與筆的各個(gè)頁(yè)面。』是對(duì)該標(biāo)簽的一個(gè)描述。
第三行更加簡(jiǎn)單:└?:一個(gè)單頁(yè)。每一頁(yè)是一個(gè)字符串,不能超過32767個(gè)字符。
最開始的└不用說,?估計(jì)也不用說。但?后面的標(biāo)簽名稱呢?
還是那句話,這是個(gè)列表,列表是由多個(gè)相同類型的值組成,而不是標(biāo)簽。換句話說,這部分NBT樹實(shí)際上描述的不是個(gè)標(biāo)簽,而是個(gè)值,自然也就不需要給出名稱,因?yàn)闆]有名稱。
冒號(hào)右邊的很明顯,是個(gè)對(duì)值的描述,相信大家都看得懂這里的中文,我就不再闡述。
現(xiàn)在,你肯定已經(jīng)擁有閱讀Minecraft Wiki上NBT樹狀圖的基本素養(yǎng)。來嘗試一下下面的這個(gè)NBT樹:
?實(shí)體數(shù)據(jù)值
│實(shí)體共通標(biāo)簽
│活體共通標(biāo)簽*
│生物共通標(biāo)簽
├?? Size:史萊姆的大小。最小為0,即小型史萊姆大小;最大值為126,超過126的值將當(dāng)作126處理。
└? wasOnGround:表示史萊姆是否正在接觸地面。
圖示:
??—— Int整型
?—— Boolean布爾值(Byte字節(jié)型)
*Minecraft WIki把生物共通標(biāo)簽給拆開了?啥時(shí)候多出個(gè)活體共通標(biāo)簽?
上面唯一需要注意的一點(diǎn)是,你應(yīng)該知道Byte字節(jié)型有兩個(gè)種類的值,一個(gè)是普通的數(shù)值,一個(gè)是布爾值。為方便區(qū)分,Minecraft Wiki將布爾值類型從Byte字節(jié)型中獨(dú)立出來,成為Boolean布爾值,但實(shí)際上在NBT中還是Byte字節(jié)型。
這里就暫時(shí)不放參考答案(實(shí)際上是因?yàn)閼械脤懀?,相信大家都能夠看懂上面的NBT樹狀圖。
搞懂NBT樹狀圖后,接下來讓我們繼續(xù)了解NBT路徑。
在上一章,我們基本上搞清楚了NBT路徑是什么。比如對(duì)于下面這個(gè)NBT路徑:
Apple[0].Cen.Sama
你應(yīng)該知道它有三個(gè)意思:
①這代表Sama標(biāo)簽的路徑,你可以通過這個(gè)路徑來找到這個(gè)標(biāo)簽
?、谶@代表Sama這個(gè)標(biāo)簽
?、圻@代表Sama這個(gè)標(biāo)簽的值
而在Minecraft中,NBT路徑最常見的意思就是第二和第三個(gè)——代表一個(gè)標(biāo)簽和或其值?;蛘哒f,NBT路徑最常見的作用,就是用來尋找并獲取到一個(gè)標(biāo)簽,然后對(duì)這個(gè)標(biāo)簽的值進(jìn)行一些操作。
舉個(gè)簡(jiǎn)單的例子,還記得你在第一百零八章掉下來的鉆石嗎?把它拿過來再看看:
{Age:0s,Health:5s,PickupDelay:0s,Item:{Count:1b,id:“minecraft:diamond“}
↑↑↑這是你掉的鉆石的NBT,需要注意這只不過是一個(gè)簡(jiǎn)化版↑↑↑
如果我們要使用/data指令來獲取到這顆鉆石Age標(biāo)簽的值,這個(gè)NBT路徑該怎么寫?
很簡(jiǎn)單,就一個(gè)單詞:
Age
然后在聊天框中就會(huì)返回:0s
但其實(shí)你也可以這么寫:
{Health:5s}.Age
這是怎么一回事?前面的{Health:5s}是咋冒出來的?
這雖然是個(gè)多此一舉的寫法,但我們從中也可以了解到NBT路徑的一個(gè)特殊功能:匹配特定的NBT標(biāo)簽
有時(shí)候,我們固然想要得到一個(gè)標(biāo)簽的值,但當(dāng)我們想把范圍縮小時(shí),比如想要獲取所有鉆石掉落物的Age值,我們可能就無從下手。但其實(shí),這有兩種方法:
第一種,使用目標(biāo)選擇器;第二種,在NBT路徑內(nèi)加入一些匹配標(biāo)簽用的值。
其實(shí)這兩種方法的原理都一樣,但由于目標(biāo)選擇器的nbt參數(shù)我們不現(xiàn)在講,因此先來看看第二種方法。
首先,路徑『Age』雖然是正確的,但其實(shí)在這里省略了一些東西。
什么東西?沒錯(cuò),根標(biāo)簽?zāi)兀?p> 一般情況下,根標(biāo)簽都會(huì)被省略不寫。如果不省略,那整個(gè)路徑會(huì)變成:
{}.Age
其中,{}是根標(biāo)簽的路徑,也就是代指根標(biāo)簽。由于根標(biāo)簽是個(gè)復(fù)合標(biāo)簽,所以用大括號(hào)表示。
然后,對(duì)比『{Health:5s}.Age』和『{}.Age』,我們會(huì)發(fā)現(xiàn)兩者唯一的區(qū)別就在于根標(biāo)簽擁有一個(gè)值:Health:5s
很奇怪吧?明明路徑就可以代表標(biāo)簽的值,為什么還要專門寫一個(gè)特定的值呢?
其實(shí),給路徑中的一個(gè)標(biāo)簽加上值看上去多此一舉,但實(shí)際上很有用。因?yàn)樗幸粋€(gè)功能——過濾。
如果不加上Health:5s,那么單獨(dú)的{}將代表任何一個(gè)根標(biāo)簽。但如果加上Health:5s,那么這僅能代表含有Health:5s這個(gè)標(biāo)簽的根標(biāo)簽。
比如{Health:5s}.Age雖然能選中上面鉆石的Age值,但一定選不中下面這個(gè)鉆石的Age值:
{Age:-1s,Health:32767s,PickupDelay:0s,Item:{Count:1b,id:“minecraft:diamond“}
同理,對(duì)于路徑『Age』,我們也可以寫成這樣:
Age:100s
這看起來是一個(gè)SNBT,但其實(shí)也是個(gè)路徑,意思是尋找根標(biāo)簽內(nèi)值為100s的Age標(biāo)簽。
總而言之,如果給NBT路徑內(nèi)的某個(gè)或多個(gè)標(biāo)簽加上一個(gè)特定的值,那就能起到過濾的作用,使結(jié)果更加精確。
你現(xiàn)在應(yīng)該知道如何獲取所有鉆石掉落物的Age值吧?讓我們?cè)囈辉嚕?p> /execute as @e run data get entity @s {Item:{Count:1b,id:“minecraft:diamond“}}.Age
返回:
鉆石擁有以下實(shí)體數(shù)據(jù):163s
鉆石擁有以下實(shí)體數(shù)據(jù):127s
鉆石擁有以下實(shí)體數(shù)據(jù):11451s
?。ㄉ厦娴膁ata指令之后再解釋)
GOOD!另外,你應(yīng)該能解釋『{Item:{Count:1b,id:“minecraft:diamond“}}.Age』的意思吧?試一試描述一下它的意思。
上面的內(nèi)容只是NBT路徑的冰山一角,在下一章,我們將會(huì)繼續(xù)深入了解NBT路徑,但至于何時(shí)更新是個(gè)大問題。