根因(拿到的真实证据,不是猜的):v0.2.2(run 42322062879 / job 128248713926)与 v0.2.3 (run 42429017002 / job 128573547829)两份 check-run 注解逐字一致 —— 失败步骤是第 6 步 `Windows ARM64 工具链体检`,第 7 步 `cargo build` 状态 skipped。也就是说 v0.2.1~v0.2.3 五轮 全红都红在一个**编译前的启发式探针**上,真正的编译器/链接器一次都没说话。该探针的结论还与它 自己打印的快照矛盾:`SDK Lib 版本→um 架构: 10.0.22621.0→um:[arm,arm64,x64,x86,]` 明明在,却 同时报 `kernel32=缺失`(同一个 `find -path` 模式在本地合成目录树上命中)。runner 实况是 Windows 11 Arm64 + Visual Studio 2026 镜像,`VC.Tools.ARM64` 与 `Windows11SDK.22621/26100` 都装好了,M142 的 `setup.exe modify` 反倒返回非 0。 改: - release-build.yml:探针降级为「只取证」——vswhere 组件查询 + 各目录 `.lib` 计数 + arm64 `link.exe` 候选,一条 `::error::` 都不写、永不 exit 1;不再自动补装 VS。红绿只由 cargo/链接/静态 CRT 导入表门禁决定。cargo build 步给 arm64 显式备齐工具链: `rustup target add aarch64-pc-windows-msvc`、`vcvarsall.bat arm64` 取 `LIB`/`INCLUDE`、 vswhere 定位 arm64 `link.exe` 后导出 `CARGO_TARGET_AARCH64_PC_WINDOWS_MSVC_LINKER` (顺序不能反:只给链接器不给 LIB ⇒ LNK1181 kernel32.lib)。 - 新增 packaging/check_publish_slots.py(344 行,零依赖):名单 ⇄ 产物**两个方向**。 声明了缺 GUI/CLI ⇒ `::error::` + exit 1;有产物没声明 ⇒ `::warning::` 明说未发布(M142 之后 这个方向是静默的,裁剪步只 echo 一行 drop:)。另有源码级断言(名单每项必须存在且 mode=ci、 运行期名单必须等于文件里那行)与 8 条 `--self-test` 注入回归。 - release-publish.yml:裁剪前插一步跑那个守卫,原来内联的齐全性循环搬进脚本(一套判据一处实现); 重算 SHA256SUMS 的步骤只负责重算。 - release-guard.yml:PR 阶段跑守卫自测 + 源码级断言。 - 文档同步:release.yml / release-publish.yml / release-build.yml 头注释、packaging/README §12、 §1 矩阵、§3 构建与发布、§9 支持矩阵、§7.5 arm64 取证、release-notes.md、README/README.zh-CN 的产物矩阵与说明。口径统一为「arm64 构建取证中、未发布」,不写成已支持。 没做的(按 tower 裁决「方案乙」):`PUBLISH_SLOTS` 本轮**不加回** arm64。arm64 从未产出过 PE、 本机也证不了,写进名单就等于拿 x64 的发布去赌它(M142 移出名单正是为避免这个事故)。下一 tag 的 CI 真出包后翻一行即可,守卫与 SHA256SUMS 自动跟着扩。 验证:workflow YAML 全部可被 PyYAML 解析;所有 `run:` 块过 `bash -n`;探针步在本机(无 VS/SDK) 实跑 exit 0 并打出实况注解;守卫 `--self-test` 8 条全绿、正反两个方向都在合成 dist 上实测过; check_release_semantics.py(含 --self-mutation)/ release_marker / make_manifest 自检全绿; cargo metadata 正常。**arm64 产物从未被构建过、也从未在真机跑过**——本机 `rustc --target aarch64-pc-windows-msvc` 直接撞上没有 MSVC 链接器(git-bash 的 GNU `link` 被当成 link.exe), `cargo check --workspace --target aarch64-pc-windows-msvc` 也死在 aws-lc-sys 的 cc-rs 阶段 (GNU host 上没有该 target 的 C 编译器)。真实结论只能等下一 tag 的 CI。
160 lines
10 KiB
Markdown
160 lines
10 KiB
Markdown
# Unlucky Launcher {{VERSION}}
|
|
|
|
Rust-native **single-file** Minecraft launcher: iced 0.14 + Material 3 Expressive UI, built-in AI agent
|
|
(chat / setting edits / crash diagnosis) and an MCP server other agent tools can attach to.
|
|
No WebView, no bundled runtime, no JRE download needed to start the launcher itself.
|
|
|
|
## What's new in {{VERSION}}
|
|
|
|
- **{{VERSION}} is the first release published as a stable release.** GitHub only points
|
|
`releases/latest` at the newest **non-prerelease** release, so `0.2.2` — kept as a historical
|
|
pre-release, untouched — never appeared there. A pushed tag now creates a stable release by default;
|
|
a pre-release has to be asked for explicitly (`workflow_dispatch` with `prerelease=true`).
|
|
- **Self-update works end to end.** `ull update check` / `ull update apply` and the settings panel's
|
|
Update group share one core (`crates/core/src/update/`): manifest, version and channel admission,
|
|
length + SHA256 verification, and an atomic rename-based swap that rolls back on failure. Only the
|
|
stable channel is published today.
|
|
- **Online content library (Modrinth, anonymous).** Search, project details and version lists come from
|
|
Modrinth's v2 API with facets derived from the target instance, and a known hash completes a remote
|
|
entry. Being offline is reported as "not connected", never as "no matching content".
|
|
- **Per-file decisions when importing a modpack.** The pre-import scan lists every conflicting file in
|
|
pages of 40, and you choose keep-all, overwrite-all, or per item; files that do not conflict are
|
|
never rewritten, and the report names every conflict afterwards.
|
|
- **Per-instance launch arguments.** JVM arguments, game arguments, memory, the Java executable and the
|
|
graphics backend (`default` / `opengl` / `vulkan`) are set per instance, each field falling back on
|
|
its own to the global setting and then the factory default. The CLI reads the same resolved values.
|
|
|
|
## Downloads
|
|
|
|
Asset names are `<name>_<version>_<platform>_<arch>`, underscore separated — the rule
|
|
`packaging/make_artifacts.py::asset_stem()` applies:
|
|
|
|
| Platform | Asset | Notes |
|
|
| --- | --- | --- |
|
|
| Windows 10/11 x64 | `unlucky-launcher_{{VERSION}}_windows_x64.exe` | single exe, double-click to run; this is also what you run on ARM64 Windows (x64 emulation) |
|
|
|
|
**Windows ARM64 is not part of this release.** CI still builds it on a native `windows-11-arm` runner (Windows 11
|
|
Arm64 with Visual Studio 2026), but the build has not delivered an artifact yet, so
|
|
`unlucky-launcher_{{VERSION}}_windows_arm64.exe` is deliberately kept out of the download list and out of
|
|
`SHA256SUMS.txt` instead of handing out a build nobody has verified. Worth stating plainly: every ARM64 failure
|
|
so far happened in a **pre-build toolchain probe** that guessed whether the SDK's ARM64 import libraries were
|
|
present and aborted before `cargo build` ever ran — the compiler and linker have not been heard from yet. That
|
|
probe is now evidence-only (it prints what it sees and never decides the job), so the next CI run is the first
|
|
one that can actually answer the question. `windows-x64` is the only published slot; ARM64 rejoins this table as
|
|
soon as a run produces its artifact (one line in the workflow's `PUBLISH_SLOTS`, guarded on both sides by
|
|
`packaging/check_publish_slots.py`).
|
|
|
|
**This release ships Windows only, and CI builds Windows only.** The Linux (x64 / arm64) and macOS
|
|
(Apple Silicon / Intel) slots are not built by the release workflow at all — they have not been verified
|
|
on real machines yet, so nothing unverified is handed out and no build minutes are spent on them. They
|
|
stay out of the download list and out of `SHA256SUMS.txt` until that verification happens; a manual
|
|
workflow run can build all six slots for that purpose, but the four extra slots are never published. The
|
|
support matrix below marks those slots accordingly.
|
|
|
|
The Windows asset is a bare `.exe`, so `LICENSE`, `NOTICE` and `README.md` are attached to this release
|
|
next to it: the license terms travel with every download. Slots that ship an archive (Linux / macOS, once
|
|
published) unpack to one top-level directory of the same name holding the binary plus those three
|
|
documents.
|
|
|
|
## Command line
|
|
|
|
Each published slot also ships the command line as its own small bare asset,
|
|
`ull_{{VERSION}}_<platform>_<arch>` (`.exe` on Windows):
|
|
|
|
```powershell
|
|
.\ull_{{VERSION}}_windows_x64.exe instances list # servers and CI: no graphics stack needed
|
|
```
|
|
|
|
`ull` runs `instances`, `install`, `pack import`, `launch`, `accounts`, `sessions`, `logs`, `diag`,
|
|
`config`, `java` and `agent`, and links no graphics library at all. The GUI binary accepts the same set
|
|
before it ever opens a window, so a desktop machine does not need `ull`.
|
|
|
|
## Updating
|
|
|
|
The launcher reads `releases/latest/download/manifest.json` on startup (switchable: `update.auto_check`)
|
|
and shows four distinct outcomes: up to date, an update is available, a newer version exists but ships no
|
|
artifact for this platform, or the check itself failed. `ull update check` prints the same verdict, and
|
|
`ull update apply` downloads, verifies SHA256 and swaps the binary atomically, rolling back if the swap
|
|
fails. Nothing installs without you asking for it.
|
|
|
|
## Support matrix
|
|
|
|
Published = shipped as a download of **this** release, listed in `SHA256SUMS.txt`.
|
|
|
|
| Platform | Status in this release | Level | Runtime requirements |
|
|
| --- | --- | --- | --- |
|
|
| Windows 10/11 x64 | **published** | first class | nothing beyond the OS (UCRT is part of Win10+) |
|
|
| Windows 11 ARM64 | not published (build evidence only) | first class (launcher artifact) | nothing extra; the launcher runs natively, the game itself runs through the OS x64 emulation layer with an x64 JDK |
|
|
| macOS 12+ Apple Silicon | not built (unverified) | first class (unverified) | nothing; unsigned build, needs the Gatekeeper workaround |
|
|
| macOS 12+ Intel | not built (unverified) | first class (unverified) | same as above |
|
|
| Linux x64, X11 | not built (unverified) | first class (unverified) | `libxkbcommon`, `fontconfig`, `libGL` (or software renderer), `libxcb` |
|
|
| Linux x64, Wayland | not built (unverified) | supported (unverified) | `wayland-client`, `libxkbcommon`, plus the X11 set for XWayland apps |
|
|
| Linux arm64, X11 | not built (unverified) | first class (unverified) | glibc 2.35+, `libxkbcommon`, `fontconfig`, `libGL`, `libxcb` |
|
|
| Linux arm64, Wayland | not built (unverified) | supported (unverified) | the above plus `wayland-client` |
|
|
| Windows 8.1/8/7 | not built | unsupported | the baseline is Windows 10 |
|
|
| Android — Termux + X11 | not built (no CI slot) | experimental, not promised | CLI and GUI from source only; GUI verified on-device twice: CPU software rendering and self-built Mesa/turnip GPU acceleration (see `packaging/docs/termux-glibc-build.md` and `README.termux.md`) |
|
|
|
|
`windows-x64` is the only published slot this release; Windows ARM64 stays out until a CI run actually produces
|
|
its artifact (see Downloads above — so far every ARM64 failure was the pre-build probe, never the compiler).
|
|
Both arm64 rows are formal matrix slots, not the experimental Termux path, and Linux arm64 is not built by
|
|
default — someone has to run it on real hardware (via a manual all-slots run) before it joins this list. The
|
|
rows above and the matrix table in `packaging/docs/compliance-support-boundaries.md` §9 are the same list —
|
|
change one, change the other.
|
|
|
|
## Install
|
|
|
|
**Windows** — put the `.exe` anywhere and run it. `_windows_x64.exe` is the only Windows asset in this
|
|
release, and it is also what you run on ARM64 Windows (the OS runs it through its x64 emulation layer).
|
|
The first run creates `.ULL/` and `.minecraft/` next to the exe (portable is the default data mode); the
|
|
per-user `%APPDATA%\ULL` plus `%APPDATA%\.minecraft`, or a custom root, are selectable instead.
|
|
|
|
Linux / macOS are not part of this release; their asset names are already fixed by the same rule
|
|
(`unlucky-launcher_{{VERSION}}_linux_x64.tar.gz`, `_linux_arm64`, `_macos_arm64`, `_macos_x64`) so the
|
|
links will not change shape when those slots open.
|
|
|
|
## No GPU? Software renderer
|
|
|
|
The UI renders through `wgpu` (GPU) and falls back to the `tiny-skia` CPU rasteriser when no usable
|
|
adapter is present; `--software-renderer` (or its equivalent `--renderer=cpu`) forces that path.
|
|
|
|
## Verify the download
|
|
|
|
`SHA256SUMS.txt` lists exactly the assets attached to this release (Windows only), and `sha256sum -c`
|
|
checks the ones you actually downloaded:
|
|
|
|
```bash
|
|
sha256sum -c SHA256SUMS.txt --ignore-missing # Linux / WSL
|
|
shasum -a 256 -c SHA256SUMS.txt # macOS (sha256sum is not bundled)
|
|
Get-FileHash .\unlucky-launcher_{{VERSION}}_windows_x64.exe -Algorithm SHA256 # Windows PowerShell
|
|
```
|
|
|
|
```
|
|
{{SUMS}}
|
|
```
|
|
|
|
## Known limitations of this build
|
|
|
|
- Microsoft (MSA) sign-in works out of the box: this build carries the Azure public client id it needs
|
|
(a public client id, not a credential — it ships inside the binary), so there is nothing to configure
|
|
before signing in. Setting `ULL_MSA_CLIENT_ID=<id>` before launching still overrides it; the variable
|
|
is read at startup, so restart the launcher after changing it. A build with no id anywhere stops
|
|
before any network call, and the GUI banner says so plainly: the title "Microsoft sign-in is not
|
|
configured", a body naming `ULL_MSA_CLIENT_ID=<id>` (set it, or build with it, then restart) and
|
|
`Code: msa_not_configured`, with no Retry button. Every other sign-in failure keeps the generic
|
|
banner plus its own `Code:` line, with the full reason only in the launcher log. `ull accounts add
|
|
msa` prints the same fix on the command line. Offline profiles and authlib-injector servers need no
|
|
id.
|
|
- Binaries are not code-signed / notarized yet: Windows SmartScreen and macOS Gatekeeper warn on first
|
|
launch. The checksums above are the integrity reference for now.
|
|
- When the macOS slot ships it is the bare binary (single-file promise), not a `.app` bundle: no Dock
|
|
icon or Finder double-click — launch it from a terminal.
|
|
|
|
## License
|
|
|
|
Apache-2.0, third-party notices in `NOTICE`. Not affiliated with Mojang or Microsoft; no game files ship.
|
|
|
|
## UI framework in this build
|
|
|
|
Every asset here is built from the iced UI (`crates/app-iced`, iced 0.14, MIT); no other UI framework is
|
|
linked into it.
|