Commit Graph
3 Commits
Author SHA1 Message Date
AskaEth a322cfcbfe refactor(core): M126 r1 返工:词表改由宏单表生成,安装侧解析收口
复审 r1 的三条:

P1(CI 会红):`const MARKERS: [(LoaderKind, &'static str); 6]` 触发
clippy::redundant_static_lifetimes(`error: constants have by default a 'static
lifetime`)。返工直接**删掉 MARKERS**:标记串就取 `LoaderKind::as_str()`,候选顺序取
`LoaderKind::ALL`,认不认标记看 `has_marker()`——解析表既没有独立字面量,也没有独立清单。

P2-1:「漏加 ALL 不会被任何东西拦住」是真话,之前的 doc 覆盖声明是假的。返工用
`loader_kind_vocab!` 宏从**一张表**一次生成枚举 / `ALL` / `as_str` / `has_marker`:
「加了一支却忘了进清单」在物理上不可能(没有第二份清单可写)。尺寸锚随之删除(`[Self; N]`
的宽度本来就由表决定),`parse` 留在宏外的独立 impl 里。

P2-2:「全仓唯一一份 id 字面量」原先不成立——安装侧 `LoaderKind::parse` 还手写了一份反向
匹配表,并带一个只进不出的 `neo-forge` 别名。返工让 install 侧 `parse` **委派**
`core::game::LoaderKind::parse`,只额外收 `neo-forge`(Modrinth 拼法)这一个输入别名,
并新增 `addon::loader::tests::vocabulary` 覆盖「委派没接错 + 别名只进不出 + 装不了的几家
返回 None」。

测试:core 的 `markers_cover_every_kind_that_has_one` 换成
`every_stable_id_parses_back_to_its_kind`(往返 + 顺序优先级),仍是「改名不可见、只有契约
测试能抓」的分工,doc 里写明。

门禁:fmt OK;clippy -p unlucky-core -p unlucky-presenter -p unlucky-cli --all-targets
-- -D warnings 干净;三 crate 测试 core lib 401 / presenter 220 / cli 41 全 ok。
文件行数:loader.rs 397(≤400)。
2026-11-05 18:08:57 +08:00
AskaEth be37c17962 refactor(core): M126 加载器稳定 id 词表收敛到 game::LoaderKind::as_str
M122 把「id → 加载器」的解析收到 core::game::loader::InstanceLoader::parse,但
「种类 → 对外稳定 id」的命名词表还散在多处,其中 install 侧那一份只靠一句「不要改名」
的注释约束,MARKERS 更是第四张无守卫字面量表。

- core::game::LoaderKind 新增 as_str(**全仓唯一一份 id 字面量**)、has_marker
  (穷尽 match:新种类必须表态认不认 id 标记)、parse(as_str 的反查)与 ALL(清单,
  顺序即标记优先级);MARKERS 的标记串改为取自 as_str,不再是独立字面量。
- addon::loader::LoaderKind::as_str 改成委派(结构映射,无字面量):安装侧拼出的
  <mc>-<kind>-<loader> 与解析侧从此同源。
- presenter::dto::instances::LoaderKind 的 as_str/parse 委派给 core(to_core/from_core
  是结构映射),删掉第四份词表;CLI 删掉 loader_kind_id 翻译层,直接调 core。
- 测试:core 新增 markers_cover_every_kind_that_has_one(MARKERS↔ALL↔has_marker↔as_str
  逐格对齐 + 按标记串 round-trip + neoforge 先于 forge);presenter 新增
  loader_kind_ids_are_the_released_contract(七个 id 逐字钉住 + 反查 + 别名隔离)。
- 对外输出未变:真二进制对同一组 7 类实例的 `instances list --json` 输出逐字节相同
  (md5 0341752658ca28e020ba48c31a51a124),人读输出同样逐字节相同。

file 行数:core/game/loader.rs 337→399(≤400 硬约束,文档按密度重排、事实未丢)。
2026-11-05 18:08:56 +08:00
AskaEth 081ce65596 fix(core): M122 版本 id → 加载器只留一份解析,并认全自家 id 口径
`presenter::host::game::loader_from_id` 只认 `fabric-loader-…` / `quilt-loader-…`,
而本启动器自己生成的 id 是 `<mc>-<kind>-<loader>`(`1.20.4-fabric-0.16.5` /
`1.20.4-quilt-0.27.0`),于是刚装好的 Fabric / Quilt 实例在实例页显示成「原版」。

- 新增 `core::game::loader`:`InstanceLoader::parse` 是全仓唯一的 id 解析入口
  (按 `-` 切段、段前缀匹配标记、跳过独立的 `loader` 段、砍老 HMCL 的 MC 尾巴)。
  覆盖自家四种口径(生成端 `addon::loader::LoaderKind::version_id`)、老 HMCL / CF
  口径、OptiFine / LiteLoader 第三方前缀;标记按整段前缀匹配,不再用「包含子串」。
- presenter 只留 DTO 翻译:`dto_kind` 穷尽 match(`dto/` 里仍不许出现 core 类型)。
- 测试:真值表**从生成端取 id**,反向锚(普通版本 id 不被认成加载器),映射单射,
  以及端到端快照(`instances()` 的磁贴数据对四个加载器各自的版本号与徽标)。
2026-11-05 14:46:22 +08:00