第六十章 基巖版的JSON文本(破200收藏紀(jì)念)
JSON文本在Java版很常用。在基巖版雖然能用的地方少了很多,但仍然很有用處。
基巖版的JSON文本主要用于指令、書(shū)與筆的文本和告示牌的文本上。由于基巖版指令的限制,我們只能在/tellraw和/titleraw兩個(gè)指令中用到JSON文本。雖然能用的地方極其少,我們?nèi)匀坏脤W(xué)習(xí)學(xué)習(xí),就因?yàn)?tellraw這條指令極其有用。
基巖版的JSON文本的基礎(chǔ)格式如下:
{“rawtext“:[]}
在基巖版中,每串JSON文本的最外層必然是rawtext組件。rawtext的值是JSON對(duì)象列表,也就是由多個(gè)JSON對(duì)象組成的列表。你可以把JSON對(duì)象看作是NBT中的復(fù)合標(biāo)簽(兩者其實(shí)沒(méi)多大差別),方便理解。
基巖版的JSON文本組件相比Java版要少許多。不算rawtext的話,基巖版一共只有五個(gè)組件:
\\內(nèi)容組件\\
text(值:文本)
selector(值:文本)
translate(值:文本)
score(值:JSON對(duì)象,相當(dāng)于NBT的復(fù)合標(biāo)簽)
\ranslate配套組件\\
with(值:由多個(gè)文本組成的列表)
最基礎(chǔ)的組件還是text,用法和Java版的一模一樣:
{“rawtext“:[{“text“:“Hello!“}]}
這解析后會(huì)變成:Hello!
你有沒(méi)有注意到,基巖版甚至連文本顏色格式組件都被閹割了,也就是說(shuō)我們無(wú)法使用color組件來(lái)修改文字顏色。既然我們無(wú)法使用color之類(lèi)的組件,那么我們?cè)撊绾涡薷奈谋镜念伾透袷剑?p> 你是不是忘記了一個(gè)東西:§
由于基巖版可以自由使用§來(lái)修改文本的顏色和格式,因此Mojang就把color之類(lèi)的文本顏色格式組件給切了。
在基巖版的JSON文本中使用§,需要注意兩點(diǎn):
?、佟毂仨氁旁趦?nèi)容組件的值中,不能放在組件名等其他地方。雖然放在其他地方在命令方塊中也會(huì)生效,但JSON文本就無(wú)法被游戲正確識(shí)別并輸出了。
?、谑褂谩旌笥浀靡皶r(shí)用§r來(lái)重置文字樣式,不然會(huì)把§右邊的所有文本都修改了樣式。比如:
{“rawtext“:[{“text“:“§eHello!“},{“text“:“Minecraft“}]}
這將會(huì)輸出:Hello!Minecraft(都是黃色)
如果是{“rawtext“:[{“text“:“§eHello!§r“},{“text“:“Minecraft“}]},則只會(huì)把“Hello!”一段變成黃色。
selector組件可以輸出實(shí)體名稱(chēng),其值必須填的是目標(biāo)選擇器。比如:
{“rawtext“:[{“selector“:“@p“}]}
這將會(huì)輸出距離執(zhí)行地點(diǎn)最近玩家的名稱(chēng)。假設(shè)距離執(zhí)行地點(diǎn)最近的玩家叫做『Phigros』,那么這將會(huì)輸出:Phigros
selector的使用還是很簡(jiǎn)單的。但請(qǐng)注意,你不能把selector當(dāng)做text一樣使用。原因很簡(jiǎn)單:其值必須是個(gè)目標(biāo)選擇器。
如果你把selector當(dāng)做text一樣用,比如這樣子填寫(xiě):
{“rawtext“:[{“selector“:“HelloMinecraft“}]}
你會(huì)驚奇地發(fā)現(xiàn)執(zhí)行指令后,沒(méi)有任何的文本輸出,也沒(méi)有任何的報(bào)錯(cuò)信息。
這是為什么呢?因?yàn)閟elector的值必須是個(gè)目標(biāo)選擇器,你這樣填就相當(dāng)于要輸出玩家HelloMinecraft的名稱(chēng),而游戲中又沒(méi)有叫做HelloMinecraft的玩家,自然就不會(huì)輸出。但如果真的有一個(gè)叫做HelloMinecraft的玩家且在線,就會(huì)正常輸出『HelloMinecraft』。
translate組件是這五個(gè)組件中最難的一個(gè),因?yàn)樗行┥婕暗組inecraft的模組、資源包開(kāi)發(fā)。為何這么說(shuō)?因?yàn)閠ranslate組件可以讓一段文字以目標(biāo)玩家的語(yǔ)言輸出。
在學(xué)習(xí)translate的用法之前,我們要了解一個(gè)東西:本地化鍵(也稱(chēng)『翻譯識(shí)別符』)
每一種語(yǔ)言都有自己對(duì)應(yīng)的語(yǔ)言文件,比如美式英語(yǔ)對(duì)應(yīng)的就是en_us.lang,中文簡(jiǎn)體對(duì)應(yīng)的就是zh_cn.lang。游戲中同一個(gè)地方的文本會(huì)翻譯成不同的語(yǔ)言。這時(shí)候問(wèn)題來(lái)了:我們?cè)撊绾卧诓煌恼Z(yǔ)言文件中正確找到用于這個(gè)地方的文本呢?
這時(shí)候本地化鍵就出場(chǎng)了。
把一個(gè)地方的文本在不同語(yǔ)言中的翻譯都綁定到一串不變的ID上,根據(jù)ID找到對(duì)應(yīng)的翻譯文本,不就解決這個(gè)問(wèn)題了嗎?
舉個(gè)例子,在下面兩個(gè)不同的語(yǔ)言文件中分別有這么一行:
en_us.lang:
server.help.getgold=You can get gold by selling items and playing games.For example, you may get 500 coins if you win a game of Bed War.#
zh_cn.lang:
server.help.getgold=您可以通過(guò)售賣(mài)物品、玩小游戲來(lái)獲得金幣。比如當(dāng)你贏得一局起床戰(zhàn)爭(zhēng)時(shí),您可能會(huì)獲得500枚金幣。#
我們只需要在需要用到這一串文本的地方放上『server.help.getgold』,游戲就會(huì)自動(dòng)根據(jù)不同的語(yǔ)言將這一串本地化鍵替換成對(duì)應(yīng)語(yǔ)言的文本。
JSON文本內(nèi)的translate組件就是干這行的。在translate的值內(nèi)寫(xiě)上本地化鍵,游戲就會(huì)根據(jù)不同的語(yǔ)言將對(duì)應(yīng)的內(nèi)容呈現(xiàn)出來(lái)。比如:
{“rawtext“:[{“translate“:“server.help.getgold“}]}
如果你使用的是中文簡(jiǎn)體,最終這將會(huì)輸出:『您可以通過(guò)售賣(mài)物品、玩小游戲來(lái)獲得金幣。比如當(dāng)您贏得一局起床戰(zhàn)爭(zhēng)時(shí),你可能會(huì)獲得500枚金幣?!?p> 如果你使用的是美式英語(yǔ),這反而會(huì)輸出:『You can get gold by selling items and playing games.For example, you may get 500 coins if you win a game of Bed War.』
現(xiàn)在你明白了嗎?
(注:上面這個(gè)server.help.getgold本地化鍵是編的,但接下來(lái)的幾個(gè)本地化鍵都是真實(shí)存在于游戲中的。)
translate的使用肯定沒(méi)有這么簡(jiǎn)單,這只是最基礎(chǔ)的用法而已。有時(shí)候,本地化鍵對(duì)應(yīng)的文本內(nèi)會(huì)有一些特殊的部分。比如『death.attack.onFire』,如果你只是這么用它:
{“rawtext“:[{“translate“:“death.attack.onFire“}]}
最終它會(huì)輸出:
%1$s 被燒死了
這是怎么回事?因?yàn)槲覀儧](méi)有指定死亡的東西是什么。如果我們要指定,就得用到translate的配套組件:with
with的值是由多個(gè)文本組成的列表。至于為什么是個(gè)列表,是因?yàn)橛行r(shí)候會(huì)有多個(gè)特殊的部分,這時(shí)候就需要使用列表來(lái)分別指定每個(gè)部分是什么。
我們待會(huì)再研究具有多個(gè)特殊部分的情況。先來(lái)試試使用with指定死亡的東西是『張三』:
{“rawtext“:[{“translate“:“death.attack.onFire“,“with“:[“張三“]}]}
這將會(huì)輸出:張三被燒死了
現(xiàn)在我們?cè)賮?lái)看看有多個(gè)特殊部分的情況:
{“rawtext“:[{“translate“:“death.attack.arrow.item“}]}
這將會(huì)輸出:%1$s 被%2$s 用%3$s 射殺
這句話雖然很短,但有三個(gè)特殊的部分。如何正確指定這三個(gè)特殊部分呢?按照從左到右的順序指定:
{“rawtext“:[{“translate“:“death.attack.arrow.item“,“with“:[“枯藤“,“老樹(shù)“,“昏鴉“]}]}
這會(huì)輸出:枯藤被老樹(shù)用昏鴉射殺
一般情況下,特殊部分會(huì)按照從左到右的順序一一對(duì)應(yīng)列表內(nèi)的元素。在上面的例子中,%1$s最靠左,“枯藤”也在列表的最左邊,因此%1$s就被“枯藤”替換了。剩下的%2$s和%3$s同理。
這就是translate組件一般的用法。除了這個(gè)用法外,translate還能被當(dāng)做text組件一樣用,且比text組件多出了一個(gè)沒(méi)啥用的功能:自定義特殊部分
特殊部分有兩種自定義的格式:
%%s
%%#(#為列表內(nèi)元素從左到右排列的序號(hào))
先來(lái)說(shuō)說(shuō)%%s。%%s的用法和上面的%1$s、%2$s之類(lèi)的一模一樣,都是從左到右一一對(duì)應(yīng)。比如:
{“rawtext“:[{“translate“:“你好%%s!這里有一些關(guān)于%%s的說(shuō)明?!?,“with“:[“新手“,“空島戰(zhàn)爭(zhēng)“]}]}
這會(huì)輸出:你好新手!這里有一些關(guān)于空島戰(zhàn)爭(zhēng)的說(shuō)明。
%%#的功能和%%s比較不一樣。%%#的#實(shí)際上是列表內(nèi)各個(gè)元素從左到右的排列數(shù)字。比如%%1在上面的列表中就代表著『新手』。也就是說(shuō),如果這樣子填寫(xiě):
{“rawtext“:[{“translate“:“你好%%1!這里有一些關(guān)于%%1的說(shuō)明?!?,“with“:[“新手“,“空島戰(zhàn)爭(zhēng)“]}]}
最終會(huì)輸出:你好新手!這里有一些關(guān)于新手的說(shuō)明。
上面的例子中,%%s和%%#都是獨(dú)立使用。如果兩者一起使用會(huì)發(fā)生什么呢?
來(lái)看看下面這個(gè)例子:
{“rawtext“:[{“translate“:“歡迎來(lái)到%%s,%%1!您今日的%%s還未領(lǐng)取!“,“with“:[“EaseCation“,“每日簽到獎(jiǎng)勵(lì)“,“一個(gè)普通的路人“]}]}
猜一猜,最終這會(huì)輸出什么?
你是不是以為,最終這會(huì)輸出:歡迎來(lái)到EaseCation,EaseCation!您今日的每日簽到獎(jiǎng)勵(lì)還未領(lǐng)??!
如果你這樣想,就錯(cuò)了。實(shí)際上輸出的是:歡迎來(lái)到EaseCation,一個(gè)普通的路人!您今日的每日簽到獎(jiǎng)勵(lì)還未領(lǐng)取!
這是怎么一回事?當(dāng)%%s和%%#一起使用的時(shí)候,游戲會(huì)優(yōu)先把%%s替換掉。按照從左到右的原則,第一個(gè)%%s被替換成了『EaseCation』,第二個(gè)%%s被替換成了『每日簽到獎(jiǎng)勵(lì)』。然后游戲才會(huì)替換%%#。這時(shí)候神奇的地方來(lái)了,由于%%s使用過(guò)的列表元素%%#就不能再使用,因此%%#的順序得從第三個(gè)元素開(kāi)始算起,最終導(dǎo)致%%1被替換成了『一個(gè)普通的路人』。
這就是translate和其配套with組件的全部?jī)?nèi)容,你學(xué)會(huì)了嗎?
最后的score組件簡(jiǎn)單且有用,它可以顯示記分板上的分?jǐn)?shù)。
score的值是JSON對(duì)象,你可以把它當(dāng)做是復(fù)合標(biāo)簽。對(duì)象內(nèi)有三個(gè)子組件:
name——選擇正在被記分板追蹤的目標(biāo),顯示ta的分?jǐn)?shù),值為文本。必須填寫(xiě)目標(biāo)選擇器或玩家名(假的也可以)。
objective——計(jì)分項(xiàng)名稱(chēng)。值為文本。
value[可選]——值為文本。如果指定了該項(xiàng),不管真實(shí)的分?jǐn)?shù)是多少,都會(huì)顯示為該項(xiàng)的值。
?。ㄗⅲ鹤髡邔?shí)驗(yàn)時(shí)發(fā)現(xiàn)value組件沒(méi)用,可能在目前的基巖版最新版中已經(jīng)刪去了該標(biāo)簽。作者實(shí)驗(yàn)的版本是基巖版1.18.2)
舉個(gè)例子。假設(shè)玩家Liben在計(jì)分項(xiàng)Primogems上的分?jǐn)?shù)為2431,我們可以這樣輸出他的分?jǐn)?shù):
{“rawtext“:[{“score“:{“name“:“Liben“,“objective“:“Primogems“}}]}
這將會(huì)輸出:2431
需要注意,當(dāng)name選定的目標(biāo)為多個(gè)時(shí),游戲?qū)?huì)按照目標(biāo)選擇器排列的順序輸出每個(gè)目標(biāo)的分?jǐn)?shù)。
現(xiàn)在你會(huì)使用基巖版的JSON文本了嗎?注意,一個(gè)JSON對(duì)象內(nèi)不能有多個(gè)內(nèi)容組件。當(dāng)一個(gè)對(duì)象內(nèi)有多個(gè)內(nèi)容組件時(shí),權(quán)重高的組件的內(nèi)容將會(huì)覆蓋權(quán)重低的組件。四個(gè)內(nèi)容組件的權(quán)重如下:
score<selector<text<translate
(注:該權(quán)重為作者實(shí)驗(yàn)得出)
這就是基巖版JSON文本的全部?jī)?nèi)容了。