Kzeroko KTM2

蓝图研究与铁匠委托

物品研究状态、服务端誊录校验、托管存档与村民实际劳动。

更新于 2026/9/19 12 分钟阅读

研究进度使用物品 NBT,铁匠委托使用全服托管账本。item.blueprint 下的研究代码与 internal.blacksmith 下的委托代码属于实现层;公开的村民集成门面是 api.blacksmith.BlacksmithAPI。

它做什么

ResearchDataLoader 先载入知识,再载入蓝图,跳过无效文件并以成功定义替换目录。蓝图数据负责 JSON 约定,研究与委托负责玩家操作说明。

BlueprintResearchService 在服务端校验发现与誊录,不创建玩家或队伍知识账本。BlacksmithService 将已揭示图纸、配方产物和条款快照存入委托;接受后的订单不再从目录重新读取这些条款。

运行时模型

物品状态

物品根标签 IsekaiBlueprint 必须是 NBT compound。以下字段由 BlueprintResearchState 写入,属于存档约定,并非另一套数据包格式。

字段类型默认值作用
Schemaint1绑定时写入;当前读取不校验或迁移该版本。
Definitionstring绑定必需蓝图 ID;无法解析到定义时仍保留绑定状态。
NameKeystring来自定义揭示后的名称翻译键。
DescriptionKeystring来自定义揭示后的描述翻译键。
UnknownNameKeystring来自定义未鉴明名称翻译键。
UnknownDescriptionKeystring来自定义未鉴明描述翻译键。
Recipestring来自定义缓存配方 ID;仅 Revealed 为真时返回。
Typestring来自定义大写显示枚举;已存值无效时回退 UNKNOWN。
Complexityint来自定义从定义复制的显示复杂度。
Decorint来自定义从定义复制的装饰索引。
Revealedboolean绑定时为 false绑定时为假;规范化时按当前全部要求重算。
Knowledgecompound绑定时为空按 ID 存储整数进度;挂接时若缺失或类型不符则新建。
Knowledge.<id>int0读取为非负值;规范化按当前要求限制上限,未使用键保留。

绑定会替换整个研究 compound。规范化时,定义不匹配则重新绑定,随后更新元数据、按当前要求限制各项进度并重算揭示状态;空要求列表直接完成。无关知识键保留。已有 compound 不会在每次规范化时重写 Schema,旧 BlueprintRecipeId 标签在此没有迁移路径。

revealedRecipe 使用保存的 Revealed 标志与 Recipe 缓存,不单独查询当前定义。打开研究界面和委托报价前会规范化;锻造台的配方访问方法本身不会执行这一步。

快照与客户端界面

ResearchSystem.init() 只注册一次重载监听。数据包内容同步与成功重载会发送 BlueprintCatalogPacket;服务端停止时清空知识和蓝图注册表。目录包含创造模式变体所需的显示数据,不包含可变研究进度。

BlueprintScreenPacket 提供要求、当前证据、配方步骤及产物快照。未揭示图纸同样收到配方信息,因此界面的揭示状态不能作为保密边界。上限为 2048 个目录条目、32 项要求、32 个步骤及每步 64 项材料;翻译键限 256 字符,学科限 64 字符。JSON 加载器不执行这些解码上限。

两个接收处理器都调度到 Minecraft 客户端执行器。ResearchScreenController 在 ModernUI 线程更新当前同 ID 蓝图,避免重新打开;不同蓝图则创建界面并播放打开音效。字体顺序为 ArchitectsDaughter、ZhiMangXing、ModernUI 当前选择的后备字体族。自定义字体缺失或损坏时记录日志,其余字体链仍可使用。

委托持久化

ForgeOrderStorage 使用主世界保存的 blacksmith/commissions_v1 键,路径为 data/isekaiexpansion/blacksmith/commissions_v1.dat。持有人与铁匠 UUID 索引各只允许一份活动订单。蓝图与产物均复制 ItemStack,避免共享可变实例。

字段类型默认值作用
Orderslist<compound>空列表根列表:有效订单后附保留的不可读条目。
Orders[].IdUUID必需订单身份,用于拒绝过期回调。
Orders[].OwnerUUID必需全服持有人索引;重复持有人使该条目加载失败。
Orders[].SmithUUID必需负责村民索引;重复铁匠使该条目加载失败。
Orders[].Dimensionstring必需指定工坊的世界 ID。
Orders[].Stationlong缺失时为 0指定工作站的压缩 BlockPos。
Orders[].SmithPositionlong必需,且必须为 long 类型铁匠最后已知位置,用于加载租约。
Orders[].Blueprintcompound必需,物品不得为空托管蓝图的 ItemStack NBT 快照。
Orders[].Outputcompound必需,物品不得为空报价产物的 ItemStack NBT 快照。
Orders[].Costlong必需,必须为正接受时的铜币价格;取消不退费。
Orders[].RequiredTicksint必需2–30 个完整每日额度;必须整除 DailyLimit。
Orders[].DailyLimitint必需每日 2000–6000 个工作刻。
Orders[].Workedint0已完成劳动,范围 0 至 RequiredTicks。
Orders[].Daylong0最后工作日或初始接单日,按 24000 刻向下取整。
Orders[].DailyWorkedint0范围 0 至 DailyLimit,且不超过 Worked。

UUID 使用 Minecraft 的 UUID NBT 表示。其他缺失数字字段先按 NBT getter 读取为零,再经过构造校验。无效 ID、托管物品、劳动范围或重复索引会使该条目失败。原始 compound 会记录日志并保存在 unreadableOrders,再次保存时附在有效订单之后;不会自动修复,也不能直接领取。

添加、移除、转交、记录铁匠位置变化或推进劳动都会标记存储为 dirty。转交仅改变铁匠、维度与工作站,不替换报价快照,也不重置当天进度。

劳动与远程工坊

ForgeWorkProgress 在 2000 <= timeOfDay % 24000 < 9000 且未用完每日额度时接受劳动。work 对同一服务端刻最多增加一次。进入后续日历日后,在下一次实际劳动时重置 DailyWorked;日期倒退则等待至保存的工作日。离线时间与跳过的天数不产生劳动。

BlacksmithWorkTask 要求村民职业合适、存活、清醒、启用 AI、未交谈或受威胁,且认领工作站匹配。工作期间独占脑活动 BLACKSMITH_WORK。到站条件为距中心的平方距离不超过 4、垂直差不超过 1,且射线无遮挡或命中工作站。否则以速度 0.5、完成距离 1 导航,每 40 刻(2 秒)刷新行走请求。工作特效同样每 40 刻触发;完成后标记可领取,并通知在线持有人。

调度参数数值
远程工坊租约最多 8 个;不限制已加载工匠的总数。
检查间隔END_SERVER_TICK 阶段,每 20 刻(1 秒)。
初次加载宽限100 刻(5 秒)。
无进展超时1200 刻(60 秒)。
失败后重试间隔1200 刻(60 秒)。
区块票据半径参数2;中心分别为工作站与铁匠最后已知区块。
票据过期时间100 刻(5 秒);持有租约时持续刷新。

租约刷新维度空闲计时,并随铁匠记录位置更新。这些是带周边加载影响的区块中心,并不表示只加载 2 个区块。完成、分配失效或非工作时段会释放租约;加载失败或停滞则释放并延后重试。转交、领取、取消会清除该订单的租约与重试状态。服务端停止时关闭所有租约。存储订单的遍历不保证公平排队。

约定

服务端研究校验

发现检查另一只手;誊录按来源顺序、再按槽位顺序搜索主物品栏。创造模式只免除消耗,不免除匹配。誊录在修改前检查当前手、蓝图物品、定义 ID、所请求知识是否属于要求、完成状态及证据。包中没有唯一物品令牌:同手替换为另一张相同定义蓝图后,操作可能作用于新图纸。完成后的重复请求不再消耗。

先消耗证据,再加入经过上限限制的洞见。成功修改后标记背包 dirty、发送容器内容更新,再发送新快照。锻造台只读审阅将台内物品传入快照构建;誊录仍解析玩家当前手持物品,无法任意指定锻造台内的物品。

研究与委托修改应在服务端线程执行。这些辅助代码不加锁,也不替任意异步调用者切换线程。TranscribeBlueprintKnowledgePacket.handle 经 IsekaiCore 包框架直接调用服务;此处理器本身没有额外执行器调度。

事务边界

接受委托会检查交互条件、两个唯一索引、已认领且可达的工作站与重新生成的报价。ItemStack 相等及条款相等检查用于拒绝变化的蓝图、产物或价格。先检查货币联动并付款,再清空玩家槽位、添加托管。除 isLoaded/tryPay 调用外,Numismatic 付款细节由 IsekaiCore 负责,此处不实现钱包。

领取时校验持有人、订单 ID、指定铁匠与完成状态,随后同时模拟两件物品的背包容量,再移除订单并插入副本。取消要求尚未完成且能放回蓝图,可通过另一位合适铁匠处理,绝不退款。转交要求目标空闲且工作站可达,保留全部原条款。这些是同步服务操作,不是带崩溃事务日志的分布式支付协议。

Blabber 回调重新解析当前村民,并检查捕获的铁匠或订单 ID。菜单 ID 为 isekaiexpansion:blacksmith/villager,普通交易仍保留为菜单选项。村民对话处理器另外按负面流言限制入口;仅职业符合并不表示事务一定可执行。

扩展方式

通过 net.kzeroko.isekaiexpansion.api.blacksmith.BlacksmithAPI 接入村民:

方法侧别约定
init()通用初始化注册调度器与对话;只调用一次,门面没有幂等保护。
eligible(VillagerEntity)实体上下文只检查成年铁匠职业,不检查交互条件或订单。
dialogue()通用返回菜单 Identifier。
registerBrainActivity(Brain<VillagerEntity>)服务端脑初始化注册独占工作活动。
createWorkTask()服务端脑初始化返回新的工作任务。

现有村民 mixin 在核心优先级 10 安装工作任务,并在脑初始化后注册活动。其他调用者不要重复安装任务。接单、取消与结算仍是内部服务操作。

api.research.KnowledgeLedger 是已有的公开 NBT 工具,并非研究门面。以下用于独立的服务端所属 compound:

static int recordInsight(NbtCompound owner, Identifier knowledge) {
    var ledger = KnowledgeLedger.attach(owner, "Knowledge");
    return ledger.add(knowledge, 4, 24);
}

attach 会将缺失或类型不符的存储改为 compound。get 与 set 将值限制为不小于 0;add 按给定非负上限限制结果并返回实际差值。entries 返回清理后的不可变副本,忽略无效 ID 键;copyNbt 返回独立 compound。调用者负责 dirty 标记与同步。实际蓝图应使用研究服务或状态路径,以重算揭示状态。

验证

  • 在生存与创造模式发现、誊录,检查参照物所在手、单栈不足、证据优先级、副手排除和最后一次洞见的完整消耗。
  • 将研究物品放入箱子、交易或丢出,并存档重进。修改定义、移除知识、新增要求或放入错误文件,确认规范化及成功目录替换行为。
  • 在誊录请求到达前切换为另一种定义,再测试相同定义的替代物品。完成后的重复请求不得继续消耗。
  • 确认未揭示图纸无法绑定锻造台;已揭示图纸可绑定、开始前取回、推进步骤后在材料槽为空时审阅,并优先领取成品。
  • 检查两种语言、宽窄画面与界面缩放,验证字体回退、滚动边界、羽毛笔与揭示过渡,以及快照更新不重复播放打开音效。
  • 测试余额不足、报价过期、背包已满、重复持有人或铁匠,以及缺失或受阻工作站。同时领取两件物品,确认取消不退款、跨维度转交不重置劳动。
  • 保存并重启订单,移动或移除铁匠、卸载区域、耗尽租约预算,验证释放与重试时机。跳时或倒退日期不得补发劳动。在一次性测试存档损坏订单,确认原始托管数据仍保留。

相关页面

蓝图数据、蓝图研究与铁匠委托。