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里其实是这样的

Entity data
    id: string ...
    Pos: list of 3 TAG_Doubles ...
    ...
    Passengers: list of the data of the entity riding...
        see this format (recursive)

我们看最"大"的tag,就是看没有父标签的那个,在这情况就是Entity data


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

阅读List元素

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

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

以HandItems作例子

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里的元素类型以及用途。而粗体的那三个字就是你要写的元素了。以下是一个例子:

Motion:[1d,2d,3d]

x轴上的速度为1m/s,y轴为2m/s,z轴为3m/s。


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

例子:

1:

2: Tags: List of custom string data.

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

例子:

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

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的例子为:

Colors:[I;123,456,789,123,456,789]

1.12后数组有类型分别,分号前的值即代表其类别。

例子1——给予物品

give命令的功能为给予物品,其格式为

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的(部分)子标签为

 tag: compound
 └── display:compound
      ├── Name: 物品名称,string
      └── Lore: 物品描述,string的list,每个string代表一行

故此我们命令里的NBT就能这么写:

{display:{Name:"物品名称",Lore:["第一行","第二行"]}}

例子命令:

give @p nether_star 1 0 {display:{Name:"原谅之星",Lore:["爱是一道光","如此美妙"]}}

这命令给予玩家一个下界之星,名称为 原谅之星,描述为 爱是一道光 (下一行)如此美妙。

例子2——物品自定义NBT

只有物品的tag能有这个操作

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

tag: compound
├── 自定义NBT1: 种类自定
├── 自定义NBT2: 种类自定
├── ...
└── 自定义NBTn: 种类自定

假设我们要给予玩家一些特别的物品,我们需要统一进行检查。(检测有没有持有那类的物品,给予buff或者避免重复给予玩家那类型物品)
如果我们不使用自定义NBT,就需要逐个物品来检查,那就会十分麻烦,故此我们可以使用自定义NBT。

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

#这是第二类
give @p iron_axe 1 0 {CustomNBT:2b}
give @p iron_sword 1 0 {CustomNBT:2b}

这样,比如我们要检查拿着第一类物品的玩家,我们可以通过以下命令:

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。

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

至于箱子(一种方块实体)的NBT就是这样的

chest
└──Items: 箱子内的物品列表。

而物品的格式就是

Item
├──Count: 物品数量。byte。
├──Slot: 物品所处格子编号。byte。
├──Damage: 物品数据值。short。
├──id: 物品id。字串。
└──tag: 物品的其他tag。

首先我们写出这剑的NBT,假设我们希望是一把钻石剑,在箱子的第一格(编号从0开始)。

{Count:1b,Slot:0b,Damage:0s,id:"minecraft:diamond_sword"}

然后编写箱子的NBT(物品列表内的物品就是剑的NBT)

{Items:[{Count:1b,Slot:0b,Damage:0s,id:"minecraft:diamond_sword"}]}

最后编写掉落方块的NBT(TileEntityData里的就是箱子的NBT)

{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。

zombie
└──IsBaby: 僵尸是否婴儿。Byte。

那么僵尸有没有定义名称的NBT呢?看起来是没有的。???

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

Entity
├──CustomName: 实体的名称。字串。
└──CustomNameVisible: 实体名称是否可见。Byte。

可以这么想,僵尸有的NBT为:

zombie
├── 一切实体的NBT
└── 僵尸独有的NBT

也就是

zombie
├──CustomName
├──CustomNameVisible
├──IsBaby
└──...

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

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

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

Mob的格式是这样的:

Mob
├──Attributes: Attributes列表。
│   └┬─ 一个Attribute
│    ├──Name: attribute的名称(我们改血量,写generic.maxHealth)
│    ├──Base: attribute的数值(写30),类型为byte。
│    ├──...
├──Health: 血量(只改maxHealth只会修改最大血量,实际血量还是20)。float。
└──...

所以NBT可以这么写:

{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),即前方样式不会对后方有作用

例子:

{CustomName:"§a123456§r"}

{display:{Lore:["§a§l粗体原谅"]}}

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


例子

命令:

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发现

results matching ""

    No results matching ""