AskaEth 69d0025d09 fix(core): M73 r1 —— Windows 壁纸来源改为「当前主题优先」,通配主题包降为末档
复审 p2-1(medium):Win10+ 上 `%APPDATA%\Microsoft\Windows\Themes\` 通常只有
`TranscodedWallpaper`,一个 `.theme` 都没有;当前生效的主题记在
`HKCU\Software\Microsoft\Windows\CurrentVersion\Themes` 的 `CurrentTheme` 值里,
指向 `%LOCALAPPDATA%\Microsoft\Windows\Themes\Custom.theme`。

- 新增第二步 `windows-current-theme`:`reg.exe query ... /v CurrentTheme` →
  归一化(含 `%LOCALAPPDATA%` 展开)→ 读该 `.theme` 的 `Wallpaper=`;
- `%APPDATA%\...\Themes\*.theme` 通配扫描从「第二步」降为第四步兜底,
  evidence 如实标注「用户另存的主题包,可能未启用」;
- 新顺序:TranscodedWallpaper → CurrentTheme → 注册表 WallPaper → 另存主题包;
- `HostRoots` 增加 `local_app_data`(`%LOCALAPPDATA%`,退 `~/AppData/Local`)。

复审 p2-2(low):`transcoded_wallpaper_hit_comes_first` 补一条字面量路径断言,
防止夹具与生产代码用同一构造函数一起拼错。

复审 p2-3(low):`HostIo::run` 现在检查退出码(`!output.status.success()` 也返回
`None`),与四处「非零退出 → 失败」的文案对齐;`io.rs` 补一条夹具用例
(有 stdout 但退出码非零)证明旧行为会被挡掉。

行长:`windows.rs` 371 → 拆出纯解析到 `wallpaper/windows/parse.rs`(100 行),
全部 7 个文件 ≤400 行。真机复跑 `detect()`:第 1 条 transcoded、第 2 条
`windows-current-theme` → `C:\Windows\web\wallpaper\Windows\img0.jpg`(与注册表同源,
去重后只剩一条),`%APPDATA%` 下无主题包的 note 照旧。
2026-11-01 21:17:55 +08:00
2026-10-31 21:54:10 +08:00
2026-10-31 21:54:10 +08:00
2026-10-31 21:54:10 +08:00
2026-10-31 21:54:10 +08:00
2026-10-31 21:54:10 +08:00

Unlucky Launcher (ULL)

English · 简体中文

Official project home: https://github.com/AskaEth/Unlucky-Launcher | downloads, issues and release notes all live there: https://github.com/AskaEth/Unlucky-Launcher/releases

Unlucky Launcher (ULL) is a free, open-source Minecraft: Java Edition launcher written in Rust (Apache-2.0). It ships as one native binary per platform — no installer, no bundled runtime, no WebView. The launcher embeds an AI agent client (chat / configuration / crash diagnosis) and can be attached to other agent tooling as an MCP server.

Highlights

  • Single-file native binary: the launcher itself needs no JVM, no WebView and no sidecar runtime. The JDK a game needs is downloaded and managed per instance, not as a launcher dependency.
  • Two UI stacks during the rewrite: the released UI is Slint (Royalty-Free 2.0); the next-generation UI is iced 0.14 + Material 3 Expressive and is still being written (see Status).
  • CPU software-rendering fallback: --software-renderer keeps the interface rendering normally on machines with no usable GPU or with broken drivers.
  • AI agent + MCP: chat, setting edits and crash diagnosis inside the launcher; ull agent serve exposes the same core as an MCP server (stdio or Streamable HTTP) to external agent tools.
  • Mod loaders: Fabric, Quilt, NeoForge, Forge, with modpack and CurseForge / Modrinth clients in the core.
  • Java management: a Temurin → Oracle → Microsoft → Zulu fallback chain, region-aware.
  • Accounts: sign in with a Microsoft account over OAuth 2.0 device code flow → Xbox Live → XSTS → api.minecraftservices.com; account tokens are kept on this machine only.
  • 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).

Status

Two tracks. They are not the same product yet, so read the headings before downloading anything.

Track A — released: v0.1.0, Slint UI (this is what you can download today)

  • GitHub Releases v0.1.0 (2026-11-01, flagged pre-release): single-file assets for Windows x64 (a bare .exe), Linux x64 and macOS (arm64 and x64) .tar.gz. Every release also carries SHA256SUMS.txt and the LICENSE / NOTICE / README.md texts as separate assets; on Windows those texts sit next to the .exe because a bare exe cannot hold them, while the unix archives already contain them.
  • UI: Slint + Metro. This is the shipped GUI — the instance, download, account, Java, log and settings pages all run on the core engine (the in-app AI chat panel is a scripted placeholder).
  • CLI ull is built from the same tree at the same version — but the v0.1.0 assets ship only the GUI binary. If you want the CLI, build it yourself: cargo build --release --bin ull. Commands: instances, install, launch, accounts, sessions, logs, diag, config, java, agent.
  • Windows ARM64 and Linux ARM64 slots are wired into the release pipeline; the next tagged release builds them. The v0.1.0 assets predate those two slots.

Track B — in progress on dev: next-generation UI (iced + Material 3 Expressive)

This track is not released yet — you can see it only by building from source.

  • Locked direction: the look is Material 3 Expressive and the framework is iced 0.14; the UI layer is written from scratch. Neither the style nor the framework will change again.
  • Done: the token crate crates/design (no UI framework, no third-party crates — real HCT color, type scale, shape scale, spacing, elevation, motion, icon geometry, per-component metrics) and the skeleton crate crates/app-iced (opens a window, self-drawn title bar and window buttons, navigation rail, colors and type taken from tokens only, GPU→CPU backend probe with automatic fallback, and the screenshot/diff channel the visual reviews use).
  • Not done: the component library (buttons, dialogs, lists, menus, search, and the rest of the M3 set), page migration, and the i18n pass. Every page in the iced binary is a placeholder.
  • Slint stays until the flip: crates/app remains the reference implementation until the iced build passes equivalence acceptance; only then is unlucky-launcher-iced renamed to unlucky-launcher and the Slint crate retired.

Binaries in the workspace, so you can tell them apart:

Binary Crate State
unlucky-launcher crates/app (Slint) released in v0.1.0; still the usable GUI
unlucky-launcher-iced crates/app-iced (iced 0.14) under construction; skeleton only, not shipped
ull crates/cli built from the same tree at the same version; not in the v0.1.0 assets

Module map

Unlucky-Launcher (cargo workspace)
├── crates/core       # domain library: zero UI dependencies, eight modules
├── crates/agent      # AI agent: ToolSpec registry + built-in client + MCP server (one core, two shapes)
├── crates/design     # design tokens: real HCT color / type / shape / spacing / elevation / motion / icons
│                     #   / component metrics — zero UI dependencies, no third-party crates
├── crates/app        # Slint UI (bin `unlucky-launcher`): the released GUI, kept until equivalence acceptance
├── crates/app-iced   # next-generation iced UI (bin `unlucky-launcher-iced`): under construction
├── crates/cli        # CLI (bin `ull`): headless, zero UI
└── packaging         # single-file artifact matrix and release scripts

The eight modules of crates/core:

Module Responsibility
setting three data-directory modes, schema-based config, atomic writes, migrations
download multi-source health scoring, mirrors, chunked downloads, hash-while-downloading
game version / instance repository, snapshots and inheritance resolution
launch 10-stage launch pipeline, processes, JSONL event stream
auth Microsoft sign-in (OAuth 2.0 device code → Xbox Live → XSTS → Minecraft Services)
addon mod loader installation, modpacks, CurseForge / Modrinth
diagnose five signal collectors, YAML rule engine, hs_err parsing
platform OS abstraction: paths, processes, file locks, capability probing, runtime OS detection

Building

Prerequisites:

  • Rust stable (rust-toolchain.toml selects the toolchain automatically; the gates also need the rustfmt and clippy components)
  • Windows: MSVC toolchain (what CI uses) or MinGW-w64 (x86_64-pc-windows-gnu)
  • Linux: libxkbcommon-dev libfontconfig1-dev libgl1-mesa-dev libegl1-mesa-dev libwayland-dev libxcb1-dev — needed by both UI stacks (Slint's winit + femtovg, iced's winit + wgpu/tiny-skia)
cargo fmt --all --check                                # formatting
cargo clippy --workspace --all-targets -- -D warnings  # lints (zero-warning gate)
cargo test --workspace                                 # tests
cargo build --release                                  # binaries land in target/release/

What the build produces:

  • unlucky-launcher — the Slint UI (the released one)
  • unlucky-launcher-iced — the iced UI skeleton. The name is temporary: it can only become unlucky-launcher at the flip, because two crates in one workspace cannot emit the same binary name into the same target directory.
  • ull — the CLI

Rendering switches:

  • unlucky-launcher --software-renderer (equivalent to SLINT_BACKEND=winit-software) forces the CPU path on the Slint build
  • unlucky-launcher-iced --software-renderer forces tiny-skia (ICED_BACKEND=tiny-skia); --screenshot <png> writes one frame and exits, which is the acceptance channel
  • Both stacks fall back to the CPU path when no usable adapter is there: the Slint build through its own renderer fallback chain, the iced build through its explicit probe

Dependency license check (optional locally, required in CI): cargo deny check licenses bans sources.

CI gates

Every push to main and every pull request runs fmt / clippy (warnings are errors) / the full test suite, and the Linux headless render smoke is a hard gate on the same footing: a red result blocks the merge. The macOS runtime probe is not there yet — it only runs on a manual workflow_dispatch and its result is recorded, not enforced (continue-on-error), until the slot passes a first run on a real runner.

Workflow Content
.github/workflows/ci.yml fmt + clippy + test + release build (Windows / Linux matrix); Linux runtime smoke (Xvfb: renders one real frame, then asserts the PNG is not blank); macOS runtime probe (manual dispatch only)
.github/workflows/guards.yml zero-UI guard for crates/core (manifest plus cargo tree), 400-lines-per-file guard, cargo-deny license and source guard
.github/workflows/release.yml tag v* → per-slot builds → single-file artifacts + SHA256SUMS.txt → GitHub Release

Platform baseline

Minimum baseline: Windows 10; Windows 8.1 / 8 / 7 are not supported.

  • Windows 10/11 builds use the standard toolchain (MSVC / GNU), built the same way as upstream cargo
  • macOS 12+ (Apple Silicon and Intel) and Linux x64 / arm64 are supported build slots; on Linux, 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
  • Each platform runs its own test matrix; capability differences use feature gates with runtime probing.

License and acknowledgements

  • This project: Apache License 2.0, see LICENSE; third-party notices in NOTICE.
  • Slint (https://slint.dev), Royalty-Free 2.0: obligation for the Slint build that v0.1.0 ships — an AboutSlint widget on the about page (still outstanding) and, until it lands, the NOTICE file, this section and a "Made with Slint" note on the release page. The obligation is kept for as long as a Slint-linked binary ships.
  • iced (https://github.com/iced-rs/iced), MIT: the framework of the next-generation UI, together with winit and, through it, wgpu / tiny-skia (Apache-2.0 / MIT).
  • Google Material Color Utilities (Apache-2.0): the color tokens in crates/design are a Rust port of its HCT / ColorSpec2021 algorithms; details and the exact ported functions are listed in NOTICE.
  • Other major dependencies: rmcp and axum (Apache-2.0 / MIT) for the MCP server, tokio (MIT), reqwest with rustls (MIT / Apache-2.0), serde / serde_json (MIT / Apache-2.0), zip / flate2 / tar (MIT / Apache-2.0). The allow-list cargo-deny enforces is in deny.toml; GPL-family dependencies may not enter the main line.

Thanks to HMCL and PCL2 (both GPL-3.0). They have been with the vast majority of Minecraft players for years, and this project has benefited a great deal from their design choices and implementation details.

S
Description
A modern MC launcher.
Readme Apache-2.0
1.8 MiB
0 Stars 1 Watchers 0 Forks
Languages
Rust 93.4%
Slint 6.4%
Python 0.2%