跳到主要内容

数据组件

本体往物品堆上挂的状态全部走原版数据组件(DataComponentType),没有"往物品上存一份模组自己的 NBT"这回事。全部 35 个登记在 registry.MxtDataComponents 一处,每一个都同时声明持久化 codec 与网络 codec(persistent(...).networkSynchronized(...)),所以它们都跟着存档走、也跟着同步给客户端——组件里没有"只服务端"或"只在本次会话有效"的类别。

组件是这一堆物品自己的事实:它被锻造过、它铭刻了哪条符、它装了多少灵气。与之相对的是数据包声明("这类物品通常怎样"),两者的合并方向写死在数据加载的「组件压过声明」一节。

一览​

下表的「载荷」是 codec 解出来的 Java 形状,不是 JSON 键名——字段级的 JSON 写法在各定义自己的页面里。一行里出现 Holder<X> 表示存的是注册表引用(跟着包走),Identifier 表示存的是裸 id(不校验存在)。

品质与元素​

组件 id载荷作用
mxt:qualityHolder<ItemQuality>全模组唯一一个装档位的组件,也是品质解析三层里的第一层。它装的是整份品质对象,所以它既定档位、也定这一堆读哪条链:写上去就是"这一堆是这个档"。/quality set、一次成功的升级、锻造台结算与画符铭刻写的都是它;/quality clear 摘掉它,这一堆退回携带的定义那一层。
mxt:elementList<Either<Holder<Element>, TagKey<Element>>>这一堆额外带的元素,与定义里写的取并集。可以写具体元素,也可以写元素标签。

锻造​

组件 id载荷作用
mxt:forging_resultForgingResultComponent(blueprint、final_value、actual_steps、optimal_steps、extra_steps)一次成功的锻造会话留下的记录:按哪份蓝图、最终值、实走步数与最短步数。构造器要求 actual_steps - optimal_steps == extra_steps。不含档位——会话定下的档写进 mxt:quality,所以 /quality clear 会把它一起清掉。
mxt:forging_methodsList<Holder<ForgingMethod>>这一堆当工具用时能执行的锻造手法。逐条容错(坏条目打日志后丢弃),与定义里的手法取并集。
mxt:forging_blueprintsList<Holder<ForgingBlueprint>>这一堆携带的锻造蓝图,与定义取并集;同样是逐条容错的列表。

丹药​

组件 id载荷作用
mxt:pillPillComponent(可选 pill、on_consume、toxicity_gain、toxicity_threshold、on_overdose、toxicity_after_overdose)这一堆丹药自己声明的身份与效果。组件里的 pill 指名一份丹药定义,优先于 pill_binding 匹配到的那份;五个效果键再按字段逐个盖上去。服用次数与冷却不在这里,它们只认匹配到的绑定。

功法​

组件 id载荷作用
mxt:techniqueHolder<Technique>这一堆教的是哪门功法。有它时不再按匹配器挑 technique_binding 声明,而是点名 technique 等于它的那一条。
mxt:technique_readingTechniqueReadingComponent(可选 learn_time、hold_animation、hold_sound)这一堆怎么被读,逐字段覆盖功法自己写的那三个字段。学哪门功法不在这里,那在 mxt:technique。
mxt:stored_textComponent(裸字符串=翻译键,对象=完整组件)玉简上写着的那段文字,读出来时整段打进聊天栏;不写就印一句"什么都没写"。
mxt:jade_slip_readingint(tick,0 及以上)玉简读多久:按住右键读满这么多 tick 才出内容。不写就是 40(两秒);写 0 与潜行右键一样是一点即读。

灵气与法器​

组件 id载荷作用
mxt:item_auradouble remain一件被消耗过的物品堆上剩余的灵气,一个数。
mxt:spirit_storageObject2DoubleMap<Holder<Aura>>物品堆的灵气存量,按灵气身份保存有限非负 double。存取和容量支持小数,展示保留两位;缺组件的含义由物品决定(灵石满、符箓空),空表表示已耗空。
mxt:artifact_stateArtifactStateComponent(可选 owner_uuid、owner_name、nourishment)一件法器的持有者与喂养度。身份是 UUID(所有归属问题都问它),名字只用于显示、由认领者写一次。它是哪件法器由物品定义回答,装了多少灵气在 mxt:spirit_storage,两件事都不在这里重复。
mxt:item_abilitiesItemAbilitiesComponent(abilities)装备或激活期间额外授予的技能 id 列表,与定义声明的并集。行为 mxt:add_ability 是它的专用生产者(已写过的一条不写第二遍、原有条目一律保留)。
mxt:storageDataStorageHolder技能运行期状态的宿主(冷却、充能、开关、计时、锁目标)。一对 (技能 id, 状态种类) 地址对应一格,同一种类的第二个值会替换而不是并列。值本身是可变的,由内容侧或物品宿主整份写入。

诅咒​

组件 id载荷作用
mxt:curse_containerCurseContainerComponent(curses,每条是一个 mxt:apply_curse 条目)这一堆物品携带的诅咒:装备时施加给持有者,摘下时移除它自己施加的那些。条目就是 mxt:apply_curse 行为本身,所以物品声明不了那个行为做不到的事,物品也从不直接改持有者状态。

契约与灵兽​

组件 id载荷作用
mxt:contract_scrollContractScrollComponent(可选 contract_type)一张可重复使用的契约卷轴指向哪份契约定义。
mxt:contract_bellContractBellComponent(beast、name、behaviors)御兽铃对准的那只灵兽与它能听的命令。指名放在工具上是因为两个铃可以点两只不同的兽;命令列表是选中那一刻从生物自己那里抄下来的快照,正因如此,主人的轮盘不必在客户端解析实体就能画出这一页。
mxt:spirit_beastSpiritBeastComponent(entity_type、entity、name、contract_type、owner、owner_name)灵兽袋里那一只生物:存档数据、重建它需要的实体类型,以及进去时的契约。类型存在数据旁边而不是里面,所以存档数据保持生物自己写的样子。名字、契约类型与主人是快照,因为画提示框的地方不能解码、不能查表。

阵法​

组件 id载荷作用
mxt:formation_plateFormationPlateComponent(allowed、可选 formation)一块便携阵盘允许跑哪些阵法,以及这一块跑的是哪座。允许列表每块一样,选中的那座必须是列表成员;列表为空表示不限制,除非服务端配置把它变成"什么都不许"。

秘境、令牌与鉴定​

组件 id载荷作用
mxt:secret_realm_token可选 realm、preset、duration_ticks、summoned、summoned_dimensionrealm 为秘境定义,preset 为裂隙预设;门的持续时间默认 0(永久),后两项由运行时记录复用的门 UUID 与维度。
mxt:reward_boxResourceKey<LootTable>奖励箱开哪张战利品表。存的是 ResourceKey 而不是 Holder:/reload 会换掉战利品表实例,握着旧的那份会一直滚重载之前的表。
mxt:tokenTokenComponent(可选 kind、value、owner)秘境令牌与交易令牌共用的身份与权限载荷。owner 是权限记录,故意不进提示框。
mxt:identificationIdentificationComponent(result)本体提供的未鉴定物品鉴定后变成哪件物品的已解析 id。

经济​

组件 id载荷作用
mxt:chequeChequeComponent(value、issuer)一张支票上记的价值,与任何具体的货币物品无关。

资源容器​

组件 id载荷作用
mxt:resource_containerResourceContainerComponent(values)这件物品这口容器里现在装着哪些资源、各多少。它是转运的容器而不是电池:装的是持有者自己那口池子里的东西,按着不放就倒回那口池子,小数也认。
mxt:resource_capacityResourceCapacityComponent(values)这口容器每种资源最多装多少,由发放容器的一方写。这里没有条目的资源就是一点也装不下——资源本身没有天然上限,数字必须写在某处。

符箓与符笔​

组件 id载荷作用
mxt:talismanTalismanComponent(talisman、mode)一张载体上已铭刻的那条符箓:单个 talisman 条目,缺省即一张空白载体;再刻一条会顶掉前一条。mode 是 fire(缺省)或 store,存在堆上而不是任何定义上,所以同一条铭刻在不同载体上可以有不同行为。它的提示框由 TalismanTooltipAppender 单独画,好让那些行落在载体的充能行上面。
mxt:brush_pigmentint(0 到上限)符笔自己的颜料存量,一个非负整数,1 单位就是 1 像素弧长。没写这个组件与写 0 是一回事。它不是消耗品条目:加料是原版储物袋那套点击,判定与换算只在 runtime.talisman.BrushPigmentService 一处。

灵植、丹炉与灵根​

组件 id载荷作用
mxt:herb_ageint(0 到上限)一株灵植果实的药龄。破坏成熟植株时,已生长的年数向下取整写进掉落的每一堆,同一刻再按它去查这株灵植自己的 quality_by_age 阶梯,命中的那一档写进 mxt:quality。它同时是药力公式的输入(变量 herb_age),而不是第二个乘数——想让老药更值钱,就在药力公式里读它。
mxt:alchemy_furnaceHolder<AlchemyFurnaceDefinition>这件丹炉核心是按哪份炉型规格造的。一类规格共用一件方块物品,物品本身说不清是哪一档,所以档也从这份引用读。
mxt:alchemy_wall_materialHolder<AlchemyWallMaterial>这块炉壁是哪种炉壁材料,即它的耐温等级。炉温上限取 18 块炉壁里的最低那个。
mxt:spirit_rootHolder<SpiritRoot>这件物品(通常是灵根石)携带哪条灵根定义。
mxt:physiqueHolder<Physique>这件物品(通常是体质石或卷轴)携带哪条体质定义。

裂缝​

组件 id载荷作用
mxt:rift可选 blueprint、recordedblueprint 为完整单门模板;recorded 为记录的目的地,放置时优先于蓝图目的地。物品对空气使用编辑参数,对方块使用重复放置;保存蓝图会清除 recorded 覆盖。

三种"谁说了算"​

看完上面那张表,组件与声明的关系可以收成三句:

  • 只有 mxt:quality 装档位。 别的组件都不带品质,mxt:forging_result 只记锻造记录。
  • mxt:pill / mxt:technique / mxt:technique_reading 参与"哪条声明适用"。 前两者能指名或挑出声明,后者再覆盖一层参数。这三条是数据加载里那张「组件压过声明」表的全部成员。
  • 其余全部只装状态。 它们不影响"适用哪条声明",只回答"这一堆现在是什么样"。

组件不是消耗品条目​

两个容易混的地方:

  • 符笔颜料不是 Cost。 "载体自己的存量"这套形状目前只有两个实例——符箓载体里灌的灵气(mxt:spirit_storage)与符笔的颜料(mxt:brush_pigment)——两者的付款者都是被使用的那件工具而不是玩家,硬做成 Cost 就得凭空造一个付款者。
  • 货币不是消耗。 支票上的价值与 currency 定义的汇率都是价格,永远不进 Cost。

写组件时的两个坑​

  • 列表里的空堆要用 ItemStack.OPTIONAL_CODEC。 组件是要落盘、要同步的,列表里出现一个空堆会让整个包编码失败。本模组用空堆占位的列表一律走那个 codec。
  • mxt:rift.blueprint 的格式见 rift;recorded 使用相同的 destination 格式。

相关阅读​

  • 数据加载:组件的持久化与网络 codec 在哪里登记、组件与声明的合并顺序、品质解析的三层。
  • 附件:同一个"状态放哪"问题的另一侧——挂在实体、区块与世界上的那些。
  • Java API:QualityService 等读组件的服务入口。
  • 内置物品:哪些本体物品带哪些组件,以及可以直接抄的 give 例子。