2026-06-28 03:37:07 +08:00
|
|
|
|
import electron from 'electron';
|
2026-08-28 02:08:12 +08:00
|
|
|
|
import { launchGame, diagnoseVersion } from '../core/launcher';
|
|
|
|
|
|
import { resolveGamePath } from '../core/paths';
|
|
|
|
|
|
import { getConfig, type AppConfig } from '../config';
|
2026-06-28 03:37:07 +08:00
|
|
|
|
|
|
|
|
|
|
const { ipcMain } = electron;
|
|
|
|
|
|
|
|
|
|
|
|
interface WinRef {
|
|
|
|
|
|
mainWindow: electron.BrowserWindow | null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-28 02:08:12 +08:00
|
|
|
|
// 游戏窗口就绪后按配置处理启动器窗口(afterLaunch)
|
|
|
|
|
|
function applyAfterLaunch(config: AppConfig, win: WinRef): void {
|
|
|
|
|
|
const mode = config.advanced?.afterLaunch ?? 'close';
|
|
|
|
|
|
if (mode === 'close') {
|
|
|
|
|
|
win.mainWindow?.close();
|
|
|
|
|
|
} else if (mode === 'minimize') {
|
|
|
|
|
|
win.mainWindow?.minimize();
|
|
|
|
|
|
}
|
|
|
|
|
|
// 'keep' → 无操作
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-28 03:37:07 +08:00
|
|
|
|
export function registerLaunchHandlers(win: WinRef) {
|
|
|
|
|
|
ipcMain.handle('launch:launch', async (_event, payload: {
|
2026-08-28 02:08:12 +08:00
|
|
|
|
instanceName: string;
|
2026-06-28 03:37:07 +08:00
|
|
|
|
gamePath: string;
|
2026-08-28 02:08:12 +08:00
|
|
|
|
profile: { username: string; uuid: string; accessToken?: string };
|
2026-06-28 03:37:07 +08:00
|
|
|
|
server?: { ip: string; port?: number };
|
|
|
|
|
|
}) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const requestId = `launch-${Date.now()}`;
|
|
|
|
|
|
|
2026-08-28 02:08:12 +08:00
|
|
|
|
// 使用主进程内存配置(唯一权威,永远是最新值,无磁盘竞争)
|
|
|
|
|
|
const config = getConfig();
|
|
|
|
|
|
|
|
|
|
|
|
// 快速进入服务器:UI 显式传入优先,否则使用配置中保存的 advanced.server
|
|
|
|
|
|
const server = payload.server
|
|
|
|
|
|
?? (config.advanced?.server?.ip ? config.advanced.server : undefined);
|
|
|
|
|
|
|
|
|
|
|
|
const result = await launchGame({
|
|
|
|
|
|
config,
|
|
|
|
|
|
instanceName: payload.instanceName,
|
|
|
|
|
|
gamePath: resolveGamePath(payload.gamePath),
|
|
|
|
|
|
profile: payload.profile,
|
|
|
|
|
|
server,
|
2026-06-28 03:37:07 +08:00
|
|
|
|
onEvent: (event) => {
|
2026-08-28 02:08:12 +08:00
|
|
|
|
// afterLaunch 副作用:窗口就绪后关闭/最小化启动器
|
|
|
|
|
|
if (event.event === 'window-ready') {
|
|
|
|
|
|
applyAfterLaunch(config, win);
|
|
|
|
|
|
}
|
2026-06-28 03:37:07 +08:00
|
|
|
|
win.mainWindow?.webContents.send('launch:event', { requestId, ...event });
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return { success: true, data: { ...result, requestId }, error: null };
|
|
|
|
|
|
} catch (e: unknown) {
|
|
|
|
|
|
return { success: false, data: null, error: String(e) };
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
ipcMain.handle('launch:diagnose', async (_event, payload: { gamePath: string; version: string }) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const data = await diagnoseVersion(payload.gamePath, payload.version);
|
|
|
|
|
|
return { success: true, data, error: null };
|
|
|
|
|
|
} catch (e: unknown) {
|
|
|
|
|
|
return { success: false, data: null, error: String(e) };
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|