From 51ea32284dc4888051b6ccfd007484741adee9f7 Mon Sep 17 00:00:00 2001 From: AskaEth Date: Mon, 9 Nov 2026 22:17:49 +0800 Subject: [PATCH] =?UTF-8?q?docs(core):=20inherit::merge=20=E9=87=8C?= =?UTF-8?q?=E5=86=99=E6=B8=85=20minecraftArguments=EF=BC=88=E5=AD=90?= =?UTF-8?q?=E8=A6=86=E7=9B=96=E7=88=B6=EF=BC=89=E4=B8=8E=20arguments.game?= =?UTF-8?q?=EF=BC=88=E8=BF=BD=E5=8A=A0=EF=BC=89=E7=9A=84=E5=8C=BA=E5=88=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit M222 的准入条件就是这条;不给结论留档,下一个人还会以为「叠一层」随便往哪个字段写都行。 --- crates/core/src/game/inherit.rs | 10 +++++ crates/core/tests/liteloader/install.rs | 49 +++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/crates/core/src/game/inherit.rs b/crates/core/src/game/inherit.rs index 2760ac4..fe5ee3f 100644 --- a/crates/core/src/game/inherit.rs +++ b/crates/core/src/game/inherit.rs @@ -132,6 +132,16 @@ pub fn apply_patches(base: VersionJson, patches: &[VersionJson]) -> VersionJson /// 这两点**与 analyse/03 §8.3 第 15 条建议相左**(该条主张逐字段/逐 key 合并)。 /// 保留现状的理由是生态兼容:现实 modpack/loader 的版本 JSON 按 HMCL/原版语义编写, /// 逐 key 合并会让"子层想整份换掉 downloads"的场景语义漂移。经 tower 裁决 2026-10-29 维持。 +/// +/// # 两种 args 表达的语义**不一样**(M222 核实,别混) +/// +/// - `arguments.game` / `arguments.jvm`:父在前、子在后**追加**([`Arguments::merge`]); +/// - `minecraftArguments`(pre-1.13 的单串):**子覆盖父**,子不写才继承。 +/// +/// 所以「叠一层加载器」只能往 `arguments.game` 里加参数;往 `minecraftArguments` 里写会把父链 +/// (例如 Forge 1.12.2 的 `--tweakClass FMLTweaker`)整串顶掉。回归: +/// `crates/core/tests/liteloader/install.rs` 的 `merge_laws_liteloader_depends_on` 与 +/// `stacks_on_forge_and_keeps_the_forge_tweak_class`。 pub fn merge(child: &VersionJson, parent: &VersionJson) -> VersionJson { let mut extra = parent.extra.clone(); extra.extend(child.extra.iter().map(|(k, v)| (k.clone(), v.clone()))); diff --git a/crates/core/tests/liteloader/install.rs b/crates/core/tests/liteloader/install.rs index 24ab372..6c259aa 100644 --- a/crates/core/tests/liteloader/install.rs +++ b/crates/core/tests/liteloader/install.rs @@ -238,3 +238,52 @@ fn new_style_parent_args_are_appended_not_replaced() { "父层参数必须在前:{game:?}" ); } + +/// LiteLoader 生效所依赖的**两条继承合并律**(M222 第一步核实,直接钉在合并函数上)。 +/// +/// 1. `arguments.game`:父在前、子在后**追加**(所以 tweakClass 能叠在父链参数之后); +/// 2. `minecraftArguments`:**子覆盖父**(所以 loader 层绝不能写它,否则父链的 tweakClass +/// 整串消失)。 +/// +/// 抓得住:有人把 `minecraftArguments` 改成追加(HMCL/原版语义不是这样),或把 +/// `arguments.game` 改成整体替换(LiteLoader/其它叠层加载器当场失效)。 +/// 抓不住:真实启动 argv 的顺序(那是 `launch::game_args` 的第 24/25 项, +/// 由 `tests/launch/cmdline_snapshot.rs` 钉住;本 mission 没有改那一层)。 +#[test] +fn merge_laws_liteloader_depends_on() { + use unlucky_core::game::inherit::merge; + use unlucky_core::game::manifest::VersionJson; + + let parse = |json: &str| VersionJson::from_json_str(json).expect("夹具应可解析"); + + let parent = parse( + r#"{"id":"p","minecraftArguments":"--tweakClass FMLTweaker","arguments":{"game":["--parent"]}}"#, + ); + let child = parse(r#"{"id":"c","arguments":{"game":["--child"]}}"#); + let merged = merge(&child, &parent); + assert_eq!( + merged.minecraft_arguments.as_deref(), + Some("--tweakClass FMLTweaker"), + "子没写就继承父(这条是「叠在 Forge 上」的前提)" + ); + let game: Vec = merged + .arguments + .as_ref() + .expect("arguments") + .expand(&Environment::host()) + .game; + assert_eq!( + game, + ["--parent", "--child"], + "arguments.game 是父在前、子在后追加" + ); + + // 子写了 minecraftArguments:整串替换(不是追加)。 + let loud_child = parse(r#"{"id":"c2","minecraftArguments":"--tweakClass LiteLoaderTweaker"}"#); + let merged = merge(&loud_child, &parent); + assert_eq!( + merged.minecraft_arguments.as_deref(), + Some("--tweakClass LiteLoaderTweaker"), + "子覆盖父:这正是 loader 层不许写 minecraftArguments 的原因" + ); +}