第一百五十九章 深入了解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è)字符?!?p> 什么?你很難理解,?或許我們需要睜大眼睛,,逐行研究上面的例子。
第一行:? 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è)列表?!簆ages』是該列表的標(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,,即小型史萊姆大?。蛔畲笾禐?26,,超過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路徑是什么。比如對于下面這個(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)簽,,然后對這個(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
?。ㄉ厦娴膁ata指令之后再解釋)
GOOD!另外,,你應(yīng)該能解釋『{Item:{Count:1b,,id:“minecraft:diamond“}}.Age』的意思吧?試一試描述一下它的意思,。
上面的內(nèi)容只是NBT路徑的冰山一角,,在下一章,我們將會繼續(xù)深入了解NBT路徑,,但至于何時(shí)更新是個(gè)大問題,。