跳到主要内容

物品配置

Baikiruto 的物品配置围绕 ItemDefinitionLoader 展开,支持模型继承、显示模板、运行时数据、脚本、内置 Meta 快捷配置,以及 1.20.5+ 的 components

和现有很多物品系统不同,Baikiruto 会把配置拆成“模板层”和“运行时数据层”两部分:

  • 模板层:modelsdisplays、物品基础 ItemStack
  • 运行时数据层:datadata-mappereffectsmetacomponentsi18n

配置文件结构

每个 items/*.yml 都支持多种真实加载方式。

方式 1:完整结构(推荐)

__group__:
models:
displays:
items:

这是默认 items/example.yml 使用的结构,也是最推荐的写法。

__group__ 的实际作用

__group__:
id: "example"
path: "example"
priority: 100
icon: "example:all_features"

这个节点主要影响 /baikiruto menu 的分组展示:

  • id 是菜单分组 ID
  • path 是菜单里显示给你的路径名
  • priority 越高,分组越靠前
  • icon 可以直接写 Baikiruto 物品 ID,也可以写原版材质名

如果你完全不写 __group__,Baikiruto 会按当前文件在 items/ 下的相对路径自动生成:

  • 例如 items/weapons/swords.yml 默认会生成分组 ID weapons/swords
  • 它的父分组会自动视为 weapons

方式 2:单物品模式

material: "DIAMOND_SWORD"
name: "Example Sword"
lore:
- "A simple sword"

当文件本身不包含 itemsmodelsdisplays 等保留节点时,loader 会把整个文件当成一个物品定义,物品 ID 默认取文件名。

方式 3:顶层键模式

my_custom_item:
material: "STONE"
name: "Custom Item"

保留顶层键以外的 section,也会被当成独立物品条目读取。

方式 4:兼容简写

源码还支持部分兼容语法,适合做小型文件或过渡迁移。

顶层 display: 单显示定义:

display:
name: "&7<item_name>"
lore:
- "&9<item_type>"
- "&f<item_description...>"

这种写法会把当前文件里的 display 当成一个显示模板定义,模板 ID 默认就是 display

顶层 foo$: 模型简写:

"example/base$":
material: "NETHERITE_SWORD"
effects:
glow: true

这种写法会把键名末尾的 $ 去掉,真正注册出来的模型 ID 是 example/base

但日常文档和生产配置仍建议优先使用完整结构,兼容简写更适合快速验证或迁移旧配置。

核心配置节点

1. 基础属性节点

items:
example:
id: "example:item"
material: "NETHERITE_SWORD"
icon: "DIAMOND"
version-hash: "m12111-example"
model: "example/base"
from:
- "example/base"
display: "example/default"

字段说明:

  • id:物品 ID;未填写时默认取当前条目的键名
  • material / icon / type:材质字段,三者等价
  • version-hash:显式版本哈希;未填写时源码会根据配置自动计算 SHA-1
  • model / from:继承模型,可写字符串或列表
  • display:关联显示模板 ID

注意:

  • material 不是严格必填;若当前条目和继承链都没给材质,最终会回退到 STONE
  • modelfrom 都能参与模型继承,常用上可以把 model 理解成单引用快捷写法

2. 显示节点

name(物品名称)

# 字符串写法
name: "&6传说之剑"

# Map 写法
name:
item_name: "&6传说之剑"

# 锁定显示名
name!!:
item_name: "&6Locked Name"

lore(物品描述)

# List 写法
lore:
- "&7Line 1"
- "&7Line 2"

# Map 写法
lore:
item_type: "&7类型: 武器"
item_stats:
- "&7攻击: {damage}"
item_description:
- "&7一把传说中的神剑"

# 锁定描述
lore!!:
item_description:
- "&7Locked lore"

显示节点的真实特性:

  • name 支持字符串或 map
  • lore 支持字符串列表或 map
  • lore 为 map 时,键会按排序顺序拼装到最终 lore 中
  • 显示文本在 RELEASE 显示阶段才会做运行时变量替换
  • 如果你在 config.yml 里开启了 settings.mini-message.enabled<red><gradient:...> 这类标签也可以直接写进名称和 Lore

3. 数据节点 (data)

data:
durability: 240
charge: 3
player:
level: 1

durability!!: 240
player.level!!: 1

data 会直接进入运行时数据。

锁定规则:

  • 使用 !! 后缀表示锁定路径
  • 被锁定的数据路径会写入 __locked_data_paths__
  • 后续脚本或重建时,锁定路径不能被随意覆盖

4. 数据映射器节点 (data-mapper)

data-mapper:
durability_line:
type: fluxon
script: |
def current = &data["durability_current"] ?: &data["durability"] ?: 0
def max = &data["durability"] ?: 0
return current.toString() + "/" + max.toString()

data-mapper 会把脚本编译成运行时映射,在 toItemStack() 早期执行。

当前规则:

  • 可以继续直接写成字符串或字符串列表
  • 也可以像上面这样显式写 type + script
  • engine 可作为 type 的别名,source / content 也能代替 script
  • loader 最终会把 mapper 统一整理成带 typesource 的内部结构

注意时机:

  • data-mapperItemReleaseEvent 之前运行
  • durability_barcooldown_remaining 这类显示期变量尚未注入
  • 因此推荐在 mapper 中使用原始运行时数据,不要依赖显示阶段才生成的派生变量

5. 效果节点 (effects)

effects:
glow: true
item-flags:
- HIDE_ENCHANTS
- HIDE_ATTRIBUTES

effects 是兼容层效果映射,适合常见视觉和基础属性键。

详见 视觉效果

6. 组件节点 (components)

components:
custom_name: "&6Example Item"
enchantments:
levels:
sharpness: 5
attribute_modifiers:
modifiers:
- type: "attack_damage"
amount: 6.0
operation: "add_value"
slot: "mainhand"

components 是现代原版 Data Components 的主入口。

详见 原版组件

7. 国际化节点 (i18n)

i18n:
en_us:
name:
item_name: "English Name"
lore:
item_description:
- "English description"

zh_cn:
name:
item_name: "中文名称"
lore:
item_description:
- "中文描述"

i18n 会作为运行时数据的一部分保留,并在显示和脚本阶段按当前 locale 选择对应内容。

注意:

  • 它不是简单的“整份配置最高优先级覆写”
  • 当前最关键的是本地化 name / lore / scripts / event
  • i18n.<locale>.scriptsi18n.<locale>.event 也沿用同一套脚本源写法,既兼容旧的纯字符串,也支持 type: fluxon

8. 脚本节点 (scripts)

scripts:
build:
type: fluxon
script: |
return item

release:
type: fluxon
script: |
&ops.setData("last_release", "release")
return item

release_display: |
&ops.setData("last_release_display", "release_display")
return item

drop: |
return item

常见生命周期脚本:

  • build
  • release
  • release_display
  • drop

注意:

  • loader 会同时合并 scriptsevent 下的脚本条目
  • 旧的纯字符串写法仍然可用;如果你要跟新默认示例保持一致,推荐写成 type: fluxon + script: |
  • type 默认会回落到 fluxonengine 也能当作别名使用
  • scriptsourcecontent 都能放脚本文本;字符串列表会自动按换行拼接
  • 如果配置里声明了未注册的脚本类型,这条脚本会被跳过,并输出 log-script-type-missing
  • !! 后缀在动作触发器里用于取消底层 Cancellable 事件;对 build / release 这类生命周期脚本不要理解成“取消 BUILD/RELEASE 阶段”

9. 事件节点 (event)

event:
on_use:
type: fluxon
script: |
&ops.setData("last_trigger", "use")
return item

on_right_click:
type: fluxon
script: |
&ops.setCooldown(80)
&ops.setData("last_trigger", "right_click")
return item

on_attack: |
&ops.setData("last_trigger", "attack")
return item

data:
source: "example"

默认示例里展示过的常见触发器包括:

  • on_use
  • on_interact
  • on_left_click
  • on_right_click
  • on_right_click_entity
  • on_attack
  • on_damage
  • on_block_break
  • on_item_break
  • on_consume
  • on_pickup
  • on_swap_to_mainhand
  • on_swap_to_offhand
  • on_select
  • on_async_tick

如果你要控制 on_async_tick 的开关、触发间隔,或“只在某些玩家状态、世界、权限、游戏模式 / 特定槽位触发”,不要把这些条件写在 event 里,而是写到 meta.async-tick;脚本文本本身仍然写在 event.on_async_tick

默认 items/example.yml 里其实还示范了 on_deathon_killon_hurton_shooton_projectile_hiton_sneakon_sprinton_jumpon_respawnon_equipon_unequip 等更偏战斗 / 装备联动的触发器;完整 31 种写法建议直接对照 脚本系统

事件脚本和生命周期脚本共用同一套解析规则:

  • 可以直接写 on_use: |
  • 也可以像上面的示例一样,在触发器下面再包一层 type / script
  • type 会先做规范化(转小写、-_

event.data 也是真实支持的,但它会被合并进脚本上下文,而不是保留成一个独立的 &event.data 对象树。

10. Meta 节点 (meta / metas)

metas:
trace:
scripts:
build:
type: fluxon
script: |
return item

meta:
durability:
synchronous: true
remains: "example:remainder"
cooldown:
ticks: 80
by-player: true
unique:
enabled: true
bind-player: true
async-tick:
interval: 20
conditions:
worlds:
- world
permissions: "baikiruto.async.fire"
slots:
- mainhand

需要明确区分:

  • metas / meta-scripts:真正的 Meta 扩展入口
  • meta:内置效果快捷配置

详见 Meta 扩展

继承机制

Model 继承

models:
"example/base":
material: "NETHERITE_SWORD"
effects:
glow: true

"example/advanced":
from:
- "example/base"
effects:
item-model: "baikiruto:items/all_features_12111"

真实规则:

  • from 支持字符串和列表
  • 支持多继承
  • 子模型覆盖父模型同名字段
  • loader 会处理依赖顺序并检测循环引用

运行时合并顺序

在默认物品运行时数据里,源码会按以下顺序合并:

model defaults
-> display runtime
-> item display runtime
-> display lock metadata
-> item components
-> item data
-> item data-mapper
-> item effects
-> item meta effects
-> item i18n

这也是为什么 componentseffectsmeta 之间会出现覆盖关系。

锁定机制

数据路径锁定

data:
durability!!: 240
player.level!!: 10

源码会把这些路径记录到:

  • __locked_data_paths__

显示字段锁定

name!!: "&6Locked Name"
lore!!:
- "Locked line"
material!!: "DIAMOND"

显示锁定相关的真实运行时键包括:

  • __locked_display_fields__
  • __locked_display_values__
  • __locked_display_signature__

这套签名不仅用于重建时恢复锁定显示,也会参与更新检测。

ItemStream 数据流

物品在 toItemStack() 时的大致顺序如下:

ItemUniqueFeature.prepare
-> ItemDataMapperFeature.apply
-> ItemReleaseEvent
-> scripts.release
-> apply selected display
-> apply i18n display
-> ItemReleaseDisplayEvent
-> scripts.release_display
-> ItemDurabilityFeature.prepare
-> ItemCooldownFeature.injectDisplayData
-> runtime display render
-> PlaceholderAPI render
-> ItemStreamTransport.sync
-> VersionAdapterService.applyVersionEffects
-> ItemNativeFeature.apply
-> ItemReleaseFinalEvent

这也是为什么:

  • unique.* 会先生成
  • data-mapper 早于显示变量注入
  • native 是最后一轮 NBT 覆写

更新检测与 version-hash

version-hash: "m12111-example"

真实行为:

  • 写了 version-hash 时,直接用显式值
  • 不写时,源码会根据 item、model、display、template、runtimeData 等内容自动生成 SHA-1
  • 更新检查不仅比较版本哈希,还会比较锁定显示签名

因此即使 version-hash 不变,只要锁定显示签名变化,物品仍可能被判定为需要更新。

NBT 存储结构

baikiruto:
id: "example:all_features"
version: "m12111-example"
meta_history:
- trace
data:
durability: 240
unique.uuid: "..."
__locked_data_paths__:
- durability
__locked_display_fields__:
- name
__locked_display_values__:
name:
item_name: "Locked Name"
__locked_display_signature__: "..."

注意:

  • meta_history 记录的是真正应用过的 metas
  • 运行时数据整体存放在 baikiruto.data

完整示例

默认资源骨架

__group__:
id: "example"
path: "example"
priority: 100
icon: "example:all_features"

models:
"example/base":
material: "NETHERITE_SWORD"
display: "example/default"

displays:
"example/default":
name:
item_name: "&6Baikiruto Example Item"
lore:
item_type: "&7Target: Minecraft 26.1.1"

items:
"example:all_features":
icon: "NETHERITE_SWORD"
version-hash: "m12111-example"
model: "example/1_21_11"
display: "example/default"

默认资源里的真实组合

data:
category: "example"
tier: "legendary"
durability: 240

data-mapper:
durability_line:
type: fluxon
script: |
def current = &data["durability_current"] ?: &data["durability"] ?: 0
def max = &data["durability"] ?: 0
return current.toString() + "/" + max.toString()

effects:
glow: true
item-flags:
- HIDE_ENCHANTS
- HIDE_ATTRIBUTES

meta:
durability:
synchronous: true
remains: "example:remainder"
cooldown:
ticks: 80
by-player: true
unique:
enabled: true
bind-player: true

components:
custom_name: "&6Example All Features"
item_model: "baikiruto:items/all_features_12111"
custom_model_data: 1211101

display/def.yml 的默认显示模板

default_display_1:
name: "&7<item_name>"
lore:
- "&9<item_type>"
- "&f<item_description...>"

default_display_2:
name: "&7<item_name>"
lore:
- "&9<item_type>"
- "&f<item_description...>"
- ""
- "&a+<damage> Damage"

default_display_2 适合做“基础描述 + 额外属性尾行”这种展示风格;你也可以直接复制它改成自己的武器模板。

下一步