Kzeroko KTM2

商人交易覆盖

职业目录、报价选取、物品堆叠与严格重载校验。

更新于 2026/9/30 10 分钟阅读

交易覆盖接管一个商人职业的完整目录。初次来访时,就会从所有货品层级选出库存。村民与NPC共用这套定义;每位玩家的生意交情单独决定照拂服务。

文件放在哪里

使用data/<namespace>/trade_overrides/<path>.json,每个文件对应一个职业。不同资源ID指向同一职业时,isekaiexpansion命名空间优先于其他所有命名空间,然后比较较高的priority,最后取资源ID字符串字典序较大的定义。整个定义一起选中,不逐级合并。替换内置内容时,覆盖其准确资源路径,或在isekaiexpansion下使用合适优先级的资源。

内置文件按vanilla/、compat/<provider>_<profession>.json、npc/unique/和npc/common/组织。NPC预设通过trade_profession选目录。伊芙琳娜等唯一角色使用isekaiexpansion:mahoutsukai_evelina这类专属键;普通NPC也能使用minecraft:farmer等已有目录。普通NPC可用实体的TradeProfession覆盖预设职业,并随存档保存;唯一NPC始终使用预设绑定。

最小示例

以下完整目录沿用内置农民文件的物品堆叠格式,使用Numismatic货币:

{
  "schema_version": 3,
  "profession": "minecraft:farmer",
  "tiers": {
    "1": [
      {
        "id": "bread",
        "costs": [
          {
            "money": 48
          }
        ],
        "result": {
          "item": "minecraft:bread"
        }
      }
    ]
  }
}

字段

根字段

字段类型默认值作用
schema_versioninteger必填必须为3;其他值会拒绝本次目录更新。
professionidentifier必填目录键,可对应已注册村民职业或自定义NPC职业。可选来源模组须通过requires_mods明确限制。
priorityinteger0命名空间权重相同时数值高者优先,范围−1000000…1000000。
requires_modsarray<string>[]列出的模组必须全部加载;空列表不限制。
excludes_modsarray<string>[]任一列出的模组已加载就禁用该定义;空列表不排除模组。
selectionobject{"mode":"all"}缺失或为null时选取全部合格报价,见选取字段。
selection.modeenum(all, weighted)对象内必填all选取全部候选;weighted先加入保底报价,再按权重无放回抽取。
selection.countintegerweighted时必填每个货品层级1–64条报价,all模式禁止此字段。
tiersobject必填至少包含一个1–5的货品层级键。每个值是最多1024条的报价数组,可以为空。
courtesiesarray<object>[]最多3项职业照拂,见照拂字段;显式null会被拒绝。

报价字段

字段类型默认值作用
idstring必填在文件所有货品层级中唯一,符合[a-z0-9][a-z0-9_.-]*。
costsarray<object>必填1–2个堆叠,最多一个货币堆叠;货币会排在第一支付槽。
resultobject必填输出堆叠,格式与支付堆叠相同。
weightinteger1加权抽取权重,1–100000。
guaranteedbooleanfalse合格时先于随机候选加入;每个货品层级保底条目不能超过加权数量。
max_usesinteger12补货前可用次数,1–1000000。
price_multipliernumber0.0有限数值0–100;存在货币支付时,生成报价的倍率强制为零。
demandinteger0初始需求,−1000000…1000000;存在货币支付时初始需求强制为零。
conditionsobject{}缺失或为null时不限制;在生成报价时检查。

堆叠字段

字段类型默认值作用
moneyinteger货币堆叠必填1–9223372036854775807铜币单位,货币堆叠只能有这一个键。
itemitem id物品堆叠必填一个ID或非空且无重复的ID数组。从已注册候选中等概率选取,缺失候选被过滤。
countinteger1固定数量或含端点的[minimum, maximum],范围1–64,上限不得小于下限。随机数量不按物品自身堆叠上限截断。
nbtobjectnull复合JSON或SNBT字符串,按复合标签解析。先于其他堆叠选项应用;语法错误会拒绝更新。
custom_namestringnull非空白的字面名称,不是翻译键;显式null非法。
damageinteger00–2147483647。只对有耐久的物品应用,截断到物品最大损伤值。
potionidentifiernull药水ID;生成堆叠时忽略未注册药水,显式null非法。
enchantmentsarray<object>[]缺失或为null时无附魔。找不到注册项的附魔跳过,不检查物品与附魔兼容性。
enchantments[].ididentifier必填格式合法的附魔ID。
enchantments[].levelinteger必填1–255,不按附魔通常的最高等级截断。

条件字段

字段类型默认值作用
conditions.requires_modsarray<string>[]列出的模组必须全部加载。
conditions.excludes_modsarray<string>[]列出的模组均不能加载。
conditions.villager_typesarray<identifier>缺失:不限制一个ID或非空且无重复的ID数组。匹配村民类型,显式空数组会被拒绝。
conditions.dimensionsarray<identifier>缺失:不限制一个ID或非空且无重复的ID数组。匹配世界ID,显式空数组会被拒绝。

照拂字段

字段类型默认值作用
courtesies[].idstring必填照拂内唯一,语法与报价ID相同。
courtesies[].labelstring必填非空白翻译键,需要提供双语文本。
courtesies[].rankinteger必填可选2、3、5,每个交情阶段最多一项;重复会拒绝。
courtesies[].actionobject必填已注册的动作数据;缺失或无效会拒绝目录。
courtesies[].action.typeidentifier必填带命名空间的已注册类型;未知ID拒绝加载。
courtesies[].action.itemobjectisekaiexpansion:gift单一固定物品堆叠,数量1–16,不可使用货币;其余字段见上方物品格式。
courtesies[].action.item_tagidentifierisekaiexpansion:repair不带#的标签;受损的主手物品须匹配。
courtesies[].action.percentintegerisekaiexpansion:repair最大耐久的1–10%,向下取整,至少1点。
courtesies[].action.capintegerisekaiexpansion:repair1–100耐久点,最终不超过已有损伤。
courtesies[].action.hungerintegerisekaiexpansion:meal1–8饥饿点,饱和度因子为0.25;饥饿值未满时可用。
courtesies[].action.effectidentifierisekaiexpansion:cleanse, isekaiexpansion:effect已注册的状态效果。前者解除已有的非增益效果;后者仅在同类效果不存在时,以强度0赋予非瞬时增益。
courtesies[].action.secondsintegerisekaiexpansion:effect1–120秒,按每秒20 ticks换算。

内置类型拒绝其他动作的字段;扩展类型自行验证数据。赠品检查行囊空间,保养仅改变损伤。执行前重新核对对话、定义、阶段、可用次数与选择时的主手快照,成功后才消费次数。唯一NPC拒绝此菜单,内置数据也没有照拂。格式3不保留版本2或旧式平铺动作的读取方式。

完整示例

这里按权重选取1条报价,物品候选与数量范围也会在生成时确定:

{
  "schema_version": 3,
  "profession": "minecraft:farmer",
  "tiers": {
    "1": [
      {
        "id": "bread",
        "costs": [
          {
            "money": 48
          }
        ],
        "result": {
          "item": [
            "minecraft:bread",
            "minecraft:carrot"
          ],
          "count": [
            1,
            3
          ]
        },
        "weight": 5
      }
    ]
  },
  "priority": 10,
  "selection": {
    "mode": "weighted",
    "count": 1
  }
}

校验

只接受格式版本3;已移除的等级字段和村民经验字段会被拒绝。所有层级都拒绝未知字段。缺失必填字段、类型错误、重复报价ID、非法ID语法、超范围数值和非法NBT都会记录错误,并保留上一版目录,不应用本轮已解析的定义。空文件不是合法JSON,空对象缺少必填字段。tiers本身不能空,但货品层级对应的数组可以空。

整数必须是精确整数,数字字符串和小数不能充当整数。模组列表不允许空白值或重复值。自定义职业ID可直接使用;物品候选全部不可用时,对应报价被过滤。过滤后即使没有报价,这个定义仍然接管该职业,不回退原版交易。

货币堆叠需要numismatic-overhaul及铜、银、金币和钱袋物品均可用。银币值为100,金币值为10000,计价单位为铜币。货币支付排在首槽,初始需求与价格倍率强制归零。这里的数值来自异界扩展的货币适配逻辑。

换金宝物只用于独立的换金服务。支付或产物包含已注册的换金宝物,或带有LuxuryVal NBT时,该报价不可用;物品数组中的候选及NPC目录同样受此规则约束。创建报价与REI预览使用相同限制。目录生成器从物品注册定义读取宝物ID,校验器会拒绝任一方向中的此类条目。

重载

在服务端启动和/reload时重新读取。成功应用会增加目录版本;商人在定义、版本或库存轮换变化后的下次访问时重建。抽取种子由商人UUID、职业、货品层级、报价ID和已保存的轮换值决定,不是在每次打开交易界面时重新随机。

初次生成就包含1–5所有货品层级的报价。重建按支付与输出堆叠的物品、数量、NBT匹配旧报价,保留使用次数(不超过新的上限)、需求和特殊价格,并转移已有货币声望数据。职业/报价ID记录还会保留轮换中已用掉的库存,直到真正补货;请保持ID稳定。客户端交易界面接收实际报价,不在本地抽取。

村民补货时获得一次换货机会,最多保留一次。NPC在下一个实际流逝的服务端日补货,也获得一次换货机会;初次来访不赠送机会。在对话服务中使用后会轮换当前货物。加权目录保留必选条目,并优先选择上一批未出现的非必选ID;候选不足时才用重复条目补足。上一批ID和轮换种子随实体保存。all目录仍包含所有符合条件的条目。议价和筛选见交易。

REI预览读取内置目录,不读取服务端重载后的覆盖表。它按模组条件展示可用候选,数量范围使用最小值;预览不代表某个村民的加权选取、类型或维度。数据包修改应通过实际村民交易验证。

内置目录生成器与校验器排除Donner、Schlag、悬赏契约与悬赏板,也排除开发工具、测试物品、内部图标和世界制作所用的锚点或结构方块。这些物品不得成为商店货品;校验覆盖每个候选物品,也包括NPC目录。

相关页面

交易价格还可能受声望影响。