◄教學►【1.9指令入門教學】[json篇] ◆提摩◆

大家好~我又來啦
這次打的是進階的教學
我會以你們已熟悉入門的前提下介紹
若遇到不懂的地方請回頭看我之前發的入門教學


json在Minecraft中佔有非常重要的地位,許多地方都使用json結構來儲存或執行。例如你可以在Minecraft的儲存資料夾的根目錄中找到launcher_profiles.json及usercache.json兩個檔案,若以記事本開啟,可以很明顯的看到裡面以文字儲存的訊息。以我的usercache.json為例,打開後裡面只有一段文字:
[{"name":"CottontailTeemo_","uuid":"afd5eaaa-f3d8-4a9f-9116-f50552880594","expiresOn":"2016-05-20 07:34:30 +0800"}]

首先要注意的是,json語法是由許多字串所構成,而每串字串會以引號包圍(不只限於「"」雙引號,之後會說明),以冒號做解釋,並以逗號分隔項目。以上面的例子說明,我的name(名稱)為CottontailTeemo_,uuid(使用者ID)為afd5eaaa-f3d8-4a9f-9116-f50552880594這一串,expiresOn(到期日期)為2016-05-20 07:34:30 +0800。

你也可以在Minecraft的儲存資料夾下方\assets\indexes找到1.9.json,或是將1.9.2.jar(路徑:
\versions\1.9.2,其他版本類推)解壓縮,也可以發現大量的json文件。

json語法也在遊戲中使用。當你在玩別人做好的地圖時,可以經常發現下列幾種情形:
.在對話框中出現彩色的字,字體有些正常、有些為粗體、而另一些有可能有下劃線或斜體,有些字甚至點擊之後會執行某樣動作。
.在螢幕中央出現彩色的大字,也有字體的使用,有些大字下面會附一行較小的文字。
.某些告示牌上的字不是只有黑色的一般字體,而是有其他顏色或格式,或右鍵點擊之後會有反應。
.打開完成的書也可以發現異於一般情形的文字,或是將滑鼠放在字上會顯示訊息,或如同對話框那樣,點擊後會有動作產生。

不要懷疑,這些都是透過json語法辦到的。如果已經讀過我寫的指令入門概論,應該不難知道前面兩項是利用/tellraw及/title指令產生,而有些進一步研究的人,也會知道後面兩項是利用編輯告示牌或完成的書的NBTtag,也就是資料標記,而達成。

因為json的語法功能很多,沒辦法一次講解完,所以我採用邊舉例邊說明的方式進行(主要用/tellraw及告示牌舉例),若有遺漏的部分請留言告知,隨後會補上。

如果要用/tellraw顯示一段簡單的「Hello World!」文字,只需要輸入/tellraw @a {"text":"Hello World!"}即可。
但如果不想要顯示白色的俗氣字樣,想要改顏色,字體呢?這時候我們必須在<原始json訊息>中加入額外的資訊,讓系統知道你要顯示的樣式。
上面的情形是加入"color":"blue","bold":"true"後,控制了顏色為藍色,樣式為粗體的效果。

所有顏色及樣式如下表:
要使顏色變成紅色,要在內容後面加上"color":"red",其他顏色類推,而樣式要斜體需加上"italic":"true",要底線則加上"underline":"true"。

需要注意換行「\n」的用法與其他格式不同,以前面「Hello World!」為例,想要讓兩個單字在不同行顯示,要在「Hello」後方加上「\n」。

在告示牌和完成的書中,json的格式稍稍被改變,因為它們不再是純粹的json結構,而是裝作
json的NBT結構,不過我還是一起介紹,因為主要架構還是相似的

若利用/blockdata替換告示牌的字樣,同樣顯示「Hello World!」,可以用/blockdata ~ ~1 ~ {Text1:"{\"text\":\"Hello World!\"}"},注意引號使用「"」、「\"」兩種。

若用/give,則可以用/give @p minecraft:sign 1 0 {BlockEntityTag:{Text1:"{\"text\":\"Hello World!\"}"},display:{Lore:[(+NBT)]}}。
為了解說方便,以下都用/blockdata來作為範例。

若在告示牌使用換行,會發現換行後的字都被切掉,
這是因為在告示牌中的換行並不是這樣的結構,而是每一行為每個獨立的字串(共四行),分別為Text1、Text2、Text3和Text4。

若在第一行顯示「Hello」而在第二行顯示「World!」的話,必須改成/blockdata ~ ~1 ~ {Text1:"{\"text\":\"Hello\"}",Text2:"{\"text\":\"World!\"}"} 。

若要在完成的書中顯示,指令格式為/give @p minecraft:written_book 1 0 {author:"CottontailTeemo_",title:"written_book",generation:0,pages:["{text:'',extra:[{text:'Hello World!'}]}"]},注意引號有使用「"」和「'」兩種。

最後介紹/title指令,因為裡面的json結構和/tellraw相同,所以我不多贅述,僅介紹兩者相異處。
和最一開始相同,若要顯示藍色粗體的「Hello World!」,指令為/title @a title {"text":"Hello World!","color":"blue","bold":"true"},可以發現兩者的json內容相同。

但若改成換行的內容,將會發現:
不但沒有換行,反而出現了一個亂碼。這是因為/title不支援換行,若要顯示兩行文字,就必須使用/title的標題與副標題:/title @a title {"text":"Hello","color":"blue","bold":"true"}、/title @a subtitle {"text":"World!","color":"blue","bold":"true"},注意這是兩個指令。

之前所舉的所有例子,都是只有用單一格式和單一顏色,若想要在一串字中使用好幾種樣式,該怎麼辦?別擔心,這時候就該輪到子類別(child)出場啦!
大家應該覺得一直看到重複的句子很煩,所以現在我使用新的字串啦~

若要顯示「Welcome to Summoner's Rift」還要讓不同單字有不同樣式,可以使用/tellraw @a {"text":"Welcome ","color":"aqua","extra":[{"text":"to ","color":"dark_aqua","bold":"true"},{"text":"Summoner's ","color":"blue","underlined":"true"},{"text":"Rift","color":"dark_blue","italic":"true"}]},將原本的字串設定為「Welcome 」,後面三個單字分別為其子類別,在json裡用「extra」表示。
json沒有規定只有主要類別才能擁有子類別,子類別也可以擁有子類別。例如/tellraw @a {"text":"Welcome ","color":"aqua","extra":[{"text":"to ","color":"dark_aqua","bold":"true","extra":[{"text":"Summoner's ","color":"blue","underlined":"true","extra":[{"text":"Rift","color":"dark_blue","italic":"true"}]}]}]}。因為子類別不限一個,所以沒有必要一直堆疊子類別,會造成編寫及解讀困難,並且可以發現,子類別若沒有指定到的格式,會繼承父類別,所以若想要把「Summoner's 」的粗體取消、「Rift」的底線取消,必須在其後分別加上"bold":"false"、"underlined":"false",這將使編寫更加複雜。

最簡單的解決方法是,取消父類別,而全部使用子類別,像這樣:/tellraw @a {"text":"","extra":[{"text":"Welcome ","color":"aqua"},{"text":"to ","color":"dark_aqua","bold":"true"},{"text":"Summoner's ","color":"blue","underlined":"true"},{"text":"Rift","color":"dark_blue","italic":"true"}]}。有沒有注意到這和上面的不同?將父類別留空,不使用任何格式,並將全部的字串當作空字串的子類別,這樣就不會因為繼承父類別的格式而造成困擾。
在子類別中,所有格式(包含之後介紹的功能)均和父類別相同,這也表示,換行在這裡也可以使用:/tellraw @a {"text":"","extra":[{"text":"Welcome\n","color":"aqua"},{"text":"to\n","color":"dark_aqua","bold":"true"},{"text":"Summoner's\n","color":"blue","underlined":"true"},{"text":"Rift","color":"dark_blue","italic":"true"}]}。

這個方法在告示牌中也可以使用:/blockdata ~ ~1 ~ {Text1:"{\"text\":\"\",\"extra\":[{\"text\":\"Welcome \",\"color\":\"green\"},{\"text\":\"to\",\"color\":\"dark_green\"}]}",Text2:"{\"text\":\"Howling Abyss\",\"color\":\"red\"}"}。
我發現我忘記打粗體上去了,只好請各位自行腦補。

在完成的書中是這樣運作的:/give @p minecraft:written_book 1 0 {author:"CottontailTeemo_",title:"written_book",generation:0,pages:["{text:'',extra:[{text:'Welcome ',color:'aqua'},{text:'to ',color:'dark_aqua',bold:true}]}","{text:'',extra:[{text:'Summoners ',color:'blue',underlined:true,italic:true},{text:'Rift',color:'dark_blue',italic:true}]}"]},順帶一提,要顯示反斜線要輸入「\\」;要顯示雙引號要輸入「\"」;要顯示單引號要輸入「\'」。在完成的書中每一個父類別表示一頁,上面使用了兩個父類別,所以分成兩頁。

關於json語法中的格式解說到這裡,不過還沒結束喔,別忘了還有點擊及滑鼠懸浮的用法。

點擊事件(clickEvent)和漂浮事件(hoverEvent)分別是兩種類別,但許多情況下他們會一起使用。例如:/tellraw @a {"text":"","extra":[{"text":"Click_me!","clickEvent":{"action":"run_command","value":"/say hi"},"hoverEvent":{"action":"show_text","value":"Click!!"}}]},簡單顯示「Click_me!」字串,並讓滑鼠至於其上方時顯示「Click!!」,滑鼠點擊時執行「/say hi」。

clickEvent的action共有六種,分別是「run_command」、「suggest_command」、「open_url」、「change_page」、「open_file」、「twitch_user_info」,這六種後面都接著value值。
「run_command」:value必須為可執行、正確的指令(需有前綴斜線「/」),在滑鼠點擊後將執行。注意執行某些指令需要擁有管理員權限。
「suggest_command」:value必須為可執行、正確的指令(需有前綴斜線「/」),在滑鼠點擊後將顯示在對話框,按下Enter後執行。注意執行某些指令需要擁有管理員權限。
「open_url」: value必須為一串網址,在滑鼠點擊後將詢問是否打開網站。
「change_page」: value必須為正確的頁碼(在完成的書中使用),在滑鼠點擊後將跳轉至該頁。
「open_file」: value必須為磁碟中檔案的路徑,在滑鼠點擊後將開啟該檔案。
「twitch_user_info」: value必須為Twitch使用者名稱,在滑鼠點擊後將顯示其資訊。

hoverEvent的action共有四種,分別是「show_text」、「show_item」、「show_achievement」、「show_entity」,這四種後面分別有不同的變數。
「show_text」: value可以為字串或json結構。但在json結構中無法使用clickEvent或hoverEvent,以免造成堆疊。
「show_item」:接著一串NBT結構。id為方塊或物品的ID;Damage為方塊或物品的損害值(可選);tag為方塊或物品的NBTtag (可選)。
「show_achievement」:value為成就或統計ID,格式和記分板準則相同。
「show_entity」:type為實體ID;name為實體名稱;id為實體UUID(也可以任意打啦)。

顯示物品:/tellraw @a {"text":"","extra":[{"text":"Hover_Event","hoverEvent":{"action":"show_item","value":"{id:stone,Damage:2}"}}]}。
顯示實體:/tellraw @a {"text":"","extra":[{"text":"Hover_Event","hoverEvent":{"action":"show_entity","value":"{type:EnderDragon,name:BaronNashor,id:League-of-Legends}"}}]}]}。
顯示成就:/tellraw @a {"text":"","extra":[{"text":"Hover_Event","hoverEvent":{"action":"show_achievement","value":"achievement.flyPig"}}]}。
顯示統計:/tellraw @a {"text":"","extra":[{"text":"Hover_Event","hoverEvent":{"action":"show_achievement","value":"stat.flyOneCm"}}]}。

clickEvent最常使用的是run_command,在RPG地圖中,為了方便玩家與NPC對話,可以經常見到這個功能。而hoverEvent最常使用show_text來輔助clickEvent,可以幫助玩家辨別複數個clickEvent的差異。

在告示牌中,只存在點擊執行指令的功能。例如:/blockdata ~ ~1 ~ {Text1:"{\"text\":\"/tp\",\"color\":\"light_purple\",\"bold\":\"true\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/tp @p ~ ~1 ~\"}}",Text2:"{\"text\":\"/tell\",\"color\":\"dark_purple\",\"bold\":\"true\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/tell @p tell\"}}",Text3:"{\"text\":\"/say\",\"color\":\"gray\",\"bold\":\"true\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/say say\"}}",Text4:"{\"text\":\"/me\",\"color\":\"dark_gray\",\"bold\":\"true\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/me me\"}}"}。
當點擊告示牌時,會執行第一行的/tp @p ~ ~1 ~、第二行的/tell @p tell、第三行的/say say、及第四行的/me me(一個告示牌最多執行四個指令)。不過...若指令比要顯示的字多該怎麼辦?別擔心,其實在文字的地方留白就可以嘍~
在告示牌執行指令的優點是無視管理員權限。也就是說,在沒有管理員權限的情形下點擊告示牌,可以執行如/fill、/tp等被設定在告示牌裡面,原本需要管理員權限才能執行的指令。(當然,/op或/ban這類不能在指令方塊執行的指令還是不能使用)

而/title只具備顯示的功用,所以這些功能在/title裡面是沒有用處的。

在完成的書中,這些功能和/tellraw的一樣完整。不過要注意裡面的指令是否含有引號,若有則需要改成顯示引號的樣子,不然會導致json解析錯誤而造成失敗。/give @p minecraft:written_book 1 0 {author:"CottontailTeemo_",title:"written_book",generation:0,pages:["{text:'',extra:[{text:'Option_A\n',color:'red',bold:true,clickEvent:{action:'run_command',value:'/say hi'},hoverEvent:{action:'show_text',value:'Click to say hi'}},{text:'Option_B\n',color:'blue',bold:true,clickEvent:{action:'run_command',value:'/me slain the Dragon'},hoverEvent:{action:'show_text',value:'Click to announce your achievement'}},{text:'Option_C',color:'yellow',bold:true,clickEvent:{action:'run_command',value:'/say I told you not to click!'},hoverEvent:{action:'show_text',value:'Do not click this!'}}]}"]}。

在充分熟悉並活用上述json的語法後,你可以做出含有強大劇情系統(或對話系統)的遊戲地圖。你也可以選擇在地圖內放置效果書、咒文書、或是萬能的告示牌。

但...json可還不只有這些功能喔!!!
底下要介紹另類的字串,熟悉這些功能將可以帶領你的json程度到達顛峰!

在一些RPG劇情中,為了使玩家能夠更融入劇情,經常在對話中提及或呼叫玩家的名字。而另外一些,則可以實時的顯示出玩家在遊戲中的分數。

在概論篇裡,介紹了一種叫目標選擇器的東西。目標選擇器的功能非常強大,不僅在指令裡面可以精確的選擇目標,而在json中,它也可以做到!

若要顯示「『玩家』獲得五連殺!」可以用/tellraw @a {"text":"","extra":[{"selector":"@p","color":"dark_red","bold":"true"},{"text":" penta kill!","color":"red","bold":"true"}]}來顯示。
在這條指令中,會向所有玩家顯示「『最靠近指令執行處的玩家名稱』獲得五連殺!」,若更改目標選擇器,也可以同時顯示複數名稱。例如「jeb_ and dinnerbone are feeding sheeps.」或「Notch, Steve and Alex tried to swim in lava.」。

有沒有發現,在子類別中,原本應該是"text"的地方,被替換成"selector"了?
若替換成"score",還可以顯示玩家分數。
注意"score"的格式和前面兩者有所差異,因其並不是僅含一個字串或變數,故以大括號「{}」將必需變數"name"與"objective"括起來(在記分板名稱使用「*」代表所有正在被記分板追蹤的目標,亦即,在此記分板目標有分數的實體)

而比較冷門的用法有:"insertion"(當玩家壓著shift點擊文字時,會將文字插入玩家的對話欄而不會清除現有以輸入文字)、"translate"(翻譯遊戲或資源包定義的識別碼為玩家當前遊戲中的語言)、"with"(使用"translate"時的參數)等。

/title指令、告示牌、完成的書皆可以使用這些功能。

關於json的其他資料

*前面有提過,當要顯示反斜線要輸入「\\」;要顯示雙引號要輸入「\"」;要顯示單引號要輸入「\'」。但當要在引號內使用第二層引號時,就必須再多加兩條反斜線,而第三層的引號也需比第二層引號多兩條,依此類推。具體公式為: 「(2×層數) + 1」。

*json支援unicode字元,例如要顯示段落符號(¶,編號00B6)則要輸入\u00B6。
unicode字元集:點此。

*/tellraw及/title的指令可以簡化,單一的字串會被辨認為"text"。
但不建議這樣使用,會降低指令的可讀性。