SPGoding
何为ㄆㄧㄉㄧㄎㄞㄊㄜ


ㄆㄧㄉㄧㄎㄞㄊㄜ(predicate),社区常见译名「谓词」「战利品表条件」「皮迪凯特」等,在平常交流时可以任意采用合适的、不易与其他词语产生混淆的叫法。其是在 19w38a 中加入的新内容,是数据包的组成文件之一。


说是新内容,其实ㄆㄧㄉㄧㄎㄞㄊㄜ就是原先战利品表中的条件,只不过现在可以被单独抽离出来形成新的文件而已。没有接触过战利品表?没关系,本文将从零开始。


简单来讲,ㄆㄧㄉㄧㄎㄞㄊㄜ储存的是一系列对实体、位置、天气、环境等上下文(context)的判定条件。首先写好一个ㄆㄧㄉㄧㄎㄞㄊㄜ,再给定一个上下文,游戏就能判定该上下文是否是你想要的。好了,我说完了,大概没什么难理解的。




文件格式


所有ㄆㄧㄉㄧㄎㄞㄊㄜ文件均为 JSON 格式,放置在数据包的 ./data/<命名空间>/predicates 文件夹下。


该文件内容是一个对象。其中含有 condition 字段,指明所用条件的名称;同时还需含有该条件所需的各种附加参数:





应用


命令 execute (if|unless) predicate <ㄆㄧㄉㄧㄎㄞㄊㄜ的命名空间 ID>


该命令能够检测命令的执行者和执行位置等上下文是否满足指定的ㄆㄧㄉㄧㄎㄞㄊㄜ。在 if 模式下,只有满足指定ㄆㄧㄉㄧㄎㄞㄊㄜ时,测试才能通过;在 unless 模式下则相反。特别地,当命令执行者并不是实体(例如命令方块、控制台等),且ㄆㄧㄉㄧㄎㄞㄊㄜ中有对实体的限定条件时,在 unless 模式下也能导致测试通过。


实体选择器参数 predicate


通过指定该选择器参数,能够筛选出满足(或不满足)指定ㄆㄧㄉㄧㄎㄞㄊㄜ的实体。例如 @a[predicate=minecraft:test] 能够选中所有满足放置在数据包下 ./data/minecraft/predicates/test.json 的文件中条件的玩家,而在等号后方添加一个半角感叹号(!)则将选中所有满足该ㄆㄧㄉㄧㄎㄞㄊㄜ的玩家。


tag 等选择器参数一样,选择器中能够指定多个 predicate 参数,只有满足所有参数的实体才能被选中。例如,@e[predicate=do,predicate=!not,sort=nearest,limit=1] 会选中最近的、满足 do ㄆㄧㄉㄧㄎㄞㄊㄜ、且不满足 not ㄆㄧㄉㄧㄎㄞㄊㄜ的 1 个实体。


相比于用 nbt 选择器参数,predicate 选择器参数在大多数情况下性能都会更好。这是因为,nbt 选择器参数的检测原理是,先把实体的所有数据转换为 NBT,再将转换后的 NBT 与用户输入的 NBT 进行比较,这些操作十分耗时。而ㄆㄧㄉㄧㄎㄞㄊㄜ会在游戏加载数据包以后就初始化完毕,在选择实体时会直接调用实体的各种方法进行比较,省去了转换为 NBT 的过程。


战利品表


战利品表的条件(conditions)数组中的每一个对象就是ㄆㄧㄉㄧㄎㄞㄊㄜ。有关战利品表的详细内容可以参阅【CBL|SPG】[1.15] 战利品表 —— 数据包的组成文件之一




附录 1:通用谓词


说明


在ㄆㄧㄉㄧㄎㄞㄊㄜ文件(以及进度的触发器、战利品表的条件)中有许多共通的 JSON 结构。这些结构能够对某个单一的输入(如物品、实体、位置等)根据指定条件做出判定,符合计算机界术语谓词(predicate)的定义,因此在本文中我将其称为谓词。


本文中这些通用结构的提炼都是以游戏源代码为基础,而非以「形似」为基础的,能够保证一定的可靠性。


范围谓词


「范围谓词」能够判断一个数字是否在你所指定的范围之中。


其格式可以是一个数字。当一个数字与你指定的数字相等时,该范围谓词判定成功。



其格式也可以是一个对象,表明了该数字应当位于的范围。当一个数字处于你指定的范围中时,该范围谓词判定成功。



以下是几个例子。


用数字表示精确的「等于」


代码:

  1. "xxx": 5

xxx 的值确实为 5 时,该谓词测试通过。


用对象表示精确的「等于」


代码:

  1. "xxx": { "min": 5, "max": 5 }

xxx 的值确实为 5 时,该谓词测试通过。


用对象表示「大于等于」


代码:

  1. "xxx": { "min": 5 }

xxx 的值大于等于 5 时,该谓词测试通过。


用对象表示「小于等于」


代码:

  1. "xxx": { "max": 5 }

xxx 的值大于等于 5 时,该谓词测试通过。


用对象表示「在两数之间」


代码:

  1. "xxx": { "min": 5, "max": 10 }

xxx 的值大于等于 5 并且小于等于 10 时,该谓词测试通过。


状态谓词


判断一个方块的方块状态或流体的流体状态是否满足你所指定的各个值。



方块谓词


判断一个方块是否满足你所指定的各个条件。



流体谓词


判断一个流体是否满足你所指定的各个条件。



位置谓词


判断当前的位置是否满足你所指定的各个条件。



物品谓词


判断一个物品是否满足你所指定的各个条件。



实体谓词


判断一个实体是否满足你所指定的各个条件。



伤害类型谓词


判断一个伤害的类型是否满足你所指定的各个条件。





附录 2:条件列表


该列表最终更新时间:1.15.1


说明


通常,ㄆㄧㄉㄧㄎㄞㄊㄜ中的参数大多是可以省略的。一旦省略该参数,表明你对该参数的值没有任何要求:即不论实际情况中该参数为何值,甚至在该参数没有值的情况下,ㄆㄧㄉㄧㄎㄞㄊㄜ都绝不会因为这个参数的原因而不通过。但是,有些参数是不能省略的,一旦省略游戏就会报错。可以在ㄆㄧㄉㄧㄎㄞㄊㄜ没有正确读取时,打开游戏日志查看报错信息,并回帖提醒本人为该参数添加注释。


适用范围


每个条件都只能在一定的范围下使用。在本文中,将使用 [E] 表示能在 *xecute (if|unless) predicate 命令中正常运作,用 [S] 表示能在体选择器(selector)参数中正常运作,用 [L:xxx] 表示能在 minecraft:xxx 以及 minecraft:generic 类型的战利品表(loot table)正常运作。


在不适用的地方使用某个条件,会导致该条件永远不通过。如果用在不合适的战利品表中,还会引起游戏在加载该数据包时在日志中显示警告:Found validation problem in {战利品表的命名空间 ID}.出现该错误的 JSON 路径: Parameters [<parameter 出问题的参数名>] are not provided in this context


minecraft:alternative [E|S|L:*]


析取范式。即,若指定的条件中只要有任一个通过,则该条件通过;如果指定的所有条件都不通过,则该条件不通过。



例子:


代码:

  1. {
  2.     "condition": "minecraft:alternative",
  3.     "terms": [
  4.   {
  5.    "condition": "minecraft:weather_check",
  6.    "raining": false
  7.   },
  8.   {
  9.    "condition": "minecraft:match_tool",
  10.    "predicate": {
  11.     "item": "minecraft:diamond_axe"
  12.    }
  13.   }
  14.     ]
  15. }

当玩家使用的工具为钻石斧,或当前天气为晴天时,条件通过。


minecraft:block_state_property [L:block]


匹配被破坏方块。



例子:


代码:

  1. {
  2.     "condition": "minecraft:block_state_property",
  3.     "block": "minecraft:yellow_bed",
  4.     "properties": {
  5.   "part": "head"
  6.     }
  7. }

当被破坏的方块是黄色床的头的一部分时,条件通过。床在被破坏时,头和脚两部分会分别执行战利品表。为了避免掉落两个床,Minecraft 在写床的战利品表的时候加了一个 "part": "head" 的限制。


minecraft:damage_source_properties [L:entity]


匹配该实体死亡时受到的伤害。



例子:


代码:

  1. {
  2.     "condition": "minecraft:damage_source_properties",
  3.     "predicate": {
  4.   "taken": {
  5.    "min": 20
  6.   }
  7.     }
  8. }

当实际造成伤害大于等于 20 时,条件通过。


minecraft:entity_properties [E|S|L:entity]


在指定的实体满足指定条件时,该条件通过。



例子:


代码:

  1. {
  2.     "condition": "minecraft:entity_properties",
  3.     "predicate": {
  4.   "flags": {
  5.    "is_on_fire": true
  6.   }
  7.     },
  8.     "entity": "this"
  9. }

该条件会在 this 指定的实体着火时通过。可以在战利品表中利用它做出生物被烧死后掉落熟食的效果。


代码:

  1. {
  2.     "condition": "minecraft:entity_properties",
  3.     "predicate": {
  4.   "equipment": {
  5.    "mainhand": {
  6.     "item": "minecraft:air"
  7.    }
  8.   }
  9.     },
  10.     "entity": "this"
  11. }

该条件会在 this 指定的实体主手中没有拿任何物品时通过。


minecraft:entity_scores [E|S|L:entity]


在指定的实体的分数满足指定条件时,该条件通过。



例子:


代码:

  1. {
  2.     "condition": "minecraft:entity_scores",
  3.     "entity": "killer_player",
  4.     "scores": {
  5.   "foo": {
  6.    "min": 10
  7.   },
  8.   "bar": 15
  9.     }
  10. }

在击杀该实体的玩家 foo 分数大于 10,且 bar 分数等于 15 时,条件通过 [L:entity]


minecraft:inverted [E|S|L:*]


取反。即,若指定的条件通过,则该条件不通过;否则,该条件通过。



例子:


代码:

  1. {
  2.     "condition": "minecraft:inverted",
  3.     "term": {
  4.   "condition": "minecraft:random_chance",
  5.   "chance": 0.3
  6.     }
  7. }

term 内指定的条件有 30% 的概率通过,因此整个 inverted 条件有 70% 的概率通过。


minecraft:killed_by_player [L:entity]


当前实体被玩家击杀时,条件通过。



例子:


代码:

  1. {
  2.     "condition": "minecraft:killed_by_player"
  3. }

minecraft:location_check [E|S|L:*]


当前位置满足指定条件时,条件通过。



例子:


代码:

  1. {
  2.     "condition": "minecraft:location_check",
  3.     "predicate": {
  4.   "biome": "minecraft:jungle"
  5.     },
  6.     "offsetX": -10
  7. }

将当前位置向 X 轴负方向偏移 10 米后如果处于丛林生态群系,则条件通过。


minecraft:match_tool [L:block,fishing]


匹配玩家使用的工具。



例子:


代码:

  1. {
  2.     "condition": "minecraft:match_tool",
  3.     "predicate": {
  4.   "enchantments": [
  5.    {
  6.     "enchantment": "minecraft:silk_touch",
  7.     "levels": {
  8.   "min": 1
  9.     }
  10.    }
  11.   ]
  12.     }
  13. }

当玩家使用的工具具有「精准采集Ⅰ」及以上的魔咒,条件通过。


minecraft:random_chance [E|S|L:*]


游戏会生成一个 0.0 到 1.0 的随机数,当该数字小于等于被比数时,条件通过。



例子:


代码:

  1. {
  2.     "condition": "minecraft:random_chance",
  3.     "chance": 0.3
  4. }

该条件有 30% 的几率通过


minecraft:random_chance_with_looting [E|S|L:entity]


游戏会生成一个 0.0 到 1.0 的随机数,当该数字小于等于被比数时,条件通过 [E|S|L:entity]


击杀者的抢夺附魔等级会影响被比数的大小 [L:entity]



例子:


代码:

  1. {
  2.     "condition": "minecraft:random_chance_with_looting",
  3.     "chance": 0.3,
  4.     "looting_multiplier": 0.1
  5. }

该条件有 30% 的几率通过 [E|S|L:entity]。每多一级抢夺魔咒,通过几率增加 10 个百分点 [L:entity]


minecraft:reference [E|S|L:*]


引用定义的其他ㄆㄧㄉㄧㄎㄞㄊㄜ文件。



例子:


代码:

  1. {
  2.     "condition": "minecraft:reference",
  3.     "name": "test:abc"
  4. }

该条件将会引用定义在数据包 ./data/test/predicates/abc.json 文件中的ㄆㄧㄉㄧㄎㄞㄊㄜ。当被引用的ㄆㄧㄉㄧㄎㄞㄊㄜ能够通过时,该条件通过。


minecraft:survives_explosion [E|S|L:block]


如果该方块是被爆炸破坏的,该条件有 1/爆炸半径 的几率通过;如果该方块是被玩家正常挖掘的,该条件永远通过 [L:block]


该条件永远通过 [E|S]


例子:


代码:

  1. {
  2.     "condition": "minecraft:survives_explosion"
  3. }

minecraft:table_bonus [L:block]


分别定义不同级别的附魔等级下条件的通过几率。



例子:


代码:

  1. {
  2.     "condition": "minecraft:table_bonus",
  3.     "enchantment": "minecraft:fortune",
  4.     "chances": [
  5.   0.05,
  6.   0.0625,
  7.   0.083333336,
  8.   0.1
  9.     ]
  10. }

当玩家没有时运附魔时,有 5% 的几率通过;当玩家有 1 级时运时,有 6.25% 的几率通过;当玩家有 2 级时运时,有 8.3333336% 的几率通过;当玩家有 3 级及以上的时运时,有 10% 的几率通过。


minecraft:time_check [E|S|L:*]


检测当前游戏内的时间。



例子:


代码:

  1. {
  2.     "condition": "minecraft:time_check",
  3.     "value": 6000
  4. }

该条件会在游戏内每天正午(6000)的那一刻通过。


代码:

  1. {
  2.     "condition": "minecraft:time_check",
  3.     "value": 6000,
  4.     "period": 12000
  5. }

该条件会在游戏内每天正午(6000)或午夜(18000)的那一刻通过。


minecraft:weather_check [E|S|L:*]


检测当时的天气。



例子:


代码:

  1. {
  2.     "condition": "minecraft:weather_check",
  3.     "raining": true,
  4.     "thundering": false
  5. }

该条件会在普通的雨天通过,在晴天或雷雨天均不会通过。




附录 3:Datapack Helper Plus (JSON)


Datapack Helper Plus (JSON)(简称 DHP (JSON),中文名大憨批杰森)是一款优秀的 VSCode 插件,提供适用于 Minecraft 1.15 数据包 JSON 文件的自动补全与格式校验。在该款插件的帮助下,编写ㄆㄧㄉㄧㄎㄞㄊㄜ以及其他各种文件(如进度、配方、战利品表、各种标签)将变得十分方便。请您坐和放宽,前往该插件的发布帖一览究竟。




致谢




SPGoding
请哪位版主帮忙把这个帖子锁了,谢谢茄子。

顺心yi
6666666666666666

fairywonn
很好很好很好很好

248295928
6666666666666666666

ghfcjy
好复杂啊

BBERR
6666666666666666