2026-06-19 23:50:40 +08:00
|
|
|
|
# koring-launcher
|
|
|
|
|
|
|
2026-06-28 03:37:07 +08:00
|
|
|
|
Minecraft launcher built with Electron + React 19 + TypeScript + Node.js (@xmcl).
|
2026-06-19 23:50:40 +08:00
|
|
|
|
|
|
|
|
|
|
## Quick commands
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-06-28 03:37:07 +08:00
|
|
|
|
pnpm dev # full app dev (renderer + main process)
|
|
|
|
|
|
pnpm dev:renderer # frontend only (vite, port 1420)
|
|
|
|
|
|
pnpm dev:main # electron main process only
|
|
|
|
|
|
pnpm build # production build (vite + tsc)
|
2026-07-11 23:33:44 +08:00
|
|
|
|
pnpm dist:dev # dev icon + Windows installer
|
|
|
|
|
|
pnpm dist:beta # beta icon + Windows installer
|
|
|
|
|
|
pnpm dist:run # production icon + Windows installer
|
2026-06-19 23:50:40 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Architecture
|
|
|
|
|
|
|
|
|
|
|
|
- **Frontend** (`src/`): React 19 + Vite 7 + Tailwind v4 + shadcn/ui + Zustand stores
|
2026-06-28 03:37:07 +08:00
|
|
|
|
- **Main Process** (`electron/`): Node.js/TypeScript, manages windows, IPC handlers, @xmcl/* packages
|
2026-07-11 23:33:44 +08:00
|
|
|
|
- **Icon System** (`public/icons/{dev,beta,run}/`): Mode-specific icons, copied to `build/` at build time
|
2026-06-28 03:37:07 +08:00
|
|
|
|
- IPC: Frontend → `ipcRenderer.invoke()` → `ipcMain.handle()` → main process → `webContents.send()` → Frontend
|
2026-06-19 23:50:40 +08:00
|
|
|
|
|
|
|
|
|
|
## Key gotchas
|
|
|
|
|
|
|
2026-06-28 03:37:07 +08:00
|
|
|
|
- **Electron main process**: `electron/main.ts` is the entry point. All @xmcl/* packages run here.
|
|
|
|
|
|
- **Preload script**: `electron/preload.ts` exposes `window.electronAPI` via context bridge.
|
|
|
|
|
|
- **IPC handlers**: All handlers are in `electron/handlers/` directory.
|
2026-07-11 23:33:44 +08:00
|
|
|
|
- **Mutable win ref**: `electron/main.ts` uses a mutable `win` object — handlers read `win.mainWindow` at runtime, not at registration time.
|
2026-09-04 19:34:58 +08:00
|
|
|
|
- **Config**: YAML format (`Koring.yml`) stored in userData (packaged) / project root (dev). Sparse save (only non-default values). ⚠️ 不可放安装目录:NSIS 重装/升级会经旧卸载器删除整个安装目录。
|
|
|
|
|
|
- **Auth**: JSON file (`koring-auth.json`) stored in userData (packaged) / project root (dev).
|
2026-06-19 23:50:40 +08:00
|
|
|
|
- **Path alias**: `@/` maps to `src/` (configured in `vite.config.ts` and `tsconfig.json`).
|
2026-06-28 03:37:07 +08:00
|
|
|
|
- **Dev mode**: Vite runs on port 1420, Electron loads from localhost.
|
2026-07-11 23:33:44 +08:00
|
|
|
|
- **Asset paths**: Use `import.meta.env.BASE_URL` prefix for public assets. Absolute paths break in packaged app.
|
2026-06-19 23:50:40 +08:00
|
|
|
|
|
|
|
|
|
|
## Build & bundle
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-06-28 03:37:07 +08:00
|
|
|
|
pnpm build # Vite build + TypeScript compile
|
2026-07-11 23:33:44 +08:00
|
|
|
|
pnpm dist:dev # switch-icon dev + electron-builder Windows installer
|
|
|
|
|
|
pnpm dist:beta # switch-icon beta + electron-builder Windows installer
|
|
|
|
|
|
pnpm dist:run # switch-icon run + electron-builder Windows installer
|
2026-06-19 23:50:40 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-07-11 23:33:44 +08:00
|
|
|
|
Each `dist:*` command runs: `pnpm build` → `pnpm icon:{mode}` → `electron-builder --win`
|
|
|
|
|
|
|
|
|
|
|
|
## Icon switching
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
public/icons/
|
|
|
|
|
|
dev/icon.ico, icon.png
|
|
|
|
|
|
beta/icon.ico, icon.png
|
|
|
|
|
|
run/icon.ico, icon.png
|
|
|
|
|
|
|
|
|
|
|
|
build/ ← generated by switch-icon.js (gitignored)
|
|
|
|
|
|
icon.ico
|
|
|
|
|
|
icon.png
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`electron-builder.yml` uses `buildResources: build` to read icons from `build/`.
|
|
|
|
|
|
|
2026-06-28 03:37:07 +08:00
|
|
|
|
## Electron notes
|
2026-06-19 23:50:40 +08:00
|
|
|
|
|
2026-07-11 23:33:44 +08:00
|
|
|
|
- `electron/main.ts`: App entry, window management, splash→main transition (ready-to-show + 1.5s min)
|
2026-06-28 03:37:07 +08:00
|
|
|
|
- `electron/preload.ts`: Context bridge for secure IPC
|
|
|
|
|
|
- `electron/config.ts`: YAML config management (sparse save)
|
|
|
|
|
|
- `electron/auth.ts`: Auth data persistence (JSON file)
|
|
|
|
|
|
- `electron/core/`: @xmcl/* integrations (auth, installer, launcher, modrinth, instance)
|
2026-09-04 19:34:58 +08:00
|
|
|
|
- `electron/core/background-image.ts`: 背景图处理服务 —— 自选壁纸复制到 userData 并按屏幕尺寸降采样/重编码**落盘**,配置文件只存**文件路径**(不使用 BASE64)
|
|
|
|
|
|
- `electron/resource-protocol.ts`: `koring-res://` 特权自定义协议 —— 渲染进程以「资源引用」流式读取本地壁纸;仅服务 userData 内 `background-custom*` 白名单文件(realpath 二次校验,防目录穿越)
|
2026-06-28 03:37:07 +08:00
|
|
|
|
- `electron/handlers/`: IPC handlers (config, auth, install, launch, mods, instance, background, task, system, window)
|
2026-06-19 23:50:40 +08:00
|
|
|
|
|
2026-06-28 03:37:07 +08:00
|
|
|
|
## Frontend notes
|
|
|
|
|
|
|
|
|
|
|
|
- `src/api/ipc.ts`: Core IPC utilities (invoke, onIpcEvent)
|
|
|
|
|
|
- `src/api/*.ts`: API modules wrapping IPC calls
|
|
|
|
|
|
- `src/stores/`: Zustand state management
|
2026-09-04 18:56:43 +08:00
|
|
|
|
- `src/resources/`: 启动器程序本体「资源管理」子系统(与游戏无关):
|
|
|
|
|
|
- `registry.ts` 资源注册表服务(acquire/release、引用计数、预算 + LRU 逐出、onRelease 释放回调)
|
|
|
|
|
|
- `store.ts` 注册表 → zustand 镜像(调试面板消费)
|
|
|
|
|
|
- `image.ts` 图片解码管线(按显示尺寸降采样)、`hooks.ts`/`ManagedImage.tsx` 复用组件(供列表缩略图)
|
2026-09-04 19:34:58 +08:00
|
|
|
|
- 当前接线点:`BackgroundLayer` 把当前背景(dataURL 或 koring-res 引用)登记为 `background` 类资源;自选壁纸经 `background:import` 落盘、配置存文件路径、渲染端经 `background:resolve` 拿 `koring-res://` 引用(全程无 base64)
|
2026-09-04 18:56:43 +08:00
|
|
|
|
- 监控入口:debug 页「资源与内存」(`debug-resource`)
|
2026-06-28 03:37:07 +08:00
|
|
|
|
- `src/hooks/useTheme.ts`: Dark mode sync with Electron theme
|
2026-07-11 23:33:44 +08:00
|
|
|
|
- `src/components/system/WindowControls.tsx`: Custom window controls (min/max/close), uses `<button>` with `WebkitAppRegion: "no-drag"`
|
|
|
|
|
|
- `src/components/system/TitleBar.tsx`: Custom title bar with navigation, uses `WebkitAppRegion: "drag"`
|
|
|
|
|
|
- `src/lib/mode.ts`: Build mode constants (`DEFAULT_BG`, `LOGO_SVG`, `APP_ICON`, `BUILD_MODE`)
|