核心概念与架构
读懂这一页,后面所有章节都会变简单。这里把 QI 的核心名词和数据流讲清楚。完整术语速查见 术语表。
一件物品的三层数据模型
┌─────────────────────────────────────┐
YAML 设计图 │ Definition(模板) │ 所有同 ID 物品共享
│ id / type / material / lore / │ 存在内存注册表
│ providers / variables / options … │
└─────────────────────────────────────┘
+
┌─────────────────────────────────────┐
这一件的状态 │ Instance(实例数据) │ 写在这件 ItemStack 的 NBT
│ values(滚出的随机值)/ overrides / │ 每件不同
│ locks / seed / soulboundOwner … │
└─────────────────────────────────────┘
+
┌─────────────────────────────────────┐
创建后的补丁 │ Layers(层) │ 打孔/镶嵌/强化/词缀
│ base → variables → section → affix → │ 有 owner 域 + 优先级
│ external(按 order 叠加) │
└─────────────────────────────────────┘
↓ 装配管线 Assembly
最终 ItemStack(玩家手里那件)- Definition(模板):YAML 编译后的不可变设计图,由
QinhItemRegistry按 ID 管理。详见 物品定义。 - Instance(实例数据):写在单个 ItemStack NBT 里的可变状态。键名
qinhitems:instance,内容是一段 YAML。详见 层与装配。 - Layers(层):创建后追加的补丁包(
QinhLayerPatchPack),按QinhItemLayerType的 order 叠加:base(10) → variables(20) → section(35) → affix(36) → external(100)。受 写域策略(WriteDomainPolicy) 保护,防止越权改动。
装配管线(Assembly Pipeline)
把上面三层合成出 ItemStack 的过程叫装配,由 QinhItemAssemblyService 驱动,依次跑一串层贡献者(Layer Contributor):
| 顺序 | 贡献者 | 干什么 |
|---|---|---|
| 10 | BaseLayerContributor | 用 material 造出基础 ItemStack,套基础 meta |
| 20 | VariablesLayerContributor | 解析所有变量(模板 + 实例 + 层),渲染进 Lore / 名称,处理锁 |
| 35 | SectionLayerContributor | 注入段(Section)—— 前后缀池、词缀池 |
| 36 | AffixLayerContributor | 注入词缀(Affix) |
| 100 | External(插件注册) | 第三方扩展 |
两个入口:
build(...)— 全新生成:分配新种子、滚随机值、跑全部贡献者。rebuild(item)— 重建:保留已有种子 / 实例,重新渲染(配置改了之后刷新用)。
开发者 API 见 层与装配。
Provider(数据提供者)
Provider 是挂在物品上的「外部系统载荷」。它是一段不透明的 key→value 数据,键名是外部系统 ID(如 ap、perm_effects、legendinlay、magicgem)。
providers:
ap: # AttributePlus 的属性载荷
value: '{"attack_damage":18}'
legendinlay: # Legendinlay 宝石孔载荷
value: '{"set":"...","sockets":["normal"]}'QI 自己不解读 provider 内容,只负责存储、传递。解读交给对应的 Bridge(桥)。详见 Provider 与桥。
ICVM 与属性映射
ICVM 是 QI 内部对核心战斗属性的「标准词汇表」(Internal Canonical Vocabulary)。它把内部键(如 attack_damage)映射到 AttributePlus 里你实际起的名字(如 物理伤害)。映射在 config.yml 的 attribute-mapping 段配置。
内部键 attack_damage ──(attribute-mapping)──► AP 显示名 "物理伤害"为什么要这层映射?因为 QI 想保持配置可移植,而每个服在 AP 里给属性起的名字可能不同。详见 属性与数值。
变量(Variable)
变量是物品级的动态值,用于随机数值、品质词、星级等,并能用 {变量名} 占位符插进 Lore / 名称。
variables:
damage_roll: "15 - 25" # 范围 → 每件随机滚一个值
tier_name: "传说" # 静态字符串
lore:
- "伤害:{damage_roll}" # 渲染时替换成滚出的值变量经过「滚(Roll)→ 解析(Resolve)→ 渲染(Render)→ 冲突解析(Conflict)」四阶段管线,多源(模板 / 实例 / 层 / 运行时覆盖)按优先级合并并可溯源。详见 变量。
动作(Action)= 触发器(Trigger) + 处理器(Handler)
物品的「技能 / 主动效果」由动作系统实现:
玩家做某事(左键)→ 触发器原子 left_click 命中
→ 检查 条件 conditions(全过才继续)
→ 检查 冷却 cooldown
→ 检查 消耗 consume(够才继续)
→ 按顺序执行 refs 里每个 处理器 handler(传 payload)
→ 任一处理器 HANDLED → 扣消耗、记冷却- 触发器(Trigger):100+ 内置原子(点击、潜行、移动、战斗、容器、实体交互…)+ 序列连招。详见 触发器。
- 处理器(Handler):内置 10 个(
qi:message/qi:sound/qi:title/qi:command/qi:give_item…)+ 生态注册(qinhskills:cast/combat:swing)。详见 处理器。
⚠️ YAML 里不能写逻辑分支(if/else/switch)—— 这是刻意的设计边界。复杂逻辑请开发动作处理器。
类型与能力矩阵
每个物品类型(weapon / armor / ring / gem…)声明自己支持哪些能力(TypeCapability):
SKILL(技能) · ATTRIBUTE(属性) · GEM_SOCKET(宝石孔)
SET(套装) · RENDER(渲染) · CONSUMABLE(可消耗) · PROJECTILE(投射物)例如 weapon 支持 SKILL/ATTRIBUTE/GEM_SOCKET/RENDER,而 currency(货币)只支持 RENDER。能力矩阵决定了某类型能不能打孔、能不能加属性。详见 物品类型。
配置文件全景
| 文件 | 管什么 | 章节 |
|---|---|---|
config.yml | 主配置(combat / soulbound / write-domains / attribute-mapping / gem…) | 配置文件 |
item_types.yml | 物品类型与能力 | 物品类型 |
item_tiers.yml | 品质 / Tier | 品质与显示 |
enchant_limits.yml | 附魔上限 | 附魔上限 |
items/*.yml | 物品定义 | 物品定义 |
fragments/*.yml | 碎片(可复用片段) | 碎片与模板 |
sections/*.yml | 段 / 词缀 / 池 | 段 / 词缀 |
sets/*.yml | 套装 | 套装 |
integrations/*.yml | 宝石孔类型、桥接、模型目录 | 宝石孔 / 集成 |
数据流总览图
🖼️ [图片占位] 端到端数据流图:YAML → TemplateCompiler → Definition → AssemblyService(层贡献者)→ ItemStack → 装备 → EquipmentScanner → AttributePlus · 建议
assets/dataflow-overview.png
理解了这些,就可以挑你的角色深入了: