第一百五十九章 深入了解NBT樹和NBT路徑
在上一章,你應(yīng)該已經(jīng)理解了什么叫作NBT樹,但理解不代表會運(yùn)用。要真正搞懂NBT樹的理念,我們得投入實(shí)踐,學(xué)會閱讀NBT樹甚至表示出一個(gè)NBT樹。
NBT數(shù)據(jù)樹常常會表示成下面這樣的格式:
<數(shù)據(jù)類型>[root或其他具體名稱]:根、父級標(biāo)簽或其他具體的名稱或描述
│
├<數(shù)據(jù)類型>[名稱]:值或描述
......
└<數(shù)據(jù)類型>[名稱]:值或描述
注:在上面的格式中,<>代表必定會出現(xiàn),[]代表可能會出現(xiàn)(含義跟指令格式中的一樣)。
許多網(wǎng)站和程序,比如Minecraft Wiki、常用的Java版NBT編輯器NBTExplorer,都采用了上述格式來表示NBT。
舉個(gè)簡單的例子,在Minecraft Wiki上,Java版書與筆的物品NBT是這么表示出來的:
? tag:父級標(biāo)簽
└? pages:書與筆的各個(gè)頁面。
空└?:一個(gè)單頁。每一頁是一個(gè)字符串,不能超過32767個(gè)字符。
在上面的這個(gè)例子中,由于Minecraft Wiki使用一個(gè)圖片標(biāo)識來表示數(shù)據(jù)類型,所以這里用一些特殊符號來代替:
?——Compound復(fù)合標(biāo)簽
?——List列表
?——String字符串
仔細(xì)觀察Minecraft Wiki給出的NBT樹,結(jié)合我們前面所學(xué)的知識,你應(yīng)該不難得出上面這個(gè)例子所表示的意思:
『對于物品書與筆,在其物品NBT標(biāo)簽中的tag復(fù)合標(biāo)簽下,有一個(gè)名為pages的列表型標(biāo)簽。這個(gè)pages列表是一個(gè)由多個(gè)字符串類型的值組成的列表,每個(gè)值都代表著書與筆中的一頁,且每個(gè)值都不得擁有超過32767個(gè)字符。』
什么?你很難理解?或許我們需要睜大眼睛,逐行研究上面的例子。
第一行:? tag:父級標(biāo)簽
根據(jù)上面的格式『<數(shù)據(jù)類型>[root或其他具體名稱]:根、父級標(biāo)簽或其他具體的名稱或描述』,我們不難知道這在表示一個(gè)名為tag的復(fù)合標(biāo)簽。同時(shí),它被解釋為『父級標(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)簽,用來儲存物品的額外信息。所有額外的物品標(biāo)簽都在tag標(biāo)簽內(nèi),因此Minecraft Wiki不從根開始描述的原因也就不難理解——使文章詳略得當(dāng)。
問題解決,我們來看看第二行:└? pages:書與筆的各個(gè)頁面。
最開始的└意味著在這里,NBT數(shù)據(jù)樹的這條樹枝上有一個(gè)節(jié)點(diǎn),而且由于└沒有繼續(xù)向下延伸,因此這個(gè)節(jié)點(diǎn)是該樹枝上最后一個(gè)節(jié)點(diǎn)。第二個(gè)?代表的意思很明確,即該節(jié)點(diǎn)對應(yīng)的NBT標(biāo)簽是個(gè)列表。『pages』是該列表的標(biāo)簽名,而后面的『書與筆的各個(gè)頁面。』是對該標(biāo)簽的一個(gè)描述。
第三行更加簡單:└?:一個(gè)單頁。每一頁是一個(gè)字符串,不能超過32767個(gè)字符。
最開始的└不用說,?估計(jì)也不用說。但?后面的標(biāo)簽名稱呢?
還是那句話,這是個(gè)列表,列表是由多個(gè)相同類型的值組成,而不是標(biāo)簽。換句話說,這部分NBT樹實(shí)際上描述的不是個(gè)標(biāo)簽,而是個(gè)值,自然也就不需要給出名稱,因?yàn)闆]有名稱。
冒號右邊的很明顯,是個(gè)對值的描述,相信大家都看得懂這里的中文,我就不再闡述。
現(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)閼械脤懀嘈糯蠹叶寄軌蚩炊厦娴腘BT樹狀圖。
搞懂NBT樹狀圖后,接下來讓我們繼續(xù)了解NBT路徑。
在上一章,我們基本上搞清楚了NBT路徑是什么。比如對于下面這個(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)簽和或其值。或者說,NBT路徑最常見的作用,就是用來尋找并獲取到一個(gè)標(biāo)簽,然后對這個(gè)標(biāo)簽的值進(jìn)行一些操作。
舉個(gè)簡單的例子,還記得你在第一百零八章掉下來的鉆石嗎?把它拿過來再看看:
{Age:0s,Health:5s,PickupDelay:0s,Item:{Count:1b,id:“minecraft:diamond“}
↑↑↑這是你掉的鉆石的NBT,需要注意這只不過是一個(gè)簡化版↑↑↑
如果我們要使用/data指令來獲取到這顆鉆石Age標(biāo)簽的值,這個(gè)NBT路徑該怎么寫?
很簡單,就一個(gè)單詞:
Age
然后在聊天框中就會返回: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í)在這里省略了一些東西。
什么東西?沒錯,根標(biāo)簽?zāi)兀?p> 一般情況下,根標(biāo)簽都會被省略不寫。如果不省略,那整個(gè)路徑會變成:
{}.Age
其中,{}是根標(biāo)簽的路徑,也就是代指根標(biāo)簽。由于根標(biāo)簽是個(gè)復(fù)合標(biāo)簽,所以用大括號表示。
然后,對比『{Health:5s}.Age』和『{}.Age』,我們會發(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“}
同理,對于路徑『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值吧?讓我們試一試!
/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
(上面的data指令之后再解釋)
GOOD!另外,你應(yīng)該能解釋『{Item:{Count:1b,id:“minecraft:diamond“}}.Age』的意思吧?試一試描述一下它的意思。
上面的內(nèi)容只是NBT路徑的冰山一角,在下一章,我們將會繼續(xù)深入了解NBT路徑,但至于何時(shí)更新是個(gè)大問題。