diff --git a/assets/script/game/common/GameDataSync.ts b/assets/script/game/common/GameDataSync.ts index fa097085..27d71f90 100644 --- a/assets/script/game/common/GameDataSync.ts +++ b/assets/script/game/common/GameDataSync.ts @@ -93,49 +93,60 @@ export class GameDataSync { }); } + /** + * 将获取到的云端数据与本地对比并合并 + */ + public syncWithCloudData(cloudData: CloudData | null) { + const localData = this.loadFromLocal(); + + let cloudTs = cloudData?.data?.timestamp || 0; + let localTs = localData?.timestamp || 0; + + if (!localData || cloudTs > localTs) { + mLogger.log(this.debugMode, 'GameDataSync', `[GameDataSync]: 云端数据较新 (Cloud: ${cloudTs} > Local: ${localTs}), 执行覆盖。`); + if (cloudData) { + smc.overrideLocalDataWithRemote(cloudData); + this.saveToLocal(); // 同步到本地 + } + } else { + mLogger.log(this.debugMode, 'GameDataSync', `[GameDataSync]: 本地数据较新 (Local: ${localTs} >= Cloud: ${cloudTs}), 使用本地数据,触发强制云同步。`); + smc.overrideLocalDataWithRemote({ data: localData }); + // 本地数据较新,需要强制推送到云端以保证多端一致 + this._localDataDirty = true; + this.executeCloudSync(); + } + } + public getCloudData() { const localData = this.loadFromLocal(); // 未登录微信云端前,先用本地数据顶上(让玩家秒进游戏) if (localData && !this.isWxClient()) { smc.overrideLocalDataWithRemote({ data: localData }); - return; + return Promise.resolve(false); } - WxCloudApi.get().then(async (result) => { + return WxCloudApi.get().then(async (result) => { if(result.result.code === 200) { let cloudData = result.result.data as CloudData; mLogger.log(this.debugMode, 'GameDataSync', `[GameDataSync]: 获取游戏云端数据成功:`, cloudData); - // 冲突解决:基于时间戳比较(云端时间戳 > 本地时间戳 则覆盖) - let cloudTs = cloudData?.data?.timestamp || 0; - let localTs = localData?.timestamp || 0; + this.syncWithCloudData(cloudData); - if (!localData || cloudTs > localTs) { - mLogger.log(this.debugMode, 'GameDataSync', `[GameDataSync]: 云端数据更新 (Cloud: ${cloudTs} > Local: ${localTs}), 执行覆盖。`); - smc.overrideLocalDataWithRemote(cloudData); - this.saveToLocal(); // 同步到本地 - } else { - mLogger.log(this.debugMode, 'GameDataSync', `[GameDataSync]: 本地数据更新 (Local: ${localTs} >= Cloud: ${cloudTs}), 使用本地数据,触发强制云同步。`); - smc.overrideLocalDataWithRemote({ data: localData }); - // 本地数据较新,需要强制推送到云端以保证多端一致 - this._localDataDirty = true; - this.executeCloudSync(); - } - - return true + return true; } else { mLogger.warn(this.debugMode, 'GameDataSync', `[GameDataSync]: 获取游戏云端数据失败,使用本地缓存兜底。`); if (localData) { smc.overrideLocalDataWithRemote({ data: localData }); } - return false + return false; } }).catch((error) => { mLogger.error(this.debugMode, 'GameDataSync', `[GameDataSync]: 获取游戏云端数据异常:`, error); if (localData) { smc.overrideLocalDataWithRemote({ data: localData }); } + return false; }); } } diff --git a/assets/script/game/initialize/Initialize.ts b/assets/script/game/initialize/Initialize.ts index 1cfdfad1..93981bdf 100644 --- a/assets/script/game/initialize/Initialize.ts +++ b/assets/script/game/initialize/Initialize.ts @@ -14,6 +14,7 @@ import { LoadingViewComp } from "./view/LoadingViewComp"; import { smc } from "../common/SingletonModuleComp"; import { WxCloudApi } from "../wx_clound_client_api/WxCloudApi"; import { mLogger } from "../common/Logger"; +import { gameDataSync } from "../common/GameDataSync"; /** * 游戏进入初始化模块 @@ -85,13 +86,6 @@ export class Initialize extends ecs.Entity { oops.res.loadDir("common", next); }); } - /** - * 判断是否为微信客户端 - */ - private isWxClient(): boolean { - // 检查是否存在微信API - return typeof wx !== 'undefined' && typeof (wx as any).getSystemInfoSync === 'function'; - } /** * 统一的游戏数据加载流程 @@ -102,7 +96,7 @@ export class Initialize extends ecs.Entity { try { mLogger.log(this.debugMode, 'Initialize', "[Initialize]: 开始统一数据加载流程..."); - if (this.isWxClient()) { + if (gameDataSync.isWxClient()) { // 微信客户端:加载云端数据 mLogger.log(this.debugMode, 'Initialize', "[Initialize]: 检测到微信客户端,使用云端数据"); await this.loadFromCloud(); @@ -130,36 +124,33 @@ export class Initialize extends ecs.Entity { const loginResult = await WxCloudApi.login(); const response = loginResult.result; - if (loginResult.result.code === 200) { + if (response && response.code === 200) { mLogger.log(this.debugMode, 'Initialize', "[Initialize]: 云端登录成功"); - smc.updateCloudData() - const cloudData = loginResult.result.data; - try { - // 直接覆盖基础游戏数据 - if (cloudData.openid) { - smc.openid=cloudData.openid - } - // 直接覆盖出战英雄配置 - if (cloudData.game_data) { - let gameDate=cloudData.game_data - if( gameDate.gold ) smc.vmdata.gold=gameDate.gold - if( gameDate.heros ) smc.heros=gameDate.heros - if( gameDate.fight_hero ) smc.fight_hero=gameDate.fight_hero - } - - } catch (error) { - mLogger.log(this.debugMode, 'Initialize', `[SMC]: 数据覆盖失败:`, error); + + const cloudData = response.data; + + if (cloudData && cloudData.openid) { + smc.openid = cloudData.openid; } + + // 将 login 获取的 game_data 封装为统一下发格式,交给 gameDataSync 对比与合并 + const formattedCloudData = { + openid: cloudData?.openid || '', + data: cloudData?.game_data || {} + }; + + gameDataSync.syncWithCloudData(formattedCloudData); } else { - mLogger.log(this.debugMode, 'Initialize', "[Initialize]: 云端登录失败:", response.msg); - // 登录失败时使用本地数据 游戏需要退出 - mLogger.log(this.debugMode, 'Initialize', "[Initialize]: 云端登录失败:", response.msg); + mLogger.log(this.debugMode, 'Initialize', "[Initialize]: 云端登录失败:", response?.msg); + // 登录失败时使用本地数据 + gameDataSync.syncWithCloudData(null); } } catch (error) { mLogger.log(this.debugMode, 'Initialize', "[Initialize]: 云端数据加载异常:", error); - // 异常时使用本地数据 游戏需要退出 + // 异常时使用本地数据兜底 + gameDataSync.syncWithCloudData(null); } } @@ -168,10 +159,8 @@ export class Initialize extends ecs.Entity { */ private async loadFromLocalDebug() { try { - // 使用本地调试API,模拟云端接口 - // 用本地调试数据覆盖客户端数据 - + gameDataSync.syncWithCloudData(null); } catch (error) { mLogger.log(this.debugMode, 'Initialize', "[Initialize]: 本地调试数据加载异常:", error); }