import ServerEnvironment, { ServerTarget } from "./ServerEnvironment"; import ClientUpdate from "./ClientUpdate"; import Utils from "../Pay/Utils"; import DailyTaskProgressTracker from "../Task/DailyTaskProgressTracker"; import { MiniGameSdk } from "../../Sdk/MiniGameSdk"; declare const wx: any; /** Home-only, full-process switch. Never changes the active transport or storage scope. */ export default class ServerSwitch { static inProgress = false; private static confirming = false; private static isBrowser(): boolean { return typeof wx === "undefined" && cc.sys.isBrowser; } private static modal(options: any): void { if (!this.isBrowser()) { wx.showModal(options); return; } try { const confirm = options.showCancel === false ? (window.alert(options.title + "\n" + options.content), true) : window.confirm(options.title + "\n" + options.content); if (options.success) options.success({ confirm }); } finally { if (options.complete) options.complete(); } } private static showLoading(title: string): void { if (!this.isBrowser()) wx.showLoading({ title, mask: true }); } private static restart(failed: () => void): void { if (!this.isBrowser()) { MiniGameSdk.API.reboot(undefined, failed); return; } try { window.location.reload(); } catch (_) { failed(); } } static choose(target: ServerTarget, refresh: () => void): void { if (!ServerEnvironment.canSwitch() || this.inProgress || this.confirming || ClientUpdate.blocked || cc.director.getScene()?.name !== "HomeScene") return; if (target === ServerEnvironment.current() && target === ServerEnvironment.next()) return; const cancelPending = target === ServerEnvironment.current(); this.confirming = true; this.modal({ title: cancelPending ? "取消服务器切换" : "切换服务器", content: cancelPending ? "取消待生效的切换,继续使用当前服务器?" : `将切换到${target === "test" ? "测试服" : "正式服"}并重启游戏,是否继续?`, confirmText: cancelPending ? "确认取消" : "重启切换", success: result => { if (!result.confirm) return; if (cancelPending) { try { ServerEnvironment.saveNext(target); refresh(); } catch (_) { this.modal({ title: "保存失败", content: "服务器选择保存失败,请重试", showCancel: false }); } } else { this.perform(target, refresh); } }, complete: () => { this.confirming = false; }, }); } private static async perform(target: ServerTarget, refresh: () => void): Promise { const scene = cc.director.getScene(); if (scene?.name !== "HomeScene" || this.inProgress || ClientUpdate.blocked) return; this.inProgress = true; let saved = false; let restartTimer: any = null; scene.pauseSystemEvents(true); try { this.showLoading("正在保存进度"); DailyTaskProgressTracker.stopOnline(); DailyTaskProgressTracker.flushNow(); await Utils.prepareServerSwitch(); if (cc.director.getScene() !== scene) throw new Error("页面已变化,请返回首页重试"); ServerEnvironment.saveNext(target); saved = true; refresh(); this.showLoading("正在重启"); // A real restart destroys this process. If it stays alive, keep the old session usable. await new Promise((_, reject) => { const failed = () => reject(new Error("自动重启失败")); restartTimer = setTimeout(failed, 8000); this.restart(failed); }); } catch (error) { clearTimeout(restartTimer); Utils.cancelServerSwitch(); this.inProgress = false; if (ClientUpdate.blocked) { ClientUpdate.onShow(); return; } if (!this.isBrowser()) wx.hideLoading(); if (cc.isValid(scene)) scene.resumeSystemEvents(true); cc.game.resume(); cc.audioEngine.resumeAll(); DailyTaskProgressTracker.startOnline(); refresh(); this.modal({ title: saved ? "请重启游戏" : "暂未切换", content: saved ? "选择已保存,完整重启后生效。当前仍连接原服务器,请重试重启或退出后重新进入。" : (error?.message || "存档保存失败,请稍后重试"), confirmText: saved ? "重试重启" : "知道了", cancelText: "稍后重启", showCancel: saved, success: result => { if (saved && result.confirm) this.perform(target, refresh); }, }); } } }