docs(readme): M130 补微软登录的 client id 前提,删「十四页」计数,把 i18n 守门边界与产物名写成实测口径
- Accounts:发布版二进制不含 Azure 公共客户端 id(CI 0 处注入),需设 ULL_MSA_CLIENT_ID; 没配时点登录只拿到通用「登录失败 / Code: other」。 - 删「feature-complete: fourteen pages」:代码里 Route 8 个变体、Screen::ALL 5 个,没有读法得到 14; 改成按 Route 列举并说明 Screen::ALL 为何更小。 - i18n:删「视图层没有硬编码字符串」,改成白名单守门抓英文、中文与其它页扫不到的已知边界。 - 自报名例子改成 argv[0] 实测口径;翻牌措辞区分「cargo bin 名未翻」与「产物名已翻」。 - 中文版补「一壳两形」highlight,账户与 auth 模块行补第三方社区服 / 本地档案。 - 顺手改掉「ull 能跑在 Termux」:Linux 资产 glibc ≥ 2.35,Termux 不在发布矩阵内。
This commit is contained in:
1 parent
7092469f90
commit
95131d856e
2 files changed
+79
-39
No files matched your search
@@ -33,7 +33,11 @@ attached to other agent tooling as an MCP server.
|
||||
- **Java management**: a Temurin → Oracle → Microsoft → Zulu fallback chain, region-aware.
|
||||
- **Accounts**: Microsoft sign-in over OAuth 2.0 device code flow → Xbox Live → XSTS →
|
||||
`api.minecraftservices.com`; third-party community auth servers; local offline profiles for
|
||||
isolated testing. Account tokens are kept on this machine only.
|
||||
isolated testing. Account tokens are kept on this machine only. **Microsoft sign-in needs an Azure
|
||||
public client id, and no release binary carries one** — the id is not in this repo and CI injects
|
||||
none, so set `ULL_MSA_CLIENT_ID` before launching, or build with it. Without one, pressing sign-in
|
||||
only raises a generic "Sign-in failed" alert with `Code: other`; nothing on that screen tells you
|
||||
the id is what is missing. Community auth servers and local profiles need no id.
|
||||
- **Engine**: multi-source download (health scoring, mirrors, chunked transfers, hash while
|
||||
downloading) and a YAML rule-based crash diagnosis engine.
|
||||
- **License**: Apache-2.0 © AskaEth (YeiJ).
|
||||
@@ -44,14 +48,23 @@ attached to other agent tooling as an MCP server.
|
||||
Slint tag. `v0.2.0` is the first tag after the rewrite — the iced line, which is what the release
|
||||
pipeline builds now. Everything described below lives on that line.
|
||||
|
||||
- **The iced UI is feature-complete**: fourteen pages — instances, version management (three-column
|
||||
rail layout with search), content library (modpacks / mods / resource packs / shaders with source
|
||||
and version filters), logs, settings (general / appearance / Java / downloads), accounts
|
||||
(Microsoft device code, third-party community servers, local profiles), the AI rail and the
|
||||
installer flows — on top of one component library and one token set.
|
||||
- **What the iced UI has**: instances (list-detail), version management (three-column rail layout
|
||||
with search), content library (modpacks / mods / resource packs / shaders with source and version
|
||||
filters), logs, settings (general / appearance / Java / downloads), accounts (Microsoft device
|
||||
code, third-party community servers, local profiles), the AI rail and the installer flows — all on
|
||||
one component library and one token set. The page list is the one in `presenter::router::Route` —
|
||||
instances, version management, content library, logs, settings, accounts, instance detail, the AI
|
||||
page; `pages::Screen::ALL`, the smaller set that has a slug (`--screen=` and the page test matrix,
|
||||
`crates/app-iced/src/pages/tests.rs`), leaves out accounts, instance detail and the AI page, which
|
||||
are routed but opened from the nav rail or an instance tile.
|
||||
- **Localisation follows the system language**: detection, an explicit override in settings, and
|
||||
persistence across restarts. UI copy goes through a single message catalogue; there is no
|
||||
hard-coded string in the view layer.
|
||||
persistence across restarts. UI copy goes through one message catalogue (`crates/i18n`).
|
||||
- **What the copy guard catches, and what it does not**: a test reads the instances page sources and
|
||||
fails on any string literal that contains an ASCII word unless it is on a short whitelist, so a
|
||||
newly hard-coded English string turns red as it lands
|
||||
(`crates/app-iced/src/pages/instances/tests/i18n.rs`). Known boundary: that scan covers the
|
||||
instances page rather than every screen, and a hard-coded Chinese literal has no ASCII word to
|
||||
match, so nothing catches it — that class relies on review and the screenshot run.
|
||||
- **Appearance**: window background image, per-panel transparency and whole-window transparency
|
||||
(Windows), light / dark / follow-system, and system window corners where the platform grants them.
|
||||
On CPU rendering the translucent layers are switched off and the UI says so.
|
||||
@@ -66,16 +79,21 @@ Binaries you may run into, so you can tell them apart:
|
||||
|
||||
| Binary | Crate | State |
|
||||
|--------|-------|-------|
|
||||
| `unlucky-launcher-iced` | `crates/app-iced` (iced 0.14) | the GUI binary the workspace builds; the release pipeline stages it under the public name `unlucky-launcher`; the same binary answers every CLI subcommand |
|
||||
| `unlucky-launcher-iced` | `crates/app-iced` (iced 0.14) | the GUI binary the workspace builds; the release pipeline stages the file as `unlucky-launcher_<version>_<platform>_<arch>[.exe]`, and the binary inside each archive is named `unlucky-launcher`; the same binary answers every CLI subcommand |
|
||||
| `unlucky-launcher` | `crates/app` (Slint) | **historical**: that crate is excluded from the workspace, so this binary is no longer built or shipped; the v0.1.0 assets are the last Slint builds |
|
||||
| `ull` | `crates/cli` | the zero-UI build of the same command set, shipped as its own asset |
|
||||
|
||||
`unlucky-launcher` (the GUI) and `ull` are not duplicates. The GUI binary needs the graphics stack
|
||||
when it opens a window (it `dlopen`s X11 / Wayland / GL, and links `libfontconfig` at load); `ull`
|
||||
needs nothing beyond glibc, so it runs on a server, a CI container or Termux where no window can
|
||||
exist. Pick `ull` when there is no desktop, `unlucky-launcher <command>` when there is. Both print the
|
||||
same CLI text and name themselves after the binary you invoked: `unlucky-launcher --help` starts with
|
||||
`unlucky-launcher ·`, `ull --help` starts with `ull ·`.
|
||||
The GUI binary (`unlucky-launcher` once extracted or downloaded) and `ull` are not duplicates. The GUI
|
||||
binary needs the graphics stack when it opens a window (it `dlopen`s X11 / Wayland / GL, and links
|
||||
`libfontconfig` at load); `ull` needs nothing beyond glibc, so it runs on a server or a CI container
|
||||
where no window can exist. That floor is glibc ≥ 2.35 (the Linux slots build on Ubuntu 22.04), so an
|
||||
older distribution — and Android/Termux, which is not a released slot at all — needs a source build
|
||||
(`packaging/README.md` §4, §9). Pick `ull` when there is no desktop, `unlucky-launcher <command>` when
|
||||
there is. Both print the same CLI text, and each names itself after the file you ran — `argv[0]` with
|
||||
its directory and a trailing `.exe` removed, and nothing else (`crates/cli/src/cli/program.rs`). So
|
||||
`ull` prints `ull ·`, the `unlucky-launcher` inside an archive prints `unlucky-launcher ·`, a local
|
||||
`cargo build` prints `unlucky-launcher-iced ·`, and the bare Windows asset, whose file name keeps the
|
||||
version segment, prints `unlucky-launcher_<version>_windows_x64 ·`.
|
||||
|
||||
### Subcommand dispatch
|
||||
|
||||
@@ -163,9 +181,11 @@ that crate is kept as source-only reference and can no longer be built as a work
|
||||
What the build produces:
|
||||
|
||||
- `unlucky-launcher-iced` — the GUI (iced). It is also the CLI: the same binary answers every
|
||||
subcommand listed above. The name is temporary — it becomes `unlucky-launcher` at the flip. The
|
||||
release artifacts already carry the public name: the pipeline builds this bin and
|
||||
`packaging/make_artifacts.py` stages it as `unlucky-launcher[.exe]`, so download links never change.
|
||||
subcommand listed above. The `iced` in this name is cargo's, not the download's: renaming the bin
|
||||
is what the "flip" still owes. The release file name carries no implementation detail — the
|
||||
pipeline builds this bin and `packaging/make_artifacts.py` stages it as
|
||||
`unlucky-launcher_<version>_<platform>_<arch>[.exe]`, with the binary inside each archive named
|
||||
`unlucky-launcher`, so download links never carry `iced`.
|
||||
- `unlucky-launcher` — **historical**: no workspace build produces this binary any more; it belonged
|
||||
to `crates/app`, which is excluded. The v0.1.0 assets are the last builds under this name.
|
||||
- `ull` — the CLI as a standalone, UI-free binary. Same command set, no graphics stack, smaller, and
|
||||
@@ -207,7 +227,8 @@ Minimum baseline: **Windows 10**; Windows 8.1 / 8 / 7 are not supported.
|
||||
X11 is the preferred path today and Wayland is the long-term direction. macOS builds are unsigned,
|
||||
so the first launch needs the Gatekeeper quarantine attribute cleared
|
||||
(`xattr -d com.apple.quarantine`)
|
||||
- Android Termux is experimental and not promised: CLI only, GUI unverified
|
||||
- Android Termux is experimental and not promised: no released asset targets it (build from source
|
||||
there), and the GUI is unverified
|
||||
- Each platform runs its own test matrix; capability differences use feature gates with runtime
|
||||
probing.
|
||||
|
||||
|
||||
+39
-20
@@ -13,16 +13,22 @@ Unlucky Launcher(ULL)是一个用 Rust 写的免费开源 Minecraft: Java
|
||||
|
||||
- **单文件原生二进制**:启动器本体不需要 JVM、不需要 WebView、不带旁挂运行时。游戏要的 JDK 由
|
||||
启动器按实例下载管理,不是启动器的依赖。
|
||||
- **一壳两形**:GUI 二进制在跑任何 UI 代码之前就认得全部 CLI 子命令——不开窗、不探渲染器、不扫字体。
|
||||
另有一份更轻的 `ull` 产物,命令集相同,却一个图形栈都不链接。
|
||||
- **默认构建里只有一套 UI**:UI 是 iced 0.14 + Material 3 Expressive。早先的 Slint 实现
|
||||
(`crates/app`)作为**历史参考**保留源码:已被 workspace `exclude`,默认构建不编、测试不跑、
|
||||
发布不发。`v0.1.0` 那个 tag 发的仍是 Slint 版;iced 重写后的第一个 tag 是 `v0.2.0`(见「当前状态」)。
|
||||
- **CPU 软渲染兜底**:`--software-renderer` 让没有可用 GPU 或驱动有问题的老机也能正常显示界面。
|
||||
- **AI Agent + MCP**:启动器内可对话、改设置、读崩溃诊断;`ull agent serve` 把同一个内核以 MCP
|
||||
server 形态(stdio 或 Streamable HTTP)开放给外部 Agent 工具。
|
||||
- **加载器**:Fabric / Quilt / NeoForge / Forge;整合包与 CurseForge / Modrinth 客户端在 core 里。
|
||||
- **加载器**:Fabric / Quilt / NeoForge / Forge;CurseForge 清单、Modrinth `.mrpack`、
|
||||
MultiMC/Prism 整合包导入,mrpack / CurseForge 导出。
|
||||
- **Java 管理**:Temurin → Oracle → Microsoft → Zulu 回退链,带地区判定。
|
||||
- **账户**:用 Microsoft 账户登录,认证走 OAuth 2.0 device code flow → Xbox Live → XSTS →
|
||||
`api.minecraftservices.com`;账户令牌只保存在本机。
|
||||
- **账户**:三轨——Microsoft 账户登录(OAuth 2.0 device code flow → Xbox Live → XSTS →
|
||||
`api.minecraftservices.com`)、第三方社区服、本地离线档案;账户令牌只保存在本机。**微软登录需要
|
||||
一个 Azure 公共客户端 id,而发布版二进制里没有**——这个 id 不在仓库里,CI 也不注入,所以启动前设
|
||||
`ULL_MSA_CLIENT_ID`(或构建时注入)才会有;没配时点登录只会弹一条通用的「登录失败」,带
|
||||
`代码:other`——那句话不会告诉你是缺了 id。第三方社区服与本地档案不需要 id。
|
||||
- **引擎**:多源下载(健康度评分、镜像、分块传输、边下边算)与 YAML 规则引擎的崩溃诊断。
|
||||
- **许可**:Apache-2.0 © AskaEth (YeiJ)。
|
||||
|
||||
@@ -32,11 +38,18 @@ Unlucky Launcher(ULL)是一个用 Rust 写的免费开源 Minecraft: Java
|
||||
第一个 tag 是 `v0.2.0`——也就是 iced 这条线,下面说的这套东西都在线上,也正是发布流水线现在会打
|
||||
出来的东西。
|
||||
|
||||
- **iced 版界面功能已齐**:十四页——实例、版本管理(三栏 + 搜索)、内容库(整合包 / Mod / 资源包 /
|
||||
光影,带来源与版本筛选)、日志、设置(通用 / 外观 / Java / 下载)、账户(微软设备码、第三方社区服、
|
||||
本地档案)、AI 右栏,以及安装流程——共用一套组件库与一套令牌。
|
||||
- **文案跟随系统语言**:自动探测、设置里可显式切换、重启后保持。界面文案统一走一份消息目录,视图层
|
||||
没有硬编码字符串。
|
||||
- **iced 版界面上有什么**:实例、版本管理(三栏 + 搜索)、内容库(整合包 / Mod / 资源包 / 光影,
|
||||
带来源与版本筛选)、日志、设置(通用 / 外观 / Java / 下载)、账户(微软设备码、第三方社区服、本地
|
||||
档案)、AI 右栏,以及安装流程——共用一套组件库与一套令牌。页面清单就是 `presenter::router::Route`
|
||||
里的那些——实例、版本管理、内容库、日志、设置、账户、实例详情、AI 页;`pages::Screen::ALL` 是其中
|
||||
带 slug 的较小一组(`--screen=` 与页面测试矩阵用它,`crates/app-iced/src/pages/tests.rs`),账户、
|
||||
实例详情与 AI 页不在这一组里——它们能路由到,但入口是导航轨与实例磁贴。
|
||||
- **文案跟随系统语言**:自动探测、设置里可显式切换、重启后保持。界面文案统一走一份消息目录
|
||||
(`crates/i18n`)。
|
||||
- **文案守门抓得住什么、抓不住什么**:有一条测试扫实例页的源码,凡是**带 ASCII 单词**的字符串字面量
|
||||
不在短白名单里就红——新写一句英文界面文案,落地即红
|
||||
(`crates/app-iced/src/pages/instances/tests/i18n.rs`)。已知边界:这条扫描只覆盖实例页,不是每一屏;
|
||||
而且中文写死的字面量里没有 ASCII 单词,扫不到——这一类只能靠 review 与出图。
|
||||
- **外观**:窗口背景图、面板透明度、整窗透明度(Windows)、浅色 / 深色 / 跟随系统,以及在系统愿意给
|
||||
的时候使用系统窗口圆角。CPU 渲染档会关掉半透明层,并在界面上说清楚。
|
||||
- **整合包与安装链路都在构建里**:CurseForge 清单 / Modrinth `.mrpack` / MultiMC·Prism 导入,mrpack
|
||||
@@ -44,22 +57,27 @@ Unlucky Launcher(ULL)是一个用 Rust 写的免费开源 Minecraft: Java
|
||||
- **还没做**:安装器与自动更新通道;Windows 定型后的 macOS 真机复核;整合包导入的**逐文件**冲突策略
|
||||
(当前只有一份全局策略,界面如实写明而不是假装支持);原生文件选择框(导入支持拖拽与粘贴路径)。
|
||||
- **Slint 版已退出构建,只留源码作参考**:`crates/app` 不再是 workspace 成员(M118)——源码留作历史
|
||||
参考,不编译、不测试、不发布,也不再有可用的构建方式。翻牌只剩**改名**这一步:它的 bin 现在叫
|
||||
`unlucky-launcher-iced`,发布流水线已经把它按对外名 `unlucky-launcher` 打出去。
|
||||
参考,不编译、不测试、不发布,也不再有可用的构建方式。还欠「翻牌」的只有**仓库内的 bin 名**(现在叫
|
||||
`unlucky-launcher-iced`);**产物名不欠**:`packaging/make_artifacts.py` 落盘时用的是
|
||||
`unlucky-launcher_<版本>_<平台>_<架构>[.exe]`,归档里的二进制名是 `unlucky-launcher`。
|
||||
|
||||
可能会遇到的 bin,先认清楚:
|
||||
|
||||
| 二进制 | crate | 状态 |
|
||||
|--------|-------|------|
|
||||
| `unlucky-launcher-iced` | `crates/app-iced`(iced 0.14) | workspace 里**唯一**的 GUI bin;发布流水线把它按对外名 `unlucky-launcher` 落盘;子命令分发同款 |
|
||||
| `unlucky-launcher-iced` | `crates/app-iced`(iced 0.14) | workspace 里**唯一**的 GUI bin;发布流水线把文件落成 `unlucky-launcher_<版本>_<平台>_<架构>[.exe]`,归档里的二进制名是 `unlucky-launcher`;子命令分发同款 |
|
||||
| `unlucky-launcher` | `crates/app`(Slint) | **历史**:该 crate 已被 workspace `exclude`,这个 bin 不再被构建或分发;`v0.1.0` 的资产是最后一批 Slint 版 |
|
||||
| `ull` | `crates/cli` | 同一套命令的零 UI 构建,作为独立资产随发布分发 |
|
||||
|
||||
`unlucky-launcher` 与 `ull` 不是重复品:开窗时 GUI 二进制要用图形栈(X11 / Wayland / GL 走
|
||||
`dlopen`,启动时直接链接 `libfontconfig`);`ull` 除了 glibc 什么都不需要,所以在没有窗口的服务器、
|
||||
CI 容器、Termux 上跑得起来。没有桌面就用 `ull`,有桌面就用 `unlucky-launcher <子命令>`。两者打出来的
|
||||
CLI 文案是同一套,自称的名字跟着**你敲的那个二进制**走:`unlucky-launcher --help` 首行是
|
||||
`unlucky-launcher ·`,`ull --help` 首行是 `ull ·`。
|
||||
CI 容器上跑得起来。这个地板是 glibc ≥ 2.35(Linux 槽位在 Ubuntu 22.04 上构建),更老的发行版——以及
|
||||
根本不在发布矩阵里的 Android/Termux——得源码自建(`packaging/README.md` §4、§9)。没有桌面就用 `ull`,
|
||||
有桌面就用 `unlucky-launcher <子命令>`。两者打出来的 CLI 文案是同一套,自称的名字跟着**你敲的那个
|
||||
文件**走——`argv[0]` 去掉目录与结尾的 `.exe`,别的都不剥(`crates/cli/src/cli/program.rs`)。所以
|
||||
`ull` 打印 `ull ·`,归档里那个 `unlucky-launcher` 打印 `unlucky-launcher ·`,本地 `cargo build` 出来
|
||||
的打印 `unlucky-launcher-iced ·`,而 Windows 的裸 exe 文件名带版本段,打印的是
|
||||
`unlucky-launcher_<版本>_windows_x64 ·`。
|
||||
|
||||
### 子命令分发
|
||||
|
||||
@@ -84,7 +102,7 @@ unlucky-launcher --version # CLI,输出版本 + 系统摘要
|
||||
|
||||
**未知子命令是错误,不是开窗**:`unlucky-launcher lst` 打印「未知命令 `lst`」、提示
|
||||
`unlucky-launcher --help`,以 1 退出。静默开窗会让脚本以为自己那个拼错的参数生效了。子命令表只有
|
||||
一处定义(`crates/cli/src/cli/parse.rs`),所以两个 GUI 二进制和 `ull` 认的命令集天然一致。
|
||||
一处定义(`crates/cli/src/cli/parse.rs`),所以 GUI 二进制和 `ull` 认的命令集天然一致。
|
||||
|
||||
## 模块地图
|
||||
|
||||
@@ -112,7 +130,7 @@ Unlucky-Launcher (cargo workspace)
|
||||
| `download` | 多源健康度、镜像、分块下载、边下边算 |
|
||||
| `game` | 版本/实例仓库、快照与继承解析 |
|
||||
| `launch` | 10 阶段启动管线、进程、JSONL 事件流 |
|
||||
| `auth` | Microsoft 账户登录(OAuth 2.0 device code → Xbox Live → XSTS → Minecraft Services) |
|
||||
| `auth` | Microsoft 账户登录(OAuth 2.0 device code → Xbox Live → XSTS → Minecraft Services)、第三方社区服、本地档案 |
|
||||
| `addon` | 加载器安装、整合包、CurseForge / Modrinth |
|
||||
| `diagnose` | 五类信号采集、YAML 规则引擎、hs_err 解析 |
|
||||
| `platform` | OS 抽象:路径、进程、文件锁、能力探测、运行期 OS 检测 |
|
||||
@@ -138,9 +156,10 @@ cargo build --release # bin 落在 target/relea
|
||||
|
||||
编出来的 bin:
|
||||
|
||||
- `unlucky-launcher-iced`——GUI(iced)。它同时也是 CLI:同一个二进制认上面列的全部子命令。名字是
|
||||
临时的,翻牌时才改成 `unlucky-launcher`;发布产物**已经**用对外名:流水线编这个 bin,
|
||||
`packaging/make_artifacts.py` 落盘时改成 `unlucky-launcher[.exe]`,所以下载链接不用变。
|
||||
- `unlucky-launcher-iced`——GUI(iced)。它同时也是 CLI:同一个二进制认上面列的全部子命令。名字里的
|
||||
`iced` 是 cargo 的,不是下载链接的:还欠「翻牌」的只有这个 bin 名;发布文件里不带实现细节——流水线编
|
||||
这个 bin,`packaging/make_artifacts.py` 落盘时改成
|
||||
`unlucky-launcher_<版本>_<平台>_<架构>[.exe]`,归档里的二进制名是 `unlucky-launcher`。
|
||||
- `unlucky-launcher`——**历史**:workspace 构建已不产出它(它属于被排除的 `crates/app`)。
|
||||
`v0.1.0` 的资产是最后一批用这个名字发出去的构建。
|
||||
- `ull`——CLI 的独立无 UI 构建:同一套命令、不链接图形栈、体积更小,给完全没有显示设备的机器用。
|
||||
@@ -175,7 +194,7 @@ cargo build --release # bin 落在 target/relea
|
||||
- macOS 12+(Apple Silicon 与 Intel)与 Linux x64 / arm64 都是支持槽位;Linux 上 X11 是当前首选路径,
|
||||
Wayland 是大方向。macOS 产物未签名,首次启动要自己清掉 Gatekeeper 隔离标记
|
||||
(`xattr -d com.apple.quarantine`)
|
||||
- Android Termux 试验级、不承诺:只保证 CLI,GUI 未验证
|
||||
- Android Termux 试验级、不承诺:发布矩阵里没有面向它的资产(要在 Termux 上跑得源码自建),GUI 未验证
|
||||
- 每个平台跑各自的测试矩阵;能力差异用 feature gate + 运行期探测表达。
|
||||
|
||||
## 许可证与致谢
|
||||
|
||||
Reference in new issue
Block a user