MatchMaster/assets/seven_day_gift/SevenDayGiftReward.ts
2026-09-10 10:43:30 +08:00

159 lines
6.2 KiB
TypeScript

import SevenDayGiftApi, { SevenDayRewardReceipt, SevenDayRewardItem } from "./SevenDayGiftApi";
const PROCESSED_CLAIMS_KEY = "seven_day_gift_processed_claims_v1";
/** 奖励到账与本地防重,只处理资产,不负责播放动画。 */
export default class SevenDayGiftReward {
// 汇总奖励并同步资产,全部成功后才写入本地完成记录。
public static grant(result: SevenDayRewardReceipt, callback: (success: boolean, message?: string) => void) {
if (!result || !result.claimId || !Array.isArray(result.rewards)) {
callback(false, "服务器奖励数据不完整");
return;
}
if (this.hasProcessed(result.claimId)) {
callback(true);
return;
}
let coin = 0;
let hammer = 0;
let freeze = 0;
let magic = 0;
let infiniteHealth = 0;
const cats: number[] = [];
result.rewards.forEach((item: SevenDayRewardItem) => {
const rewardAmount = item.count !== undefined ? item.count : item.amount;
const amount = Math.max(0, Number(rewardAmount) || 0);
switch (item.type) {
case "coin": coin += amount; break;
case "hammer": hammer += amount; break;
case "freeze": freeze += amount; break;
case "magic_wand": magic += amount; break;
case "infinite_health": infiniteHealth += amount; break;
case "cat_skin":
if (item.itemId !== undefined) cats.push(Number(item.itemId));
break;
}
});
this.grantCommonRewards(coin, hammer, freeze, magic, infiniteHealth, (commonSuccess: boolean, commonMessage?: string) => {
if (!commonSuccess) {
callback(false, commonMessage);
return;
}
this.saveCats(cats, 0, (success: boolean, message?: string) => {
if (!success) {
callback(false, message);
return;
}
this.markProcessed(result.claimId);
callback(true);
});
});
}
// 更新金币、道具和无限体力;有道具时同步服务端总量。
private static grantCommonRewards(
coin: number,
hammer: number,
freeze: number,
magic: number,
infiniteHealth: number,
callback: (success: boolean, message?: string) => void,
) {
if (coin > 0) {
cc.fx.GameTool.changeCoin(coin);
}
let propData = null;
if (hammer > 0 || freeze > 0 || magic > 0) {
const info = cc.fx.GameConfig.GM_INFO;
info.hammerAmount = (Number(info.hammerAmount) || 0) + hammer;
info.freezeAmount = (Number(info.freezeAmount) || 0) + freeze;
info.magicAmount = (Number(info.magicAmount) || 0) + magic;
propData = {
freeze: info.freezeAmount,
hammer: info.hammerAmount,
magic_wand: info.magicAmount,
};
cc.fx.StorageMessage.setStorage("prop", {
hammerAmount: info.hammerAmount,
freezeAmount: info.freezeAmount,
magicAmount: info.magicAmount,
timestamp: Date.now(),
});
}
if (infiniteHealth > 0) {
// 服务端奖励值和体力接口都使用秒,原值传入,不做分钟换算。
cc.fx.GameTool.setUserPowerTime(infiniteHealth, "seven_day_gift");
}
const canvas = cc.find("Canvas");
const home: any = canvas && canvas.getComponent("JiaZai");
if (home && home.updateCoin) {
home.updateCoin();
}
if (infiniteHealth > 0 && home && typeof home.updatePower === "function") {
// 首次获得无限体力时也要切换主页显示并启动倒计时。
home.updatePower();
}
if (!propData) {
callback(true);
return;
}
SevenDayGiftApi.saveProps(propData, response => {
if (!response || response.code !== 1) {
callback(false, response && response.msg ? response.msg : "道具同步失败");
return;
}
callback(true);
});
}
// 逐个保存猫皮肤,已保存也视为成功。
private static saveCats(cats: number[], index: number, callback: (success: boolean, message?: string) => void) {
if (index >= cats.length) {
callback(true);
return;
}
const catNum = cats[index];
SevenDayGiftApi.saveCat(catNum, response => {
const alreadySaved = response && response.msg === "已保存猫咪";
if (!response || (response.code !== 1 && !alreadySaved)) {
callback(false, response && response.msg ? response.msg : "猫咪保存失败");
return;
}
const current = Array.isArray(cc.fx.GameConfig.GM_INFO.catArr)
? cc.fx.GameConfig.GM_INFO.catArr.slice()
: [];
if (current.indexOf(catNum) < 0) current.push(catNum);
cc.fx.GameConfig.GM_INFO.catArr = response.data && Array.isArray(response.data.catArr)
? response.data.catArr
: current;
this.saveCats(cats, index + 1, callback);
});
}
// 检查本地是否已完成这次奖励同步。
private static hasProcessed(claimId: string): boolean {
const records = cc.fx.StorageMessage.getStorage(PROCESSED_CLAIMS_KEY) || {};
return records[this.claimKey(claimId)] === true;
}
// 记录本次全部奖励已处理,供后续重复调用跳过。
private static markProcessed(claimId: string) {
const records = cc.fx.StorageMessage.getStorage(PROCESSED_CLAIMS_KEY) || {};
records[this.claimKey(claimId)] = true;
cc.fx.StorageMessage.setStorage(PROCESSED_CLAIMS_KEY, records);
}
// 同一个奖励记录按 UID 隔离,避免账号之间互相影响。
private static claimKey(claimId: string): string {
return SevenDayGiftApi.getUid() + ":" + claimId;
}
}