feat(core): LiteLoader 安装路线(官方版本表 + 从零合成 launchwrapper 清单)

按 M218 SURVEY-p1 §4.1 的清单接上 LiteLoader 的安装路线,不动 OptiFine。

- core: 新增 addon::loader::liteloader(官方 versions.json 解析 + 合成清单)与
  addon::loader::parent(父版本链读盘定位原版版本);LoaderKind 加 LiteLoader;
  LoaderRelease 加 parent_version_id、LoaderPlanInput::vanilla_installed → parent_installed;
  LoaderInstallPlan::build 改返回 Result(父版本缺失具名报错);LoaderSource::resolve_on
  支持指定父版本(仅 LiteLoader,其它组合具名 unsupported)。
- 继承边界(本 mission 第一步核实):arguments.game 父在前子在后追加,minecraftArguments
  子覆盖父,启动顺序 legacy(24) → arguments.game(25)。所以 tweakClass 只写 arguments.game,
  绝不写 minecraftArguments(会顶掉 Forge 1.12.2 的 FMLTweaker)。
- maven/fabric 的 `_ =>` 通配改成穷尽分支:非 maven 族不再静默回落 Forge 的仓库;
  maven::{metadata_url,installer_url} 改返回 Option<String>。
- presenter: supported() 收 LiteLoader、wizard_choices 六选、dto::instances 按关注点拆成
  instances/{loader,runtime,create,tests}.rs(原文件 395 行,动手前先拆)。
- cli: --loader 区分「认不出」(loader_unknown) 与「认得但装不了」(loader_unsupported);
  <version> 位写加载器版本 id 时按父版本处理(只有 liteloader 接受);help 只改 install 段。
- app-iced: 下载页加载器 chip 加 LiteLoader(1.5.2~1.12.2,两头按官方没有构建拒),
  chip 清单改为委派 Loader::ALL。
- 测试: 真实响应的裁剪夹具(dl.liteloader.com 与 repo.mumfrey.com 的 maven-metadata)
  驱动「解析→计划→落盘→继承→启动参数顺序」全链;Forge 父链有回归(FMLTweaker 必须还在
  且排在 LiteLoader 之前);父版本缺失/组合不支持/取消/坏表各自具名错误。
This commit is contained in:
AskaEth committed 2026-11-10 19:34:09 +08:00
1 parent 307d29239a
commit 944b1610c8
37 files changed
+2427 -518

No files matched your search

+5 -4
View File
@@ -6,8 +6,8 @@
//! 差异只在线程模型:进度经 [`super::job::HostTask::Install`] 回流(文件计数 + 字节 + 速度/ETA),
//! 且整段跑在后台线程里(`block_on` 不占 UI 线程)。
//!
//! 加载器范围:原版 + Fabric/Quilt/Forge/NeoForge(四家,与 CLI 对齐)。OptiFine/LiteLoader
//! 两家 core 侧都还没有安装管线,仍在 GUI 里显式拒装并说清去哪装。
//! 加载器范围:原版 + Fabric/Quilt/Forge/NeoForge/LiteLoader(五家,与 CLI 对齐)。OptiFine
//! 仍没有安装管线(要跑外部 `optifine.Patcher` + 原地改 zip),在 GUI 里显式拒装并说清去哪装。
//! 失败一律落 `.ULL/logs/install.log`([`super::install_journal`]),文案里带日志路径。
use std::path::PathBuf;
@@ -87,7 +87,7 @@ pub fn loader_label(kind: LoaderKind, version: &str) -> String {
}
}
/// GUI 侧支持的加载器(五选:原版 + 四家加载器,与 CLI 的 `--loader` 词表一致)。
/// GUI 侧支持的加载器(六选:原版 + 五家加载器,与 CLI 的 `--loader` 词表一致)。
///
/// 写成穷举 `matches!` 而不是 `true`:将来 core 加了第六种加载器,这里默认拒绝,
/// 由 [`unsupported_reason`] 给出明确说法,而不是让它走进不属于它的安装分支。
@@ -99,13 +99,14 @@ pub fn supported(kind: LoaderKind) -> bool {
| LoaderKind::Quilt
| LoaderKind::Forge
| LoaderKind::NeoForge
| LoaderKind::LiteLoader
)
}
/// 不支持的加载器 → 给用户的可执行建议。
pub fn unsupported_reason(kind: LoaderKind) -> String {
format!(
"{} 还没有接入安装管线(目前支持原版 + Fabric/Quilt/Forge/NeoForge);请先在实例页导入已有版本,或换成受支持的加载器。",
"{} 还没有接入安装管线(目前支持原版 + Fabric/Quilt/Forge/NeoForge/LiteLoader);请先在实例页导入已有版本,或换成受支持的加载器。",
kind.label()
)
}
+5 -2
View File
@@ -122,8 +122,11 @@ pub(super) fn install_loader(
layout: &env.game,
release: &release,
environment: &Environment::host(),
vanilla_installed: env.game.is_version_installed(version),
});
// 向导/下载页只能装「叠在原版上」的层(CreateRequest 没有父版本槽位),
// 所以父版本恒等于原版版本;真装缺原版时由下面的 `vanilla_install_needed` 补装。
parent_installed: env.game.is_version_installed(&release.parent_version_id),
})
.map_err(|error| error.to_string())?;
if plan.vanilla_install_needed {
let mut vanilla = request.clone();
vanilla.loader = LoaderKind::Vanilla;
+4 -2
View File
@@ -143,11 +143,13 @@ fn loader_support_matrix_is_explicit() {
LoaderKind::Quilt,
LoaderKind::Forge,
LoaderKind::NeoForge,
// M222:LiteLoader 走「官方版本表 + 从零合成 launchwrapper 清单」,不跑外部进程。
LoaderKind::LiteLoader,
] {
assert!(supported(kind), "{} 应当受支持", kind.label());
}
// 这两家 core 侧还没有安装管线,仍然显式拒装并说清去哪装。
for kind in [LoaderKind::OptiFine, LoaderKind::LiteLoader] {
// OptiFine 仍没有安装管线(要跑外部 Patcher + 原地改 zip),显式拒装并说清可替代做法。
for kind in [LoaderKind::OptiFine] {
assert!(!supported(kind), "{} 不该被当成可装", kind.label());
let reason = unsupported_reason(kind);
assert!(reason.contains(kind.label()), "{reason}");