本帖最后由 pca006132 于 2017-8-15 22:54 编辑

-------命令进阶-------
第二章 常用格式

本文首发于命令进阶教程全集
使用CC BY-SA-NC 4.0协议,转载请注明本页面链接

    虽然本文不会详细说明不同的命令,然而本文会详细解释命令常用的格式。

    常用的格式分别有:
    • JSON文本定义显示出来的文本,并且提供点击、悬浮等功能
    • 命令NBT定义、检测实体及方块实体的属性


    其中JSON文本里所介绍的JSON格式在其他游戏文件里也经常使用。
    至于NBT则是命令里一个相当重要(并且多Bug)的部分。
作为移植页面,格式可能会有偏差,请到教程全集中获得完整体验。
本页面可能随着版本推进而过期,内容以全集为准。




JSON概观

简介
什么是JSON?引用术语来说

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript等)。 这些特性使JSON成为理想的数据交换语言

简单来说

JSON就是一种易于阅读以及交换信息的语言格式

而Minecraft也看中了JSON这种便于阅读及读取的格式,以JSON格式来定义不同功能。
这里我们将会介绍JSON文本,这是一个经常用于各种命令的格式。

首先我们需要学习JSON的基本格式。


格式
首先,JSON标准的格式为:

  1. "<名称>": <值>
复制代码
值可以为一个数字(分为整数以及浮点数,浮点数即有小数),布尔值(只有 真(True)和假(False)的数值)等。
例如:

  1. "Number":1
  2. "Answer":true
复制代码
对字符串(可以理解为普通文字)来说,值需要被双引号括起来,即:

  1. "<名称>":"<值>"
复制代码
例如:

  1. "Name":"SYL"
复制代码



如果是描述一个对象(Compound)的话,把内容(属性)书写在花括号 {} 中,以 , 分隔内容。
例如:

  1. {"Name":"SYL","Gender":"Male"}
复制代码
其中 NameGender 就是这个对象的属性
这对象表达了名为SYL,性别为男的意思。




如果是一个集合/数组(Array/List),那么用 [] 把对象括起来
例如:

  1. {"CBL":[{"Name":"SYL","Gender":"Male"},{"Name":"Woody_Mo","Gender":"Male"}]}
复制代码
这里描述了名为CBL的对象集合,包含了SYL和Woody_Mo这两个对象。


转义
转义是JSON应用中十分重要的课题。在此我们只会大约说明转义的用法,详细例子将会在之后章节给出例子。

当我们在字符串里使用某些特别的字符,如 " 字符的时候,情况会变得稍微复杂。举个例子

  1. "abc":"这个JSON的名称为"abc""
复制代码
就我们现在所学, " 字符代表的是字串的开始和结尾啊!这样的话哪个 " 字符是开始哪个才是结束?
答案是:没人知道。我们不能这么写JSON的。

如果我们要在字串里填写一些特殊符号,我们需要对它们进行转义(escape)。
转义即在特殊字符前方加入一个名为转义字符的字符,表示这个字符和原来的意思不同。(当作普通字符处理)。
在JSON里,转义字符为 \ ,而需要转义的特殊字符为 \"  (为何转义字符也需要转义?因为它独自出现的时候代表的是转义,而不是一个普通字符。因此当我们需要在文本内使用此字符时需要将其转义。)。

以上方的例子来说,我们希望abc的数值为 这个JSON的名称为"abc" ,因此我们会这么写:

  1. "abc":"这个JSON的名称为"abc""
复制代码
如果我们要一个数值为上方这JSON字串的JSON呢?我们需要这么写:

  1. "foo":""abc":"这个JSON的名称为\\"abc\\"""
复制代码
注意:
转义本来是没有"多重转义"的概念的。转义是一层一层,每次在 \" 符号前方加入 \ 字符。
记住这个最基本的原则可以避免出现错误。


JSON除错
JSON常见错误有几个:

  • 标签名称忘记加上引号。如 {test:1} 是错的, {"test":1} 才是对的。
  • 额外的逗号 , 。如 [1,2,3,]{"test":1,"test2":2,} 。因为 , 代表之后还有东西,记得之后没东西的时候要删掉那个逗号。
  • 忘记转义。比如 "tellraw @a ["bla"]" 这可是错的,得转义成 "tellraw @a [\"bla\"]"
  • 括号不匹配。比如 {"a":{"test":"testing"} ,这个缺了最后的 } 符号。
      这个最好的办法是一开始就别错,而输入 {[ 符号时顺便输入 }] 符号是一个好习惯。
  • 错字,如 true 写成 ture 。这样你就没救了(误。

JSON文本
在MC里面,目前用到JSON文本(Text component)的地方有5个, tellraw 命令, title 命令, 告示牌成书 以及 advancement 命令,用于记录文字的样式和功能。

比起传统的 say 命令,JSON可以自由编辑样式,甚至提供了交互功能,所以很适合作为信息输出/用户交互界面。

其中最基本的概念是:
每一段文字被视作为一个文本对象,由 {} 括起来。
文本对象内可设置属性,决定了文字的内容,样式,功能等等(内容只能设置一种,但可以设置多个其他属性)。
以下章节将一步步解释JSON文本的格式及在游戏内的应用。



JSON文本类型
最基础的JSON文本类型可被分为5类:

  • text-文本
  • selector-目标选择器
  • score-分数
  • translate-翻译
  • keybind-显示按钮
值得注意的是,虽然这五个都是文本对象中的属性,这5类文本类型在单个对象(同一段文字)中只能设置一个。
不然会互相覆盖,只有一个能生效。
关于同时使用多个文本类型的情况,我们会在之后的章节进行讨论。


text-文本
text可谓是游戏内最基本的类型。
功能十分简单,就是显示你指定的文字。

最基本的格式为:

  1. "text":"<文本内容>"
复制代码
例如:

  1. tellraw @a {"text":"Hello World"}
复制代码


顺带一提,在内容中插入 \n 可以让文字换行(只限于 成书tellraw 命令)

例如:

  1. tellraw @a {"text":"Hello\nWorld"}
复制代码



selector-目标选择器
selector的作用就是显示选择器选择到的实体名称,与命令中的选择器格式一致

基本格式为

  1. "selector":"<目标选择器>"
复制代码
选择符就如平时使用一般输入就可以了
例如:

  1. tellraw @a {"selector":"@p"}
复制代码


如果世界内只有我和一只名为GGG的猪:

  1. tellraw @a {"selector":"@e"}
复制代码


值得注意的是,选择器参数(即跟随在选择符后的[]部分)也可使用:

  1. tellraw @a {"selector":"@e[type=Pig]"}
复制代码


注意:
JSON文本里的选择器,包括接下来的score中name使用的选择器,大部分都是以命令执行位置作为原点。
tellrawtitle 命令以命令执行点为原点,书本以打开的玩家的位置为原点,只有牌子是以牌子坐标为原点


score-分数
score用于显示特定目标的特定分数,需要对记分板的知识(详见之后的章节)。

格式为:

  1. "score":{"name":"<对象名>","objective":"<变量名>"}
复制代码
对象名 即为需要选中的对象,如指定玩家名称
分数名 就是来自哪一个记分板变量

例如我们创建了一个名为 test 的记分板变量,里面有两个玩家:


输入:

  1. tellraw @a {"score":{"name":"Tester","objective":"test"}}
复制代码


name 支持选择符(但不能为多选,如 @a ),我们放置了一个命令方块,并让SYL接近他

输入:

  1. tellraw @a {"score":{"name":"@p","objective":"test"}}
复制代码


scoretellraw 命令中还有一个特殊功能, name 部分输入 * 的话
那么观察者自己将会作为对象,显示观察者的分数(这在做地图的时候十分有用)

例如:

  1. tellraw @a {"score":{"name":"*","objective":"test"}}
复制代码
SYL的视角:


Tester的视角:



translate-翻译文件
translate其实就是在文本JSON里引用翻译文件的文字,格式为:

  1. "translate":"翻译识别器"
复制代码


  1. "translate":"chat.link.warning"
复制代码
然而翻译文件的文字可以有参数(那些 %s ),这个时候我们就可以用with来传入参数(顺序对应翻译文件内的 %s ),格式为:

  1. "with":[<参数字串列表>]
复制代码
注意with的参数可以为JSON文本。



  1. 假设翻译文件中有一行为
  2. custom.a=第一个参数: %s,第二个参数: %s

  3. JSON文本为
  4. {"translate":"custom.a","with":["a","b"]}

  5. 输出则为
  6. 第一个参数: a,第二个参数: b
复制代码



translate除了能够用作翻译以外,亦能用作检查资源包,如

  1. {"translate":"custom.1","with":[{"text":"请点击这里","clickEvent":{"action":"run_command","value":"/say 用了自定义的材质包"}}]}
复制代码
原版很明显是没有 custom.1 这个翻译识别器的,故此没加载资源包的用户看到的就是 custom.1 ,也没法点击。而地图的自定义资源包则能够添加此翻译识别器,如

  1. custom.1=%s
复制代码
然后玩家就能点击 请点击这里 并触发命令了。如果玩家没有使用该资源包,则只能看着 custom.1 在那里干瞪眼了。


Keybind-显示按钮
Keybind就是引用某些特殊按钮,如果玩家修改了的话就显示玩家修改为的按钮。对地图制作十分有用,因为有时候需要让玩家按某个按钮然而玩家可能会修改默认键位。(比如 按F装填

格式:

  1. {"keybind":"<按键>"}
复制代码
按键比如是 key.drop ,  key.forward 等等。
完整的按键列表在这:按键列表

例子:

  1. {"keybind":"key.drop"}
  2. {"keybind":"key.forward"}
复制代码
注意: 如果没有设置该键位,则会显示为 None




知道了如何定义内容后,我们就得为我们的内容搞点新意思了。
接下来将会介绍如何为文本对象加入颜色、粗体等样式



样式代码
样式代码即为帮文字添加样式的代码。
例如加粗,斜体,颜色等等。
这些都是文本对象里的属性。

同时,样式代码不像 text / selector / score 并不能重复。
每个对象都可以使用多个样式代码,以达成多种效果叠加。


color-颜色
color代码,就是帮文字添加颜色的代码。
基本格式为:

  1. "color":"<颜色代码>"
复制代码
实际使用时,添加在文本类型后方,使用 , 分隔即可。
所有的样式代码都是如此使用的,可以添加多于一个样式代码。

例如:

  1. tellraw @a {"text":"Hello World","color":"dark_blue"}
复制代码


颜色表格


bold-加粗
bold,加粗文字。
基本格式:

  1. "bold":true
复制代码
如果是后方的数值不为 true 而是 false 的话,文字就不会加粗。
将样式代码设置为false的用途主要体现在 extra-分项/JSON array 中,后续将有说明。

使用例子:

  1. tellraw @a {"text":"Hello World","bold":true}
复制代码


如果是想搭配其他样式代码,如颜色使用的话:

  1. tellraw @a {"text":"Hello World","bold":true,"color":"dark_red"}
复制代码


请注意,样式代码的先后顺序并无影响。
其他样式代码同理,不再作示范。


italic-斜体
italic,斜体,与bold的使用方式类近
基本格式:

  1. "italic":true
复制代码
使用例子:

  1. tellraw @a {"text":"Hello World","italic":true}
复制代码



underlined-下划线
underlined,下划线,与bold的使用方式类近
基本格式:

  1. "underlined":true
复制代码
使用例子:

  1. tellraw @a {"text":"Hello World","underlined":true}
复制代码



strikethrough-删除线
strikethrough,删除线,与bold的使用方式类近
基本格式:

  1. "strikethrough":true
复制代码
使用例子:

  1. tellraw @a {"text":"Hello World","strikethrough":true}
复制代码



obfuscated-混淆文字
obfuscated,混淆文字

这个是一个特别的样式代码
生效条件是文本内容必须为英文
效果为不断跳动变换的乱码文字

基本格式:

  1. "obfuscated":true
复制代码
使用例子:

  1. tellraw @a {"text":"Hello World","obfuscated":true}
复制代码


如果不是英文的话不会起效,例如:

  1. tellraw @a {"text":"世界你好","obfuscated":true}
复制代码





现在我们懂得为JSON文本加入不同的样式了,那么还有没有别的可以玩玩呢?
JSON文本除了能看以外,还能与玩家互动,这也是JSON文本一个非常重要的特点。
接下来的章节我们将会介绍点击及悬浮事件,让JSON文本变得更生动有趣!



点击事件
clickEvent 是JSON最重要的功能之一。
其功能为:点击相关文字的时候执行某些操作。
提供了一个对输入(点击)产生反馈(action)的功能。

基本格式为:

  1. "clickEvent":{"action":"<动作>","value":"<值>"}
复制代码
将其放置在对象内使用(和样式类似,都是文本对象的一个属性,只是这属性比较复杂而已)

请注意, clickEvent 不适用于标题及 advancement 的description。
告示牌的话最多只能设置4个,之后告示牌部分会有讲解。

而每个文本对象只能设置一个点击事件和悬浮事件,继承下来的事件会被覆盖。

advancement 的title的clickEvent只能在聊天栏公告获得进度时点击,不能在进度面板点击


run_command-运行命令
run_command是一个十分常用的动作
其功能为让点击者执行设定的命令
基本格式为:

  1. "clickEvent":{"action":"run_command","value":"<需执行命令>"}
复制代码
需执行命令前必须有 / ,就像是直接在聊天栏执行一样。

并且CE(clickevent的简称)可以和样式代码一起使用
例如:

  1. tellraw @a {"text":"Hello World","color":"dark_red","clickEvent":{"action":"run_command","value":"/say hi"}}
复制代码


由于run_command是使点击者执行命令,所以同一个命令由不同人点击,结果也不同
例如分别由SYL和Tester点击上面的命令:


在多人游戏时,需要注意一点,在 tellraw 命令、书本内使用CE时,如果点击者没有OP权限
那么是无法执行需要OP权限的命令的
例如 say 无法被普通玩家执行,那么如果在没有OP权限的情况点击文字:


如果是在告示牌内使用的话,则带有2级OP权限,所以普通玩家也可以右键告示牌执行命令




另一点就是, value 里面的命令长度不能太长
因为命令是视作在聊天栏输入之后按enter执行的
所以不能超越聊天栏的输入上限:256个字符

例如我使用以下 /summon 命令:
(本例子为旧版本例子,当时输入上限为100个字符,所以此命令在新版本中可用,但若超出256个字符的话依旧会出现问题)

  1. tellraw @a {"text":"Hello World","color":"dark_red","clickEvent":{"action":"run_command","value":"/summon minecraft:creeper ~ ~ ~ {powered:1,ExplosionRadius:5,Attributes:[{Name:generic.movementSpeed,Base:0}],ActiveEffects:[{Ambient:1,Amplifier:0,Duration:999999999,Id:11}]}"}}
复制代码


由于超过了长度上限,实际输入部分到逗号就终结了,命令并未完整,自然无法成功执行

如果是在告示牌内使用的话,则没有这个长度限制


suggest_command-建议命令
suggest_command ,建议命令
其功能为点击时,将点击者输入栏中的内容替换value 中设定的内容

格式

  1. "clickEvent":{"action":"suggest_command","value":"<值>"}
复制代码
例如:

  1. tellraw @a {"text":"Hello World","clickEvent":{"action":"suggest_command","value":"hi"}}
复制代码



open_url-打开链接
open_url,打开链接(一般是叫浏览器打开的,然而打开前会有一段警告询问玩家是否要打开未知链接)

基本格式为:

  1. "clickEvent":{"action":"open_url","value":"<值>"}
复制代码
值的部分必须填一个以 http://https:// 开头的网址
按下去,系统就会询问是否打开网页,同意以后就会打开浏览器跳转至页面
例子:

  1. tellraw @a {"text":"Hello World","clickEvent":{"action":"open_url","value":"http://www.google.com"}}
复制代码







change_page-换页
此CE为成书专用的CE
成书的格式容后讲解

基本格式为:

  1. "clickEvent":{"action":"change_page","value":"<值>"}
复制代码
就是要跳到的页数
例如:(成书的格式请参阅后面相关篇章)

  1. give @a minecraft:written_book 1 0 {title:"",author:"",pages:["{"text":"Page 2","clickEvent":{"action":"change_page","value":"2"}}","{"text":"The second page."}"]}
复制代码


按下以后:



悬浮事件
hoverevent 是JSON的另一个实用功能
类似CE,HE也是一个反馈机制,不过这次是对鼠标移上文字时,这个动作进行反馈
简单来说就是鼠标移上去文字,会有个悬浮框显示一些信息

基本格式为:

  1. "hoverEvent":{"action":"<动作>","value":"<值>"}
复制代码
hoverevent 不适用于标题advancement告示牌


show_text-显示文本
show_text,显示文本
功能自然为显示文字

基本格式为:

  1. "hoverEvent":{"action":"show_text","value":"<值>"}
复制代码


  1. "hoverEvent":{"action":"show_text","value":{JSON文本}}
复制代码
前者使用上比较方便简单,但不支持如样式等设定
使用例子:

  1. tellraw @a {"text":"Hello World","hoverEvent":{"action":"show_text","value":"hello again"}}
复制代码


后者需求完整的JSON文本,但支援如样式代码等功能
例子:

  1. tellraw @a {"text":"Hello World","hoverEvent":{"action":"show_text","value":{"text":"hello again","color":"gold"}}}
复制代码


甚至是其他的JSON结构,例如:

  1. tellraw @a {"text":"Hello World","hoverEvent":{"action":"show_text","value":{"score":{"name":"SYL_qiuyifeng","objective":"test"},"color":"gold"}}}
复制代码





show_item-显示物品
显示物品,可以显示一个物品的信息
其效果与在背包内查看物品信息一致

格式为:

  1. "hoverEvent":{"action":"show_item","value":"<物品NBT标签>"}
复制代码
物品标签请参考之后的NBT教程
例子:(关于\",即转义的内容,请参阅相应章节)

  1. tellraw @a {"text":"Hello World","hoverEvent":{"action":"show_item","value":"{id:"minecraft:iron_pickaxe"}"}}
复制代码


例子二:

  1. tellraw @a {"text":"Hello World","hoverEvent":{"action":"show_item","value":"{id:"minecraft:iron_pickaxe",tag:{display:{Lore:["keep digging"]}}}"}}
复制代码



show_entity-显示实体
show_entity,显示生物
此功能必须在玩家使用了F3+H打开了附加信息显示后才能运作

这个功能提供的显示,和运行命令 /say @e 或其他类似命令后
将鼠标移上去实体名称后显示的实体信息一致
效果如下:


基本格式为:

  1. "hoverEvent":{"action":"show_entity","value":"{name:"<名称>",type:"<生物ID>",id:"<UUID/文本>"}"}
复制代码
其中 name 就是最上面显示的名字
type 就是生物id
id 呢,原意是用于显示 UUID 的,但也可用作一般文本显示

例如:

  1. tellraw @a {"text":"Pig","hoverEvent":{"action":"show_entity","value":{"type":"Pig","name":"Bacon","id":"Walking Bacon"}}}
复制代码



insertion-插入
insertion是一个单独的属性
其格式为:

  1. "insertion":"<值>"
复制代码
其功能为,shift+点击该JSON文本后,在聊天栏输入插入 的内容
suggest_command 不同,此操作并不会覆盖已有输入
而是在输入的最后添加

例子:

  1. tellraw @a {"text":"Hello World","insertion":"|after click"}
复制代码


before click 是已经输入的内容, |after click 是点击后插入的内容




即使知道了那么多的功能,如果JSON文本只能做到单一颜色,单一功能,还是比较单调啊。
不用怕!我们可以进行分项处理,一次过显示多个文本对象,显示不同的样式、类型以及事件。
接下来将会讲解JSON分项处理。



分项与数组
extra-分项 以及 JSON array-JSON数组 提供了让多个不同的文本对象同时存在的可能性
例如想让一条 tellraw 命令中使用多个不同样式的文本对象,或者是组合多个JSON结构时使用

同时它们在告示牌成书之中也有重要的角色
并且继承的特性有时能让一些样式上的设定变得方便


基础
extra-分项是一个附加在JSON文本中的数组对象
其格式为

  1. extra:[{<JSON文本1>},{<JSON文本2>},......]
复制代码
JSON文本1、JSON文本2...等等的文本对象会被放在当前对象之后。




而JSON array则是由 [] 包围的JSON文本,在需求JSON文本的命令/NBT中,可以直接使用 [] 输入一个JSON数组,取代使用 {} 来输入单一对象

使用一个简单的例子:

  1. tellraw @a {"text":"Hello World"}
复制代码


最基础的一条 tellraw 命令也可以分别以 extraarray 的形式重写
array:

  1. tellraw @a [{"text":"Hello"},{"text":" World"}]
复制代码
或者

  1. tellraw @a ["Hello"," World"]
复制代码
(在array中,可以用双引号直接取代简单的 text 对象,可以和完整的JSON文本混合使用)



extra:

  1. tellraw @a {"text":"Hello","extra":[{"text":" World"}]}
复制代码


三者效果是完全一样的




extra内也可以添加多个JSON文本

例如:

  1. tellraw @a {"text":"Hello","extra":[{"text":" Minecraft"},{"text":" World"}]}
复制代码





不过由于 extraarray 的效果和特性基本一致,出于 arrayextra 使用上方便一点,以及格式上比较方便阅读和美观,个人推荐尽量使用 array

然而在进度里,文件只能够使用Compound,因此只能使用extra。


应用
extra及array最大的应用,就是可以分别设置每一个JSON文本的属性
例如:
array:

  1. tellraw @a [{"text":"Hello","color":"red"},{"text":" Minecraft","color":"green"},{"text":" World","color":"blue"}]
复制代码
extra:

  1. tellraw @a {"text":"Hello","color":"red","extra":[{"text":" Minecraft","color":"green"},{"text":" World","color":"blue"}]}
复制代码


不仅仅是颜色之类的样式代码,还可以是CE(clickEvent)和HE(hoverEvent)

例如:
array:

  1. tellraw @a [{"text":"Hello","color":"red"},{"text":" Minecraft","color":"green","clickEvent":{"action":"run_command","value":"/say Minecraft"}},{"text":" World","color":"blue","hoverEvent":{"action":"show_text","value":"World"}}]
复制代码
extra:

  1. tellraw @a {"text":"Hello","color":"red","extra":[{"text":" Minecraft","color":"green","clickEvent":{"action":"run_command","value":"/say Minecraft"}},{"text":" World","color":"blue","hoverEvent":{"action":"show_text","value":"World"}}]}
复制代码
由于命令比较长,下面将会把命令分解出来说明

这条 /tellraw 命令分别有3个JSON文本:

  • 第一个JSON文本(array内首个对象,或者是带有extra列表的那个对象),我们可称之为主项:

    1. {"text":"Hello","color":red}
    复制代码
    其设定为红色的"Hello"
  • 第二个对象:

    1. {"text":" Minecraft","color":"green","clickEvent":{"action":"run_command","value":"/say Minecraft"}}
    复制代码
    其设定为绿色的" Minecraft",点击执行/say Minecraft
  • 第三个对象:

    1. {"text":" World","color":"blue","hoverEvent":{"action":"show_text","value":"World"}}
    复制代码
    其设定为蓝色的" World",悬浮时显示"World"
效果就会是:





不仅如此,它们还可以设置不同结构的JSON(例如组合text,score和selector)

例如:
array:

  1. tellraw @a [{"text":"Nearest Player:"},{"selector":"@p"}]
复制代码
extra:

  1. tellraw @a {"text":"Nearest Player:","extra":[{"selector":"@p"}]}
复制代码
这里有两个对象:

  • 主项的文本:"Nearest Player:"
  • 和第二项的 @p 选择符
效果就是:



继承
extraarray 都拥有继承的特性
所有 分项 (array里面首个之后的对象/extra列表里面的所有对象)都会继承到 主项 (array里面首个对象/带有extra列表的那个对象)的设定

举个例子帮助理解:
array:

  1. tellraw @a [{"text":"Hello","bold":true},{"text":" World"}]
复制代码
extra:

  1. tellraw @a {"text":"Hello","bold":true,"extra":[{"text":" World"}]}
复制代码


在本例中,只有主项设置了 bold 属性,但是由于继承的特性,分项也同时拥有了粗体的样式

但是反之,分项的设定并不会影响主项,例如:
array:

  1. tellraw @a [{"text":"Hello"},{"text":" World","bold":true}]
复制代码
extra:

  1. tellraw @a {"text":"Hello","bold":true,"extra":[{"text":" World","bold":true}]}
复制代码


同时,分项之间并不会互相影响,并且继承而来的属性可以被覆盖
例如:
array:

  1. tellraw @a [{"text":"Hello","bold":true},{"text":" Minecraft","color":"green"},{"text":" World","bold":false}]
复制代码
extra:

  1. tellraw @a {"text":"Hello","bold":true,"extra":[{"text":" Minecraft","color":"green"},{"text":" World","bold":false}]}
复制代码


详细分析一下以上的命令,以上的 /tellraw 拥有三个对象

  • 主项为"Hello",拥有 bold 属性
  • 第二项" Minecraft",继承了 bold 属性,并且设定了颜色为绿色
  • 第三项" World",虽然应该继承主项的 bold 属性,但是 bold:false 设定覆盖了继承而来的属性,同时也不受第二项的颜色属性影响
虽然本节没有使用CE/HE作为例子,但它们也是可以如同 样式代码 一样被继承的,规则相同。但如果子对象也有设置CE/HE,继承下来的事件会被取代。




如果有时需要设定一段格式差异较大的JSON文本,例如只想将第一段文字设定为粗体,其他都不要,那么后面的文本是不是都要设定 bold:false 这么麻烦?

一个方便的做法为,将主项设置为空项,例如:
array:

  1. tellraw @a ["",{"text":"Hello","bold":true},{"text":" Minecraft","color":"green"},{"text":" World","italic":true}]
复制代码
extra:

  1. tellraw @a {"text":"","extra":[{"text":"Hello","bold":true},{"text":" Minecraft","color":"green"},{"text":" World","italic":true}]}
复制代码


这样即可确保每一个JSON文本的独立性,减少互相干扰



告示牌
告示牌 支持使用JSON文本定义上面的文字,并且有三种指令可以自定义告示牌,分别为 give 命令(获得物品形式的 告示牌 ), setblock 命令(直接放置),和 blockdata 命令(修改已有 告示牌

格式分别为:

  1. give @p sign 1 0 {BlockEntityTag:{NBT}}
复制代码
  1. setblock [x] [y] [z] minecraft:standing_sign/minecraft:wall_sign [数据值] [旧方块处理方式] {NBT}
复制代码
  1. blockdata [x] [y] [z] {NBT}
复制代码
其中 告示牌NBT 格式如下:

  1. {Text1:"{JSON文本}",Text2:"{JSON文本}",Text3:"{JSON文本}",Text4:"{JSON文本}"}
复制代码
Text1/2/3/4 分别代表牌子的每一行的内容(在使用 entitydata 命令时,如果相关行内容不需编辑,可以不写相关行数的NBT)。

请注意,由于 Text1/2/3/4 本身不是文本对象,而是 NBT ,所以无需使用双引号包围,并且由于JSON文本被双引号包围,请注意里面引号需要转义。

例子:

  1. blockdata ~ ~1 ~ {Text1:"{"text":"Hello World","bold":true,"color":"dark_green"}",Text2:"{"selector":"@p"}"}
复制代码


如需在同一行内使用多于一个文本对象,请使用 JSON arrayextra
例子:

  1. blockdata ~ ~1 ~ {Text1:"["",{"text":"Hello","color":"green"},{"text":" World","color":"red"}]"}
复制代码





最后是CE在牌子的应用
牌子的每一行都可以设置一个CE,即一个牌子最多可设置4个CE
但每一行的CE只能设置在主项,设置在分项的CE是无效的

例如:

  1. blockdata ~ ~1 ~ {Text1:"{"text":"say 1","clickEvent":{"action":"run_command","value":"/say 1"}}",Text2:"{"text":"say 2","clickEvent":{"action":"run_command","value":"/say 2"}}"}
复制代码




值得注意的事项是
玩家右键点击牌子时执行命令,命令的执行坐标以牌子所处位置为起始点 (情况类似与 /execute <点击者> <告示牌坐标> <命令>

  • 所以当涉及到选择符的命令,例如/say @e[c=2] ,这个命令将会以牌子为选择实体的起始点,这个情况下会选中距离牌子最近的两个实体
  • 而同样的,使用了相对坐标,例如/setblock ~ ~ ~ minecraft:stone,则会以牌子作为相对坐标的起始点,这个情况下会将牌子替换为石头
  • 特别注意c=1 这个选择器参数有特别处理,该参数无论如何都会选中点击者,如/say @e[c=1] 必定会选中点击者,不管中间有多少实体距离 告示牌 比点击者更近
亦请注意,于1.12以后的版本,由于NBT语法分析器的改动,若需要在牌子中使用 unicode-万国码 ,即 \u ,需要对其反斜杠进行转义,即写成 \\u 的形式

如果是Setblock的话,需要指明Text1-Text4的JSON。
不过,如果那行是空的话,可以写 null
例子:  Text4:null


成书
成书亦支持使用JSON文本定义书本的内容,获得方式只有一个,使用 /give 命令

格式为:

  1. give @p written_book <数量> 0 {pages:["{JSON文本}","{JSON文本}",......],title:"<成书名称>",author:"<作者>"}
复制代码
数量成书名称作者 不多作解释,而!(list)

    pages 这个NBT 里面的每一个JSON文本都代表一页的内容
    例如:

    1. give @p written_book 1 0 {pages:["{"text":"page 1"}","{"text":"page 2"}"],title:"Book",author:"SYL"}
    复制代码







    如需在一页内使用多个文本对象,自然需要使用 JSON array
    并且 成书 也支援CE和HE
    例如:

    1. give @p written_book 1 0 {pages:["["",{"text":"say hi","underlined":true,"clickEvent":{"action":"run_command","value":"/say hi"}},{"text":"\nhello","bold":true,"hoverEvent":{"action":"show_text","value":"world"}}]"],title:"Book",author:"SYL"}
    复制代码
    分解以上命令说明

    • 主项为 \"\" ,即空白的主项
    • 第二项为"say hi",点击后让玩家执行 /say hi
    • 第三项为"\nhello",悬浮在文字上显示 world
    • 需要注意的是,第三项内容前有 \n 换行符,所以它将在第二行显示
    最终效果为:


    点击say hi


    请注意,于1.12以后的版本,由于NBT语法分析器的改动,若需要在牌子中使用 unicode-万国码换行符 ,即 \u\n ,需要对其反斜杠进行转义,即写成 \\u 以及 \\n 的形式

    以上命令若需在1.12后使用,请使用以下版本:

    1. give @p written_book 1 0 {pages:["["",{"text":"say hi","underlined":true,"clickEvent":{"action":"run_command","value":"/say hi"}},{"text":"\\nhello","bold":true,"hoverEvent":{"action":"show_text","value":"world"}}]"],title:"Book",author:"SYL"}
    复制代码




    杂项
    本部分将收纳应用方面的补充说明,他们可能是难以归纳进以上架构或者是平日甚少使用,所以收纳于此部分


    unicode-万国码
    JSON支援显示Unicode,格式为:
    \u####

    #### 就是4个位的Unicode代码,具体请参考Unicode代码的网页
    不过MC字库并不保证所有的Unicode都能正常显示

    使用例子:

    1. tellraw @a {"text":"\u2622"}
    复制代码


    1. tellraw @a {"text":"\u2622\u269B"}
    复制代码



    转义
    这里是接着首章的例子。

    比如需要输出 "Hello World" ,我使用了以下命令:

    1. tellraw @a {"text":""Hello World""}
    复制代码
    但由于配对的问题,标识 部分的引号和内容所需的引号配对了,系统无法正确识别命令,导致无法执行
    JSON规定的转义方式为,将 " 转为 \" ,将 \ 转为 \\
    正确的命令为:

    1. tellraw @a {"text":""Hello World""}
    复制代码


    这样我们便能告知系统, "Hello World" 的引号和包围 的引号如何正确配对




    然后是需要更多转义的例子
    例如我们需要修改以下命令:

    1. tellraw @a {"text":"Hello World","clickEvent":{"action":"run_command","value":"/tellraw @a {"text":"Hello World"}"}}
    复制代码
    这是一个包含了CE的 /tellraw ,点击会再次输出 Hello World
    如果我们需要修改成输出 "Hello World" ,我们便需要在已经转义一次的引号内再加入一对引号
    按照正确的转义方式,命令将修改为:

    1. tellraw @a {"text":"Hello World","clickEvent":{"action":"run_command","value":"/tellraw @a {"text":"\\"Hello World\\""}"}}
    复制代码


    需要注意,因为第二次转义, \ 也需要被转义,所以正确的写法为 \\\" 而非 \\" ,三次转义为 \\\\\\\" ,如此类推




    最后需要提醒的一点是,并非一见到引号内的引号就需要额外转义多一次
    而是需要小心分辨他们是否处于同一层次
    例如我要输出 ""Hello World""
    使用:

    1. tellraw @a {"text":""\\"Hello World\\"""}
    复制代码


    将会造成错误的输出

    正确的写法应为:

    1. tellraw @a {"text":"""Hello World"""}
    复制代码



    与资源包的配合
    有些地图把部分不常用的文字改为图片(没错,Minecraft里的文字是图片来的),然后用JSON来做到在聊天栏打印合成配方的特技。
    当然,这需要牺牲,就是玩家如果输入那些字符就会变为物品。不过只要用生僻字的话一般还是没有问题的。



    • key.forward: 移动按钮(向前)
    • key.left: 移动按钮(向左)
    • key.right: 移动按钮(向右)
    • key.back: 移动按钮(向后)
    • key.sneak: 潜行按钮
    • key.sprint: 疾行按钮
    • key.inventory: 打开背包
    • key.swapHands: 交换手(把物品在主手及副手之间交换)
    • key.drop: 掉落物品
    • key.use: 使用物品(一般为右键)
    • key.attack: 使用物品(攻击)
    • key.pickItem: 选择物品(滚轮)
    • key.chat: 打开聊天栏(t)
    • key.playerlist: 列出玩家(Tab)
    • key.command: 输入命令(/)
    • key.screenshot: 截图(F2)
    • key.togglePerspective: 调换镜头位置(f5)
    • key.smoothCamera: 平滑镜头(f8)
    • key.fullscreen: 全屏
    • key.spectatorOutlines: 旁观者高亮,旁观者模式时点击此按键就会高亮所有玩家(默认没有按键)
    • key.hotbar.[1-9]: 选择热键(1-9)
    • key.saveToolbarActivator: 储存工具栏
    • key.loadToolbarActivator: 加载工具栏




    NBT

    前言(?)
    NBT(二进制命名标签)格式为Minecraft中用于向文件中存储数据的一种存储格式。
    NBT格式以树形结构并配以许多标签的形式存储数据。所有的标签都有一个独立的ID和名称。
    ...

    等等! 我们不是在说命令么?怎么跑了去编程了?教练我不要学这个!

    其实NBT有两个意思:NBT文件格式以及命令中的NBT格式,两者表达方式是不同的,然而内里的数据是相同的。
    本文只会介绍命令中的NBT的表达方式,对NBT文件格式(二进制的)有兴趣的朋友可以参考 http://wiki.vg/NBT

    同时,部分标签的修改不能通过游戏内命令达成,需要使用外置修改器修改存档中的部分NBT文件,在此推荐 NBTExplorer 这个外置修改器

    下载地址:
    http://www.mcbbs.net/thread-306895-1-1.html

    NBT文件储存了很多重要资料,如存档资料、实体资料、方块资料等。
    通过命令中的NBT,我们能够修改并检查实体(玩家除外)、物品、方块实体的属性,也能检查玩家的部分属性。
    看完本章,你不会知道NBT的完整格式,然而你会知道最好的写法,最不容易出现错误的写法。


    NBT简介
    NBT和JSON类似,是由标签(Tag)组成的。而每个标签都有它们的数值。

    标签有不同的种类,我们可以大致分为四大类(前三类可以当作基本数值类(simple)):

    • 数值类(详细分类会包括整数和浮点数,里面又可以根据不同的大小、精度再分类)
    • 字串类(没错,字串是自成一类的)
    • 数组类(虽然数组也能包括多个数值,然而其特性和List有明显不同,之后将会详细解释,但并不常用)
    • 集合类(包括compound及list,将会在下方详述)
        集合类的数值为一个集合,也就是说能够储存另外的一些标签在里面
        故此,NBT的结构是一个结构
    Tag_End算不算一个Tag....我觉得那比较算是Tag_Compound的格式之一(二进制的时候),
    而且那只会在NBT文件里使用,因此就不需要理会了。

    接下来我们会看看NBT的大致结构,基本数值类的标签将会在之后的章节逐一说明。


    集合
    NBT前三者只是简单的数值类,不能储存更多标签,因此对整体结构没啥影响。
    这里就统一把它们的类型写作simple,方便阅读。

    集合类的NBT有两种,分别为Compound以及List,它们在资料储存方式和实际应用也有很大分别。
    我们首先来看看Compound


    Compound
    Compound,其实和JSON的物件非常类似。
    Compound里的每个标签都有一个名字(key),里面的标签类型不必一样。
    Compound里的标签名字非常重要,因为游戏依靠标签名字查找资料。
    故此,一个Compound内的标签不能重名

    技术说明到此为止,我们来看看一个例子。

    说例子前先说说这章例子的格式
    标签:  种类 名称: 数值
    种类有: simple, compound, list
    格式为"某"的就是字串,和数值不同
    compound和list的子标签会缩排(对齐缩进),以与其他标签分开

    1. compound a:
    2.     simple aa: 123
    3.     simple ab: 456
    4.     simple ac: "23333"

    5.     compound ad:
    6.         simple aa: 123
    7.         simple ab: 456
    8.         simple ac: "23333"
    复制代码
    可以看到,a这个compound里同时有数字、字串及另一个compound。

    然而在ad里,出现了和compound a里重名的标签!这不是违反了我们上面说的“一个Compound内的标签不能重名”?
    其实这不算重名,因为在a里叫aa的只有1个,另一个在a的ad里,分属于不同的compound




    那么我们来看看下一个例子

    1. compound a:
    2.     simple aa: 123456
    3.     simple aa: 1234
    复制代码
    这个例子就有错误了!
    a里有两个aa,所以我们指定a的aa是要数值为123456的呢,还是1234那个?没人知道。

    所以重复名称是不允许的。

    此外,Compound是不注重次序的(同一Compound内的子标签是没有前后次序之分的)
    对Compound来说最重要的是结构,也就是谁是谁的子标签
    故此,在命令里不需要理会Compound的子标签次序,只需要理会结构就好。


    格式
    现在来让我们看看命令里是怎么写Compound的。

    Compound的数值格式为:

    1. { 子标签 }
    复制代码
    子标签需要名字,并且以 , 分隔。

    而子标签需要名字,名字是这么写的:

    1. 名字:数值

    2. "名字":数值
    复制代码
    当名字包含不是 a-z A-Z 0-9 _ . 的字符时就需要用 "" 了(出现空格的话也需要),如果出现 \" 字符则需要转义,详见之后的字串章节(正常人也不会在名字里加入这奇奇怪怪的东西吧233333)。

    注:数值前后及名字前后(如果名字需要 """名字" )的空格都会被忽略




    例子(把例子1的格式转为命令里的NBT写法):

    1. a:{aa:123,ab:456,ac:"23333",ad:{aa:123,ab:456,ac:"23333"}}
    复制代码
    假设把第一个 ab 的名称改为 a b ,我们就得这么写了:

    1. a:{aa:123,"a b":456,ac:"23333",ad:{aa:123,ab:456,ac:"23333"}}
    复制代码
    记得开了 { 就得关掉 }
    修改NBT时只会修改指定了的NBT,不会清空整个Compound。
    检测亦如是,只会检测指定NBT。比如检查 {} 只能检查此compound是否存在,不能检查是否一个空的compound。
    更多的例子将会在之后的NBT命令实战一章介绍。


    List
    List就是一个列表,和Compound类似,也能储存多个tag,然而也有很大的分别。

    • 一旦被命令修改,之前的List就会被清空。(特例会在实战部分讲解)
    • 子标签没有名字,并且重视次序
    • 每个List只能储存一种标签。比如储存List,储存字串,储存Compound等等。(但里面的List可以储存不同种类的子标签,只要确保同一个List内的标签全部类型一致即可)
    一般提及List的时候,我们也会提及这List储存的类型,说法是 List of <类型> (中文就是 <类型>的列表

    例子:

    1. compound a:
    2.     <List of simple> b:
    3.         simple : 123
    4.         simple : 456
    5.         simple : 123
    复制代码



    错误例子:

    1. compound a:
    2.     <List of simple> b:
    3.         simple a: 123
    4.         compound b:
    5.             simple a: 123
    复制代码
    错误的原因有两个:

    • List里的子标签应该是没有名字的。
    • List里的子标签应该是同一类型的。(甚至即使它们都是基本类型也不行,需要类型完全一样,之后将会介绍基本类型的分类)

    格式
    现在来让我们看看命令里是怎么写List的。

    数值格式:

    1. [ 子标签 ]
    复制代码
    子标签没有名字,之间以 , 分隔。

    例子1

    1. a:{b:[123,456,123]}
    复制代码
    例子2

    1. {a:[{a:123},{a:456},{a:789}]}
    复制代码
    例子2外面那个无名的Compound在实际命令非常常见。
    检测的时候不会循序检测,只会看看目标列表里有没有这几个标签,不论次序。
    简单来说就是你无法控制次序

    设置为 [] 会直接清空列表。
    直接检查 [] 会检查该列表是否一个空的列表。

    之后的NBT命令实战一章将会有更多例子。




    下一个章节将会仔细将基本数值里面的数值类型。
    数值类型在MC里大量使用,NBT里最多的也是数值类型。
    数值类型有一些比较方便的写法,然而某些情况会失效,因此我们不会介绍那写法,而是介绍标准写法。如果需要学习便捷写法的话请自行寻找相关教程。



    基本类型

    数字类型
    NBT把数字分为两大种,分别为整数及浮点数,然后再细分为不同储存大小、精度的种类。

    • 整数
      • Byte (数值范围为 -128 到 127 )
      • Short (数值范围为 -32,768 到 32,767 )
      • Int (数值范围为 -2,147,483,648 到 2,147,483,647)
      • Long (数值范围为 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807)
    • 浮点数(类似科学计数法,能储存小数及很大的数值,然而精度有限,数值越小精度越高,反之亦然)
      • Float (精度较低)
      • Double (精度较高)


    整数格式
    1. <数值><后缀>
    复制代码
    数值部分必须为纯数字或纯数字且前方有个 + / - 号。
    纯数字不能以0开头,也就是不能有前导零(Leading zeros),除非那个数字就是0。

    类型后缀(大小写皆可)
    Byteb
    Shorts
    Int无后缀
    Longl
    例子: (前方为+的就是正确,-的就是错误)

    1. + 123b
    2. + 123B
    3. + 123
    4. + -123b
    5. + 0
    6. + +0
    7. + -0

    8. - 0123b
    9. (前导零)
    10. - 00
    11. (前导零)
    12. - +-123
    13. (只能出现一个`+`/`-`号)
    14. - 1e3
    15. (不支持科学记数法)
    16. - 133b
    17. (超出范围)
    复制代码
    命令NBT更改NBT时能够做自动类型变换,只要数值没有超出范围就可以
    然而建议全部都写上类型后缀,因为类型变换有时候可能会出问题,而且检测的时候也必须加上类型后缀


    布尔值
    布尔值是整数格式的一个特殊情况,只储存1 (True)及 0 (False)值。
    布尔值使用 Byte储存,比如是  NoAI:1bIsBaby:0b 这类。
    由于其实根本就是byte,所以一般也不会特别介绍。


    浮点数格式
    1. <数值><后缀>
    复制代码
    数值部分可以是

    • 整数,可以有前导零
    • 小数,可以有前导零
    • 科学记数法,如 1.23e1231.23e-123
      格式就是 <数值1>e<数值2> ,数值就是 <数值1>*10^<数值2>
    类型后缀(大小写皆可)
    Floatf
    Doubled
    例子

    1. 123f
    2. 123d
    3. 1.23e2f
    4. 1.23e2d
    5. -1.23e-2d
    6. 1.23e-2d
    复制代码
    注意,浮点数的数值不太准确,一般到4个位就差不多了
    别试图检查浮点数的NBT了...检查不了


    字串类型
    字串(String)类型,顾名思义就是储存字串(文字)的类型。

    数据并不总全是数字,比如物品的名称。为了方便使用,NBT里有字符类型可以储存字符。

    格式:

    1. 字符

    2. "字符"
    复制代码
    当字符出现了不属于 a-z A-Z 0-9 _ . (空格、中文字符也是不属于这些字符)里的字符,就需要使用第二个格式,也就是以 "" 括住,表示这是一个完整的字串。
    或者当该字符可能被当作是其他类型的时候(如纯数字或数字结尾为 bsldf 等字符(大小写皆可)),也需要使用第二个格式。

    如同Compound子标签的名字一样(Compound子标签的名字其实就是一个字串类型),当字串里出现了 \" 字符时就需要将这两个字符进行转义,方式为在字符前方加上 \ 号。转义方式可以参见之前JSON的介绍,大致一样。

    例子:

    NBT表示实际显示
    abcd abcd
    "abcd" abcd
    "123" 123
    123 这个不是字符串
    "ab cd" ab cd
    "say \"hi\"" say "hi"
    "中文" 中文
    minecraft:stone 这会出错
    "minecraft:stone" minecraft:stone
    "{\"abcd\":\"{\\\"abc\\\":\\\"第一行\\\\\\\\n第二行\\\"}\"}" {"abcd":"{\"abc\":\"第一行\\n\"}"}
    \n\uxxxx\ 字符都需要转义,因为这两个格式是JSON的而不是NBT的。

    注意,部分NBT,如实体ID,在生成时容许使用 id:实体id 的方式写,比如是 id:armor_stand
    然而,检测的时候是必须全写,也就是实体id前方得加上 minecraft: ,如 id:"minecraft:armor_stand"


    数组类型
    数组(Array)类型能储存多个数字,那些数字就是该数组的类型。
    和List类似,我们会叫特定类型的数组为 <类型>数组(array of <类型>)。
    数组和List最大的分别在于,List是查看子标签里是否存在那些检测的标签,而数组则是检查整个数组看看是否符合指定要求,检查包括该标签所在位置、顺序等等。

    目前支持的类型包括:

    • Byte
    • Int
    • Long
    格式:

    1. [类型前缀;子标签]
    复制代码
    子标签和List类似,都是只有数值的标签,之间以 , 分隔

    类型字符(必须大写)
    Byte B
    Int I
    Long L
    例子:

    1. [I;]
    2. 空的Int array

    3. [I;123,456]

    4. [B;12b,13b,14b]

    5. [L;123l,456l,789l]
    复制代码
    只有很少的地方需要用到数组...





    NBT实战
    这部分会涉及不少英语...
    而且玩NBT必须会点英语...因为都是英语词语
    英语不好的读者...请自行找个命令群问吧,并且得学好点英语啊23333


    阅读树视图(Treeview)
    Wiki 主要NBT页面:
    实体、方块NBT
    玩家、物品NBT

    Wiki中以树视图来表达NBT的继承关系(父compound/list与子标签)。
    标签左边的图标会标识每个标签的类型(看不清楚的话可以把鼠标放在那图标上面)。
    那格式相信已经非常清楚了,然而还是有点需要解释的。


    阅读子Compound
    首先,大家需要明白一个很重要的事实: Compound是分种类的。
    Compound根据子标签的不同,是有不同的"种类"的。我们一般会把常用的compound分类。类别如下(子类别为在父类别加上一些别的标签):

    • Entity (实体)
      • Mob (生,实体的子类别)
      • Projectile (弹射物,实体的子类别)
      • Block Entity (动态方块,实体的子类别)
      • ...
    • Item (物品)
    • Block (方块)
    • Tag (物品内的Tag)
    • Attribute
    • ...
    我们会在之后的部分简述其中一些标签。

    其实命令里的 Data tag (数据标签)也是有分"种类"的,实体相关的大部分为Entity,物品相关的为Tag,方块相关的为Block






    有时候会看到这种 See this format (recursive) (中文为 参见这个格式(递归) )。
    这代表里面这个Compound,就是这个部分最"大"的标签(在这个例子中,最大的标签就是Entity data,中文为实体数据)。

    那个部分在wiki里其实是这样的

    1. Entity data
    2.     id: string ...
    3.     Pos: list of 3 TAG_Doubles ...
    4.     ...
    5.     Passengers: list of the data of the entity riding...
    6.         see this format (recursive)
    复制代码
    我们看最"大"的tag,就是看没有父标签的那个,在这情况就是 Entity data






    有时候也会看见这种:The list of items .... (中文:....物品的列表)
    这说明下面的compound为item。


    阅读List元素
    List元素有两种,分别为有限(且顺序敏感)元素数量及不限制元素数量的。

    有限元素的分别有两种写法。第一种就如同上方的HandItems一样,就是List下面有多于一个标签,那些标签必须放在相应的位置。

    以HandItems作例子

    1. HandItems:[{id:"minecraft:stone",Count:1b},{id:"minecraft:glass",Count:1b}]
    复制代码
    石头就是放在主手,而玻璃就是放在副手。




    对于非Compound的有限元素,有时候就会这么写:数字 TAG_<类型>....,说明了元素数量及类型,如:

    Motion: 3 TAG_Doubles describing the current dX,dY,dZ velocity of the entity in meters per tick.

    这句讲解了List里的元素类型以及用途。而粗体的那三个字就是你要写的元素了。以下是一个例子:

    1. Motion:[1d,2d,3d]
    复制代码
    x轴上的速度为1m/s,y轴为2m/s,z轴为3m/s。




    不限制元素数量的写法有两种:第一种为在List下面有一个标签,第二种为只写着 List of ... 而之后的部分不是种类而是子标签用途。

    例子:

    1:

    2:  Tags: List of custom string data.

    这代表了子标签数量不设限制,而子标签次序一般并无影响。

    例子:

    1. Passengers:[{id:"minecraft:pig"},{id:"minecraft:armor_stand"}]

    2. Tags:[abc,def,ghjdfs,sfdsfsdf,sadasdsad]
    复制代码
    注: 是一般并无影响而不是绝对没有影响。
    在Passengers的例子里,如果根实体(被Passengers骑着的实体)为船,那么第一个及第二个实体的位置会有分别。只有一个实体和有两个甚至更多实体的位置也不同。

    List是无法直接修改指定索引值的标签的。赋值时也无法不覆盖掉原先的所有标签。


    阅读数组
    其实数组方面和List的不限制元素数量写法也十分相近,就是 Array of ...

    例子:

    Colors: Array of integer values corresponding to the primary colors of this firework's explosion...

    简单来说就是一堆数字,代表了那烟花的颜色。所以NBT的例子为:

    1. Colors:[I;123,456,789,123,456,789]
    复制代码
    1.12后数组有类型分别,分号前的值即代表其类别。


    例子1——给予物品
    give 命令的功能为给予物品,其格式为

    1. give <玩家> <物品id> [数量] [伤害值] [NBT]
    复制代码
    NBT(有时亦作数据标签,其实就是NBT)部分,其base tagtag

    什么是Base tag呢?其实这是一个概念,说的是这段NBT最外层的Compound是什么。

    上面我们说到,Compound也有分为不同种类的。有一些是Entity,一些是Item,一些是Tag。而不同命令使用的NBT也有所不同。

    比如是物品类的命令,如 give 命令,它们的NBT那里就是物品的额外NBT,其Base tag就是 tag ,意思就是最外层的compound类型为 tag

    而tag的(部分)子标签为

    1. tag: compound
    2. └── display:compound
    3.       ├── Name: 物品名称,string
    4.       └── Lore: 物品描述,string的list,每个string代表一行
    复制代码
    故此我们命令里的NBT就能这么写:

    1. {display:{Name:"物品名称",Lore:["第一行","第二行"]}}
    复制代码
    例子命令:

    1. give @p nether_star 1 0 {display:{Name:"原谅之星",Lore:["爱是一道光","如此美妙"]}}
    复制代码
    这命令给予玩家一个下界之星,名称为 原谅之星,描述为 爱是一道光 (下一行)如此美妙。


    例子2——物品自定义NBT
    只有物品的tag能有这个操作

    物品的tag里能够自定义NBT,通过自定义NBT,玩家能够方便的把物品分类并且选择物品的实体/持有物品的实体等。

    1. tag: compound
    2. ├── 自定义NBT1: 种类自定
    3. ├── 自定义NBT2: 种类自定
    4. ├── ...
    5. └── 自定义NBTn: 种类自定
    复制代码
    假设我们要给予玩家一些特别的物品,我们需要统一进行检查。(检测有没有持有那类的物品,给予buff或者避免重复给予玩家那类型物品)
    如果我们不使用自定义NBT,就需要逐个物品来检查,那就会十分麻烦,故此我们可以使用自定义NBT。

    1. #这是第一类,编程的别问我为啥从1开始数
    2. give @p diamond_axe 1 0 {CustomNBT:1b}
    3. give @p diamond_sword 1 0 {CustomNBT:1b}

    4. #这是第二类
    5. give @p iron_axe 1 0 {CustomNBT:2b}
    6. give @p iron_sword 1 0 {CustomNBT:2b}
    复制代码
    这样,比如我们要检查拿着第一类物品的玩家,我们可以通过以下命令:

    1. testfor @p {SelectedItem:{tag:{CustomNBT:1b}}}
    复制代码
    相比两条命令(分别检测 {SelectedItem:{id:"minecraft:diamond_axe"}}{SelectedItem:{id:"minecraft:diamond_sword"}} )明显方便了许多,而且这只是因为一个种类里的物品比较少:比较多物品的时候能更方便。

    提示:NBT里检测id的时候,无论是实体名称、方块id或者是物品id都得写 minecraft:

    检查NBT时,如果是同样精准度的话,我们会使用较少NBT的那个,因为效率会更高。而就物品来说,我们就可以使用自定义NBT,简单方便的进行检查。


    高级用法
    我们可以用大类小类的方式更有系统的分类,对小游戏地图特别有用。
    然而我们不必写很多特殊标签,我们只需要:Compound。

    比如说,以上两类都属于工具类别,那么我们就命名这个大类为 tools
    NBT改为 {tools:{CustomNBT:1b}}{tools:{CustomNBT:2b}}
    假设我们要检测小类,则正常方式也行。如果要检测大类,则可以只写 {SelectedItem:{tags:{tools:{}}}}
    是不是方便很多呢?2333


    例子3——天降补给
    生成一个掉落中的方块(Falling block),类型为箱子,里面装着一把剑。

    首先我们看看 falling_block 的NBT。

    1. falling_block
    2. ├──Block: 方块ID。字串。
    3. ├──TileEntityData: 方块实体的NBT。
    4. ├──Data: 方块的元数据。Byte。
    5. └──Time: 这掉落中的方块的存在时间(单位为游戏刻)。如果设置为0,过了1游戏刻后如果方块发现所处位置的方块id和此实体的方块id不同,就会消失。...(省却了和这部分无关系的描述)。当数值超过600或y坐标=0,这个实体就会消失。Int。
    复制代码
    至于箱子(一种方块实体)的NBT就是这样的

    1. chest
    2. └──Items: 箱子内的物品列表。
    复制代码
    而物品的格式就是

    1. Item
    2. ├──Count: 物品数量。byte。
    3. ├──Slot: 物品所处格子编号。byte。
    4. ├──Damage: 物品数据值。short。
    5. ├──id: 物品id。字串。
    6. └──tag: 物品的其他tag。
    复制代码
    首先我们写出这剑的NBT,假设我们希望是一把钻石剑,在箱子的第一格(编号从0开始)。

    1. {Count:1b,Slot:0b,Damage:0s,id:"minecraft:diamond_sword"}
    复制代码
    然后编写箱子的NBT(物品列表内的物品就是剑的NBT)

    1. {Items:[{Count:1b,Slot:0b,Damage:0s,id:"minecraft:diamond_sword"}]}
    复制代码
    最后编写掉落方块的NBT( TileEntityData 里的就是箱子的NBT)

    1. {Block:"minecraft:chest",Data:0b,Time:1,TileEntityData:{Items:[{Count:1b,Slot:0b,Damage:0s,id:"minecraft:diamond_sword"}]}}
    复制代码
    这例子显示了NBT格式是怎么引用别的NBT的。


    例子4——小僵尸Boss
    首先我们希望Boss的名字叫Boss。这和实体格式有关:

    然后如何定义一只小僵尸呢?我们就得看僵尸的NBT。

    1. zombie
    2. └──IsBaby: 僵尸是否婴儿。Byte。
    复制代码
    那么僵尸有没有定义名称的NBT呢?看起来是没有的。???

    其实僵尸(zombie)是实体(entity)的一个子类,因此僵尸里会继承所有属于实体的tag,比如是 CustomName

    1. Entity
    2. ├──CustomName: 实体的名称。字串。
    3. └──CustomNameVisible: 实体名称是否可见。Byte。
    复制代码
    可以这么想,僵尸有的NBT为:

    1. zombie
    2. ├── 一切实体的NBT
    3. └── 僵尸独有的NBT
    复制代码
    也就是

    1. zombie
    2. ├──CustomName
    3. ├──CustomNameVisible
    4. ├──IsBaby
    5. └──...
    复制代码



    好了我们怎么弄一只boss呢?我们可以修改属性,也就是Attribute。然而在僵尸的NBT里看不到Attribute啊!是不是代表没有呢?

    不是的,其实僵尸也属于生物(Mob),而Mob就有我们需要的Attribute了。
    僵尸的继承体系是:

    • entity
      • mob
        • 怪物monster, 不死类生物 Undead (这里不影响NBT,但影响其行为)


    Mob的格式是这样的:

    1. Mob
    2. ├──Attributes: Attributes列表。
    3. │   └┬─ 一个Attribute
    4. │    ├──Name: attribute的名称(我们改血量,写generic.maxHealth)
    5. │    ├──Base: attribute的数值(写30),类型为byte。
    6. │    ├──...
    7. ├──Health: 血量(只改maxHealth只会修改最大血量,实际血量还是20)。float。
    8. └──...
    复制代码
    所以NBT可以这么写:

    1. {CustomName:Boss,CustomNameVisible:1b,IsBaby:1b,Attributes:[{Name:"generic.maxHealth",Base:30b}],Health:30.0f}
    复制代码
    注意: 使用 summon 命令生成实体时我们不是在指定实体的所有标签,我们只是修改特定的标签,其他标签还是会自动赋予的,其中一些会被随机生成。有一些NBT只能在实体生成时设置,生成后就会消失。


    样式代码
    有时候我们会希望在NBT加入样式代码,来为比如是物品名称或描述加上颜色等样式。

    样式代码其实就是 §<符号> ,之后的字符根据会加上特定样式。样式决定于 § 后的符号,和JSON那些样式类似。也能够混合使用(效果会叠加直至 §r 的出现)。

    颜色:


    特殊样式:

    样式代码效果
    §k混淆(obfuscated)
    §l粗体(bold)
    §m删除线(strikethrough)
    §n下划线(underline)
    §o斜体(italic)
    §r重置(reset),即前方样式不会对后方有作用
    例子:

    1. {CustomName:"§a123456§r"}

    2. {display:{Lore:["§a§l粗体原谅"]}}
    复制代码
    然而是无法以正常方式向游戏内输入 § 字符的。
    最方便的方式为通过命令函数输入,如果不能使用命令函数的话可以使用牌子点击黑科技,链接:http://www.mcbbs.net/thread-443181-1-1.html
    除了NBT以外,其他地方也会使用 § 字符代表颜色,比如存档名称、advancement、记分板假名等等。




    例子

    命令:

    1. give @p nether_star 1 0 {display:{Name:"§a§l爱是一道光",Lore:["如此美妙"]}}
    复制代码
    效果:


    你们是不是以为如此美妙的部分也是绿色和粗体?不是说好的 之后的字符根据会加上特定样式 么?

    其实是这样的,那句 之后的字符根据会加上特定样式 其实说的是同一个NBT内,比如是Name里面,或者是Lore里面的一个子标签里面。
    故此,Lore部分是独立于Name部分的,也不会获得那原谅Buff。


    其他
    这里会说一些NBT的额外资料。

    部分NBT是生成后就会消失的,如UUID,别想着要改了。
    部分NBT是只读(Read only)不能修改的,如OnGround这些,而且你修改了也没用。

    有时候会看见别人写类型的,如Item:  {id:"minecraft:stone",Count:1}
    然而其实这并不是错的,这是利用了NBT的型别转换(Type casting),也就是说修改NBT时能自动把类型转为正确类型。(当然,超出了正确类型范围的时候就不会自动转换了)
    不过我们并不建议这种写法,因为有很大几率会出现错误,并且在检测NBT的时候不允许使用这种写法。

    生物的ActiveEffects不建议直接修改。部分和attribute有关的状态效果需要attribute modifier。故此只声明ActiveEffects是无效的。

    生物的Attribute很坑(包括AttributeModifier,比如史莱姆的maxHealth改了也没用...)...建议使用前多测试。

    检测生物有没有受到攻击可以检测生物 HurtTime 。(function的话可以考虑检测 9s ,命令方块的话得+1s,检测 10s 。这是由于gameLoopFunction在生物更新后执行。原则上 10s1s 都可以用于检测,但一般我们都需要即时获取状态。)

    别试图检测Float/Double,你往往不要指望恰好能达到你所检测的值...例如检查实体视角时更常见的是使用选择器参数而不是相应NBT。

    处理火球的时候记着设置direction。motion对它是没用的,并且不设置direction根本生成不了。

    重要!!!
    村民的 Inventory 设置的时候只会增加物品,不会覆盖。
    比如原先有 [{id:"minecraft:stone",Count:1b,Damage:0s}] ,我们设置 Inventory:[{id:"minecraft:stone",Count:1b,Damage:0s}] ,村民的Inventory NBT会变为 [{id:"minecraft:stone",Count:2b,Damage:0s}]
    假如我们在以上的基础上设置 [{id:"minecraft:stone",Count:1b,Damage:1s}] ,村民的Inventory会变为 [{id:"minecraft:stone",Count:2b,Damage:0s},{id:"minecraft:stone",Count:1b,Damage:1s}]
    而且村民的 replaceitem 命令中的 slot.villager.数字 是基于这个列表里的物品位置的,第一个的数字就是 0 ,第二个就是 1 ,如此类推。但实际上在村民的Inventory里是不会有 Slot 这个NBT的。我们需要移除物品就只能靠 replaceitemair 了。 replaceitemair 之后物品会向前补充那空缺。
    幸好这奇奇怪怪的特性不常见...

    此特性由Yaossg发现

[groupid=546]Command Block Logic[/groupid]