mirror of
https://github.com/dream-pep/koring-launcher.git
synced 2026-09-12 05:45:18 +08:00
7d8b7bd43355b4da0b48519cbcab97876301b10f
重构自动更新模块的版本比较逻辑,替换原有的semver比较规则为项目自定义的版本序:仅对比主版本号与构建号,忽略beta通道标记,确保同主版本下按构建号排序。新增correctAvailability方法在检查更新与下载前复核版本有效性,避免陈旧的更新信息导致误更新。调整GitHub release拉取逻辑,过滤掉草稿与不符合通道权限的预发布版本。新增src/resources目录下的运行时资源缓存管理系统,包含类型定义、图片解码管线与全局资源注册表,支持LRU内存逐出、引用计数与预算控制。新增系统内存监控的IPC接口与前端API,支持获取进程内存快照用于调试面板。更新auto-update-plan.md文档,补充本次版本判定修复的相关说明。
Koring Launcher
Minecraft launcher built with Electron + React 19 + TypeScript + Node.js (@xmcl).
Quick Start
pnpm install
pnpm dev # full app (frontend + electron)
pnpm dev:renderer # frontend only (vite, port 1420)
pnpm dev:main # electron main process only
Build
pnpm build # production build (vite + tsc)
pnpm dist:dev # dev icon + Windows installer
pnpm dist:beta # beta icon + Windows installer
pnpm dist:run # production icon + Windows installer
pnpm dist:mac # build macOS DMG
pnpm dist:linux # build Linux AppImage
Architecture
src/ Frontend (React 19 + Vite 7 + Tailwind v4 + shadcn/ui + Zustand)
electron/ Main process (Node.js/TypeScript, @xmcl/* packages)
public/ Static assets (icons, fonts, images)
build/ Build resources (generated, gitignored)
IPC Flow:
Frontend → ipcRenderer.invoke() → ipcMain.handle() → main process → webContents.send() → Frontend
Config storage (main-process authoritative):
Koring.yml— 打包后存app.getPath('userData')(%APPDATA%/Koring Launcher/),开发模式在项目根目录;旧版 exe 旁文件首次启动自动迁移- 主进程内存缓存为唯一权威:渲染进程通过
config:update提交补丁,主进程深度合并 → 300ms debounce 稀疏写盘 → 广播config:changed同步渲染端镜像 koring-auth.json/koring-crash.log与配置同策略(打包后 userData)
Project Structure
src/
├── api/ # Frontend API layer (IPC wrappers)
│ ├── ipc.ts # Core IPC utilities
│ ├── background.ts # Background control
│ ├── install.ts # Minecraft install
│ ├── launch.ts # Game launch
│ ├── auth.ts # Microsoft/offline auth
│ ├── mods.ts # Modrinth/CurseForge
│ └── instance.ts # Instance management
├── stores/ # Zustand state stores
├── components/
│ ├── background/ # Background layer (z-0)
│ ├── system/ # Title bar + window controls (z-100)
│ └── ui/ # shadcn/ui components
├── layouts/
│ └── RootLayout.tsx # Three-layer page structure
├── pages/
│ ├── Home.tsx # Main page
│ └── Debug.tsx # Debug tools
├── lib/
│ ├── mode.ts # Build mode constants (DEFAULT_BG, LOGO_SVG, APP_ICON)
│ └── utils.ts # cn() helper
└── App.tsx # Root component with state router
electron/
├── main.ts # Electron entry, window management, splash→main transition
├── preload.ts # Context bridge (window.electronAPI)
├── config.ts # YAML config management (main-process authoritative, debounce sparse save)
├── auth.ts # Auth data persistence
├── core/ # @xmcl/* integrations
│ ├── auth.ts # Microsoft OAuth, Xbox Live, MC auth
│ ├── installer.ts # @xmcl/installer
│ ├── launcher.ts # Unified game launcher (@xmcl/core launch + config-driven)
│ ├── launch-options.ts # Config → LaunchOption mapping (parseArgs/buildLaunchOptions/resolveJavaPath)
│ ├── modrinth.ts # Modrinth/CurseForge API
│ └── instance.ts # Instance management
├── handlers/ # IPC handlers
│ ├── config.ts # Config load/save/update (config:get/update/save + config:changed broadcast)
│ ├── auth.ts # Auth operations
│ ├── install.ts # Install operations
│ ├── launch.ts # Unified game launch (launch:launch / launch:diagnose + afterLaunch)
│ ├── java.ts # Java detection (java:scan / java:resolve)
│ ├── mods.ts # Mod operations
│ ├── instance.ts # Instance operations
│ ├── background.ts # Background operations
│ ├── task.ts # Task system
│ ├── system.ts # System info
│ └── window.ts # Window controls + splash management
└── types/
└── electron.d.ts # TypeScript declarations
Three-Layer Page Structure
┌──────────────────────────────────────┐
│ z-index: 100 System Layer │ pointer-events: none
│ ┌──────────────────────────────┐ │
│ │ TitleBar (frosted glass) │ │ pointer-events: auto
│ │ WindowControls (25px btns) │ │
│ └──────────────────────────────┘ │
├──────────────────────────────────────┤
│ z-index: 1 Content Layer │ pointer-events: auto
│ All page content │
├──────────────────────────────────────┤
│ z-index: 0 Background Layer │ pointer-events: none
│ Image / color / gradient / blur │
└──────────────────────────────────────┘
Splash Screen
- Standalone HTML/CSS (
splash.html), no React/Vite dependency - Loads instantly while Vite dev server starts
- Window: 480×320, no decorations, transparent, locked size
- Auto-adapts to system dark mode (
prefers-color-scheme) - Logo:
filter: invert(1)in dark mode - Startup: splash shows first → main loads behind → transition after
ready-to-show+ 1.5s minimum
Icon System
Three icon variants in public/icons/:
public/icons/
dev/icon.ico, icon.png # Development
beta/icon.ico, icon.png # Testing
run/icon.ico, icon.png # Production release
Build-time switching:
pnpm icon:dev # copies public/icons/dev/ → build/
pnpm icon:beta # copies public/icons/beta/ → build/
pnpm icon:run # copies public/icons/run/ → build/
electron-builder.yml reads icons from build/ (buildResources: build).
Frontend usage:
import { APP_ICON, DEFAULT_BG, LOGO_SVG, BUILD_MODE, isDev } from "@/lib/mode";
<img src={APP_ICON} />
<img src={LOGO_SVG} />
<img src={DEFAULT_BG} />
{isDev && <span>Dev Mode</span>}
IPC Handlers
config:get/config:update/config:save/config:changed— 配置读写(主进程权威:update 深度合并 + debounce 稀疏写盘 + 广播)auth:*— Microsoft OAuth, offline logininstall:*— Minecraft install, mod loader, version listslaunch:launch/launch:diagnose— 统一游戏启动:主进程读取权威配置自动应用 Java/内存/GC/JVM/游戏参数/窗口/启动前命令,事件经launch:event推送,window-ready 时按afterLaunch处理启动器窗口java:scan/java:resolve— Java 环境检测 / 路径校验mods:*— Modrinth/CurseForge search, installinstance:*— Instance CRUD(安装/导入/诊断;启动统一走launch:launch)background:*— Background image/color/blur/animation/themetask:*— Task system progresssystem:*— System infowindow:*— Minimize/maximize/close + splash managementdialog:*— File picker
Key Gotchas
- @xmcl packages run in main process:
@xmcl/core,@xmcl/installerrequirefs/child_process. All run in Electron main process. - Path alias:
@/maps tosrc/. - Window dragging: Use CSS
WebkitAppRegion: "drag"as inline style (Electron only respects CSS property, not HTML attributes). - Transparent windows:
transparent: true+frame: falsein BrowserWindow options. - Mutable win ref:
electron/main.tsuses a mutablewinobject — all handlers readwin.mainWindowat runtime (not captured at registration time). - Asset paths: Use
import.meta.env.BASE_URLprefix for public assets (e.g.,${import.meta.env.BASE_URL}background.png). Absolute paths like/background.pngbreak in packaged app. - Config: YAML format (
Koring.yml). 打包后存app.getPath('userData')(开发模式在项目根目录);主进程内存缓存为唯一权威,渲染进程经config:update提交、config:changed同步,不在渲染端直接写盘。Sparse save(只写非默认值)。 - Auth: JSON file (
koring-auth.json),打包后存 userData(与配置同策略)。 - Launch is config-driven:
launch:launch由主进程读取权威配置映射为@xmcl/core的LaunchOption(buildLaunchOptions),前端只传实例名 + 游戏根目录 + 账户档案。 - HeroUI 3 基于 react-aria:Switch / RadioGroup 等使用
onChange(不是onValueChange),onValueChange在 HeroUI 3 中不存在且静默失效。 - 设置子页面统一原语:
src/components/setting/(SettingCard/SettingRow/SettingBadge/SettingListItem/controls.tsx +fieldCls),一套样式组合;Radio 必须显式渲染<Radio.Control><Radio.Indicator /></Radio.Control>才有圆点;HeroUI field 默认边框宽度为 0,输入框需叠加fieldCls。 - 游戏目录导入:版本从当前扫描目录导入(
sourceGamePath),实例建在主库;主目录变更自动重扫;批量导入幂等(已存在跳过);相对gameDir(默认.minecraft)由主进程resolveGamePath按 exe 目录/项目根归一化。 - 设置页结构(参考 PCL2):通用(主页/Koring 账户/关于/版权)与其他(服务与反馈/赞助/开发者)保留;游戏组(账户·离线登录、Java、目录、高级·含快速进入服务器)、个性化组(主题背景/主界面/语言/辅助)、网络组(下载/安全识别)已对接设置接口;以太/陶瓦联机页暂为占位。新增配置段:
app.language(语言偏好)、ui.showInstanceTitle/showTaskButton(主界面元素)、advanced.server(快速进入服务器,启动自动加入)。 - 离线账号登录:
auth:offline-login处理器生成离线 UUID(MD5(OfflinePlayer:用户名));微软登录 UI 标注"开发中"。
Tech Stack
| Layer | Technology |
|---|---|
| Frontend | React 19, Vite 7, Tailwind CSS v4, shadcn/ui, Zustand |
| Main Process | Node.js, TypeScript, @xmcl/* packages |
| Build | pnpm, Vite, electron-builder |
Description
A modern Minecraft launcher for Windows · 基于 Electron + React 的现代化 Minecraft 启动器
https://www.koring.space/launcher
8.8 MiB
Languages
TypeScript
95.5%
JavaScript
2.2%
CSS
1.4%
PowerShell
0.4%
NSIS
0.3%
Other
0.2%