feat(数据同步): 重构云端数据同步机制,引入防抖与本地缓存
- 新增 GameDataSync 类,封装数据同步逻辑,支持防抖与时间戳冲突解决 - 重构 SingletonModuleComp 的云端同步方法,统一调用 GameDataSync - 优化 TalentsComp 天赋升级流程,使用新的同步机制 - 添加本地缓存支持,提升离线体验与数据恢复能力
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { sys } from "cc";
|
||||
import { VM } from "../../../../extensions/oops-plugin-framework/assets/libs/model-view/ViewModel";
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { Initialize } from "../initialize/Initialize";
|
||||
@@ -8,15 +9,17 @@ import { GameEvent } from "./config/GameEvent";
|
||||
import { GameScoreStats } from "./config/HeroAttrs";
|
||||
import { mLogger } from "./Logger";
|
||||
import { TalentType } from "./config/TalentSet";
|
||||
import { gameDataSync } from "./GameDataSync";
|
||||
|
||||
/**
|
||||
* 用远程数据覆盖本地数据(统一方法)
|
||||
* @param remoteData 远程数据(云端或本地调试)
|
||||
*/
|
||||
interface GameDate{
|
||||
export interface GameDate{
|
||||
gold:number,
|
||||
heros:any,
|
||||
fight_hero:number,
|
||||
timestamp?: number, // 用于比对本地与云端数据的最新状态
|
||||
collection?: {
|
||||
talents: Partial<Record<TalentType, number>>,
|
||||
player_level: number,
|
||||
@@ -26,7 +29,7 @@ interface GameDate{
|
||||
friend?: {uuid:0,count:0},
|
||||
}
|
||||
}
|
||||
interface CloudData {
|
||||
export interface CloudData {
|
||||
openid: string;
|
||||
data: GameDate;
|
||||
}
|
||||
@@ -212,9 +215,8 @@ export class SingletonModuleComp extends ecs.Comp {
|
||||
/**
|
||||
* 判断是否为微信客户端
|
||||
*/
|
||||
private isWxClient(): boolean {
|
||||
// 检查是否存在微信API
|
||||
return typeof wx !== 'undefined' && typeof (wx as any).getSystemInfoSync === 'function';
|
||||
isWxClient(): boolean {
|
||||
return gameDataSync.isWxClient();
|
||||
}
|
||||
|
||||
finishGuide(index:number){
|
||||
@@ -223,97 +225,72 @@ export class SingletonModuleComp extends ecs.Comp {
|
||||
}
|
||||
|
||||
updateCloudData(){
|
||||
|
||||
let gemeDate=this.getGameDate()
|
||||
WxCloudApi.save(gemeDate).then((result) => {
|
||||
mLogger.log(this.debugMode, 'SMC', '云端保存')
|
||||
if(result.result.code === 200) {
|
||||
mLogger.log(this.debugMode, 'SMC', "保存成功",result.result)
|
||||
return true
|
||||
} else {
|
||||
mLogger.warn(this.debugMode, 'SMC', `[SMC]: 游戏数据增加失败: ${result.result.msg}`);
|
||||
return false
|
||||
}
|
||||
}).catch((error) => {
|
||||
mLogger.error(this.debugMode, 'SMC', `[SMC]: 增加游戏数据异常:`, error);
|
||||
return false
|
||||
});
|
||||
return true
|
||||
return gameDataSync.updateCloudData();
|
||||
}
|
||||
|
||||
getCloudData(){
|
||||
WxCloudApi.get().then(async (result) => {
|
||||
if(result.result.code === 200) {
|
||||
let data=result.result.data
|
||||
mLogger.log(this.debugMode, 'SMC', `[SMC]: 获取游戏数据成功:`, result.result);
|
||||
this.overrideLocalDataWithRemote(data)
|
||||
return true
|
||||
} else {
|
||||
mLogger.warn(this.debugMode, 'SMC', `[SMC]: 游戏数据增加失败`);
|
||||
return false
|
||||
}
|
||||
}).catch((error) => {
|
||||
mLogger.error(this.debugMode, 'SMC', `[SMC]: 获取游戏数据异常:`, error);
|
||||
});
|
||||
gameDataSync.getCloudData();
|
||||
}
|
||||
public async overrideLocalDataWithRemote(CloudData) {
|
||||
public async overrideLocalDataWithRemote(cloudData: any) {
|
||||
try {
|
||||
// 直接覆盖基础游戏数据
|
||||
if (CloudData.openid) {
|
||||
this.openid=CloudData.openid
|
||||
if (cloudData.openid) {
|
||||
this.openid = cloudData.openid;
|
||||
}
|
||||
// 直接覆盖出战英雄配置
|
||||
if (CloudData.data) {
|
||||
if(CloudData.data.gold) this.vmdata.gold=CloudData.data.gold
|
||||
if(CloudData.data.heros) this.heros=CloudData.data.heros
|
||||
if(CloudData.data.fight_hero) this.fight_hero=CloudData.data.fight_hero
|
||||
if (cloudData.data) {
|
||||
const data = cloudData.data;
|
||||
// 同步金币
|
||||
if (data.gold !== undefined) {
|
||||
this.vmdata.gold = data.gold;
|
||||
}
|
||||
// 同步英雄
|
||||
if (data.heros && Array.isArray(data.heros)) {
|
||||
this.heros = data.heros;
|
||||
}
|
||||
// 同步出战英雄
|
||||
if (data.fight_hero !== undefined) {
|
||||
this.fight_hero = data.fight_hero;
|
||||
}
|
||||
// 恢复收集记录
|
||||
if(CloudData.data.collection) {
|
||||
this.collection = CloudData.data.collection;
|
||||
if (data.collection) {
|
||||
const remoteCol = data.collection;
|
||||
if (remoteCol.talents) this.collection.talents = remoteCol.talents;
|
||||
if (typeof remoteCol.player_level === 'number') this.collection.player_level = remoteCol.player_level;
|
||||
if (typeof remoteCol.player_exp === 'number') this.collection.player_exp = remoteCol.player_exp;
|
||||
if (typeof remoteCol.talent_points === 'number') this.collection.talent_points = remoteCol.talent_points;
|
||||
}
|
||||
}
|
||||
|
||||
// 触发UI更新
|
||||
oops.message.dispatchEvent(GameEvent.GOLD_UPDATE);
|
||||
|
||||
} catch (error) {
|
||||
mLogger.error(this.debugMode, 'SMC', `[SMC]: 数据覆盖失败:`, error);
|
||||
}
|
||||
}
|
||||
getGameDate(){
|
||||
return {
|
||||
gold:this.vmdata.gold,
|
||||
heros:this.heros,
|
||||
fight_hero:this.fight_hero,
|
||||
collection: this.collection
|
||||
}
|
||||
let data: GameDate = {
|
||||
gold: this.vmdata.gold,
|
||||
heros: this.heros,
|
||||
fight_hero: this.fight_hero,
|
||||
collection: this.collection,
|
||||
timestamp: Date.now() // 每次获取当前数据结构时都附带最新的时间戳
|
||||
};
|
||||
return data;
|
||||
}
|
||||
addHero(hero_uuid:number){
|
||||
if(this.heros.indexOf(hero_uuid)==-1){
|
||||
this.heros.push(hero_uuid)
|
||||
gameDataSync.markDataDirty();
|
||||
}
|
||||
if(this.isWxClient()){
|
||||
let res = this.updateCloudData()
|
||||
if (res){
|
||||
return true
|
||||
}else{
|
||||
// 同步不成功,删除uuid
|
||||
this.heros.splice(this.heros.indexOf(hero_uuid), 1);
|
||||
oops.gui.toast("数据同步失败,已回滚操作");
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
updateGold(gold:number, is_sync: boolean = true){
|
||||
this.vmdata.gold += gold;
|
||||
if(this.isWxClient() && is_sync){
|
||||
let res = this.updateCloudData()
|
||||
if (res){
|
||||
oops.message.dispatchEvent(GameEvent.GOLD_UPDATE)
|
||||
return true
|
||||
}else{
|
||||
this.vmdata.gold -= gold
|
||||
return false
|
||||
}
|
||||
if (is_sync) {
|
||||
gameDataSync.markDataDirty();
|
||||
}
|
||||
oops.message.dispatchEvent(GameEvent.GOLD_UPDATE)
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user