[MD]
### 动作写法迁移
- **动作写法整体换新, 但大部分不需要你动手改。** 首次启动时 CoreLib 会自动把 `plugins/` 下所有 Emaki 插件的配置文件改写成新写法, 只做一次, 之后不再重复。每个被改过的文件旁边都会留一份 `.legacy-backup` 后缀的原文件备份。万一某一行转换不成功, 插件不会拿这行去覆盖你的配置, 而是单独写到一个 `.v2-failed` 文件里、原配置保持不动, 控制台也会列出是哪个文件的哪一行, 方便你自己看一眼。
- **锻造的三个刷新动作要你手工改名字**, 自动改写不包括它们。去掉开头的 `emaki`:
- `emakiforge_refresh_held` → `forge_refresh_held`
- `emakiforge_refresh_player` → `forge_refresh_player`
- `emakiforge_refresh_all` → `forge_refresh_all`
- 旧名字不再保留, 升级后还写旧名字的话, 控制台会提示找不到这个动作。
- **锻造自己的变量占位符要加 `var.` 前缀。** 配方和 config.yml 里凡是用到锻造变量的地方都要改, 例如 `%forge_result_item_name%` → `%var.forge_result_item_name%`、`%forge_failure_reason%` → `%var.forge_failure_reason%`。品质广播里那个老写法 `<show_item>` 也换成了 `%var.forge_show_item%`, 新的 config.yml 已经是新写法了。GUI 文案和 `%player%` 这类玩家占位符不在改动范围内, 不用管。
- 动作名本身的下划线分词由插件自动改写, 比如 `sendmessage` → `send_message`、`playsound` → `play_sound`、`broadcastmessage` → `broadcast_message`, 随包的 `recipes/example_recipe.yml` 已经是改好的样子, 可以对照看。
- **原先用 JS 脚本改成功率或发奖励的配方需要重写。** JS 脚本功能整体取消了, 也没有自动转换的办法。原先脚本能做的两件事现在都有配置层的做法: 改成功率用配方里的 `success_rate` 和 `failure_outcomes`, 锻造前后发奖励用配方 `actions` 段下的 `pre`/`success`/`failure` 以及 `result.success.actions`。随包的示例脚本 `scripts/examples/forge_success.js` 一并删除。
### 锻造界面与材料清单
- **锻造容量那一格现在会列出这个配方要哪些材料、你放了多少。** 新增占位符 `%blueprint_requirements%`, 写在 `gui/forge_gui.yml` 的 `capacity_display` 槽位 lore 里, 一项材料占一行, 凑够的打勾、没凑够的打叉, 后面跟着「已放入的量/需要的量」。注意这个数量看的是你已经放进锻造界面的量, 不是背包里的量。
- 清单挂在容量那一格而不是图纸格, 是因为图纸格放上图纸以后, 占位物品就被真图纸替换掉了, 清单反而会被藏起来。
- **一张图纸被多个配方共用时, 清单会按配方分组列出**, 每组前面带配方名, 最多展开 3 组, 剩下的折叠成一行「还有 N 个配方」。这里刻意不做合并: 甲配方要铁、乙配方要金, 合起来会显示两样都缺, 而实际上凑齐任意一个就能锻造。同一格还能用 `%recipe_count%` 拿到候选配方的个数。
- 还没放图纸、或者放的图纸对不上任何配方时, 这一行显示「配方会按图纸物品源自动匹配」。
- 上面这些提示语都能改, 文案在语言文件的 `gui.blueprint.*` 下面: `no_recipe`、`recipe_group_header`、`requirement_satisfied`、`requirement_missing`、`more_recipes`。
- **顺带一说, lore 里整行只写一个占位符时, 值有几条就展开成几行。** 这是清单能一行一项显示的前提, 所以 `%blueprint_requirements%` 要单独占一行, 别和别的文字挤在同一行。
### 配方与界面模板
- **配方可以指定自己的锻造界面模板了。** 在配方里加一个 `gui_template` 键, 填 `gui/` 目录下模板的文件名 (不带 `.yml`), 这个配方开出来的界面就用指定的那份。不填就还是用 `forge_gui`, 沿用旧配方文件不受影响。
### 控制台输出
- **配方里动作写错时, 控制台报错从内部代号变成了看得懂的话。** 原先某一行动作插件读不下去时, 控制台只会甩出一个内部代号, 根本看不出是哪里写错了。现在会直接说明问题是什么、出在哪个位置、以及可能想写的是什么, 后面照旧跟着出问题的文件、配方 id 和动作所在的阶段与行号。这些文案跟着语言文件走, 换语言也能用。
- **配置预检的问题行现在按严重程度整行上色**, 错误和致命是整行红色, 警告是整行黄色, 提示保持原来的灰色。新增 `console.config_precheck_issue_warn` 和 `console.config_precheck_issue_error` 两个文案键, 旧语言文件缺这两个键时会退回原来的样式, 不会打印出裸的键名。
- 启动和重载时的六条控制台日志由白色改成灰色, 和其他 Emaki 插件的输出保持一致。
### 开发者相关
- `EmakiForgeApiProvider` 已移除, 直接使用 `EmakiForgeApi` 的静态方法。
- `EmakiForgeApi.available()`、`apiVersion()`、`pluginName()`、`isReady()` 全部移除, 由 `EmakiForgeApi.status()` 统一替代 (返回 `ApiStatus`)。
- 新增三层公开 API: `EmakiForgeApi.catalog()` (配方与材料只读查询, 含 `matchRecipe`、`validate`、`previewResult`、`mastery`、`accepting`)、`EmakiForgeApi.operations()` (`forgeAsync`、`openForgeGui`、`openRecipeBook`、`viewingRecipeBook`、`refreshItem`、`refreshPlayer`)、`EmakiForgeApi.extensions()` (预留层, 当前无成员)。插件未加载时返回降级实现, 不再抛异常。
- 返回值统一为 `EmakiResult`: 「插件不可用」与「业务失败」分开表达, 配 `FailureKind` 区分子系统被关闭与插件未安装。
- 新增模型类型 `ForgeInputs`、`ForgeOutcome`、`ForgeRecipeView`、`ForgeMaterialView`、`ForgeBlueprintView`、`ForgeValidation`。
- `ForgeStartEvent`、`ForgeCompletedEvent` 补齐线程语义说明: 均为同步事件, 仅在运行时持有对应区域所有权时触发, 监听器需遵守相同的 Paper/Folia 线程约束。
- `EmakiForgeApi.Bridge` 与 `ForgeExtensions` 标记为 `@ApiStatus.NonExtendable`, 第三方插件不得实现。
- **这是破坏性 API 更新, 第三方代码需要重写, 不提供旧签名或过渡兼容。**
### 升级说明
- 需要先把 EmakiCoreLib 升到 `4.7.0`。
- **升级前请备份 `plugins/EmakiForge/` 整个目录**, 特别是 `recipes/` 和 `gui/`。
- 大部分动作写法由插件自动改写, 但下面三处要你自己动手:
- 三个刷新动作要去掉开头的 `emaki` (对照上面的清单)。
- 锻造自己的变量占位符要加 `var.` 前缀。
- 用 JS 脚本改成功率或发奖励的配方要改成用配方里的 `success_rate`、`failure_outcomes` 和 `actions` 实现。
- 想让锻造界面显示材料清单的话, 需要在 `gui/forge_gui.yml` 的 `capacity_display` 槽位 lore 里加一行 `%blueprint_requirements%`。沿用旧 GUI 文件不加也能正常锻造, 只是不显示清单。
- 配方结构、图纸、玩家的锻造熟练度数据都没变, 不需要迁移。
- 升级后建议跑一次 `/emakiforge reload` 与 `/emakiforge debug stats`, 确认配方注册数量和预期一致, 再打开锻造界面看一眼材料清单。
[/MD]