更新UI
This commit is contained in:
parent
b1eb031eaa
commit
85014adc78
|
|
@ -3947,6 +3947,8 @@ export default class JiaZai extends cc.Component {
|
|||
// 3. 处理月卡过期逻辑
|
||||
// ============================================
|
||||
rewarded() {
|
||||
const canUpdateHome = () => this.isHomeRuntimeAlive() && !cc.fx.GameConfig.isGameplayEntryPreparing();
|
||||
if (!canUpdateHome()) return;
|
||||
if (this.deferHomePopupWhileTransfer("monthlyReward", () => this.rewarded())) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -3962,6 +3964,7 @@ export default class JiaZai extends cc.Component {
|
|||
})
|
||||
}
|
||||
setTimeout(() => {
|
||||
if (!canUpdateHome()) return;
|
||||
this.updateCoin();
|
||||
this.setHealthInfo(false);
|
||||
this.startTimeCutDown();
|
||||
|
|
@ -3973,7 +3976,22 @@ export default class JiaZai extends cc.Component {
|
|||
// console.log("未到期已领取");
|
||||
}
|
||||
if (data.code == 1) {
|
||||
// 奖励处理独立于弹窗,主页销毁或队列尚未执行也不能漏发。
|
||||
cc.fx.GameTool.changeCoin(500);
|
||||
const dataTemp = {
|
||||
change_reason: "month",
|
||||
id: "1001",
|
||||
num: 500,
|
||||
compensate: false
|
||||
}
|
||||
cc.fx.GameTool.shushu_Track("resource_get", dataTemp);
|
||||
if (!canUpdateHome()) return;
|
||||
this.updateCoin();
|
||||
HomePopupQueue.get(this.node).enqueue("monthlyReward", 20, done => {
|
||||
if (!canUpdateHome() || !this.getcard || !cc.isValid(this.getcard, true)
|
||||
|| !this.cardTime || !cc.isValid(this.cardTime, true)) { done(); return; }
|
||||
const pauseNode = this.getcard.getChildByName("mcReward");
|
||||
if (!pauseNode || !cc.isValid(pauseNode, true)) { done(); return; }
|
||||
this.getcard.active = true;
|
||||
this.getcard.zIndex = 999;
|
||||
// 外层 getcard 整体弹入动画(三次回弹)
|
||||
|
|
@ -3983,7 +4001,6 @@ export default class JiaZai extends cc.Component {
|
|||
.to(0.08, { scale: 0.95 }, { easing: 'sineIn' })
|
||||
.to(0.08, { scale: 1.0 }, { easing: 'sineOut' })
|
||||
.start();
|
||||
let pauseNode = this.getcard.getChildByName("mcReward");
|
||||
pauseNode.scale = 0.3;
|
||||
cc.tween(pauseNode)
|
||||
.to(0.2, { scale: 1.05 }, { easing: 'backOut' })
|
||||
|
|
@ -3993,15 +4010,6 @@ export default class JiaZai extends cc.Component {
|
|||
for (let i = 0; i < this.cardTime.children.length; i++) {
|
||||
this.cardTime.children[i].color = cc.Color.RED;
|
||||
}
|
||||
cc.fx.GameTool.changeCoin(500);
|
||||
this.updateCoin();
|
||||
const dataTemp = {
|
||||
change_reason: "month",
|
||||
id: "1001",
|
||||
num: 500,
|
||||
compensate: false
|
||||
}
|
||||
cc.fx.GameTool.shushu_Track("resource_get", dataTemp);
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
|
@ -4018,6 +4026,8 @@ export default class JiaZai extends cc.Component {
|
|||
// 2. 使用缓存控制每天只弹一次月卡弹窗
|
||||
// ============================================
|
||||
monthH() {
|
||||
const canUpdateHome = () => this.isHomeRuntimeAlive() && !cc.fx.GameConfig.isGameplayEntryPreparing();
|
||||
if (!canUpdateHome()) return;
|
||||
if (cc.fx.GameConfig.isNewPlayerB() && cc.fx.GameConfig.GM_INFO.level < 20) return;
|
||||
if (this.deferHomePopupWhileTransfer("monthlyCard", () => this.monthH())) {
|
||||
return;
|
||||
|
|
@ -4025,6 +4035,7 @@ export default class JiaZai extends cc.Component {
|
|||
// return;
|
||||
//如果没有充值月卡,每天弹一次月卡弹窗用缓存实现
|
||||
Utils.getMonthlyCard((data) => {
|
||||
if (!canUpdateHome()) return;
|
||||
if (data.msg == "不在有效期") {
|
||||
let date = new Date();
|
||||
let day = date.getDate(); // 当前日期(1-31)
|
||||
|
|
@ -4038,6 +4049,7 @@ export default class JiaZai extends cc.Component {
|
|||
this.winStreakShow = false;
|
||||
// 更新缓存
|
||||
HomePopupQueue.get(this.node).enqueue("monthlyCard", 30, done => {
|
||||
if (!canUpdateHome()) { done(); return; }
|
||||
this.openMonthCard();
|
||||
if (this.monthlyCardNode && this.monthlyCardNode.active) cc.fx.StorageMessage.setStorage("monthlyCardDate", dateStr);
|
||||
done();
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
"premultiplyAlpha": false,
|
||||
"genMipmaps": false,
|
||||
"packable": true,
|
||||
"width": 1084,
|
||||
"height": 807,
|
||||
"width": 782,
|
||||
"height": 1024,
|
||||
"platformSettings": {
|
||||
"minigame": {
|
||||
"formats": []
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
"premultiplyAlpha": false,
|
||||
"genMipmaps": false,
|
||||
"packable": true,
|
||||
"width": 547,
|
||||
"height": 972,
|
||||
"width": 957,
|
||||
"height": 544,
|
||||
"platformSettings": {},
|
||||
"subMetas": {}
|
||||
}
|
||||
|
|
@ -999,8 +999,8 @@
|
|||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 140,
|
||||
"height": 144
|
||||
"width": 277,
|
||||
"height": 308
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
|
|
@ -1018,8 +1018,8 @@
|
|||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0.5,
|
||||
0.5,
|
||||
1
|
||||
]
|
||||
},
|
||||
|
|
@ -1052,7 +1052,7 @@
|
|||
"_srcBlendFactor": 770,
|
||||
"_dstBlendFactor": 771,
|
||||
"_spriteFrame": {
|
||||
"__uuid__": "f6fd677c-4c67-40a6-97ba-1a6154d25b4d"
|
||||
"__uuid__": "28d2a4a2-6112-4092-af82-ac2da3393401"
|
||||
},
|
||||
"_type": 0,
|
||||
"_sizeMode": 1,
|
||||
|
|
@ -1365,8 +1365,8 @@
|
|||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 118,
|
||||
"height": 141
|
||||
"width": 250,
|
||||
"height": 292
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
|
|
@ -1384,8 +1384,8 @@
|
|||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0.5,
|
||||
0.5,
|
||||
1
|
||||
]
|
||||
},
|
||||
|
|
@ -1418,7 +1418,7 @@
|
|||
"_srcBlendFactor": 770,
|
||||
"_dstBlendFactor": 771,
|
||||
"_spriteFrame": {
|
||||
"__uuid__": "e3910b71-bd4f-4861-8092-0597ed9adffb"
|
||||
"__uuid__": "ac60b2a5-c833-400a-b640-6eb478c96f1f"
|
||||
},
|
||||
"_type": 0,
|
||||
"_sizeMode": 1,
|
||||
|
|
@ -1731,8 +1731,8 @@
|
|||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 133,
|
||||
"height": 136
|
||||
"width": 264,
|
||||
"height": 279
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
|
|
@ -1750,8 +1750,8 @@
|
|||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0.5,
|
||||
0.5,
|
||||
1
|
||||
]
|
||||
},
|
||||
|
|
@ -1784,7 +1784,7 @@
|
|||
"_srcBlendFactor": 770,
|
||||
"_dstBlendFactor": 771,
|
||||
"_spriteFrame": {
|
||||
"__uuid__": "cb2834e3-8bfa-4c1e-9558-115a065076d6"
|
||||
"__uuid__": "88e305a3-bb71-410b-b067-7748e9696122"
|
||||
},
|
||||
"_type": 0,
|
||||
"_sizeMode": 1,
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"ver": "1.1.3",
|
||||
"uuid": "ccd7701f-585a-411b-a8ef-a9f03f22189f",
|
||||
"importer": "folder",
|
||||
"isBundle": false,
|
||||
"bundleName": "",
|
||||
"priority": 1,
|
||||
"compressionType": {},
|
||||
"optimizeHotUpdate": {},
|
||||
"inlineSpriteFrames": {},
|
||||
"isRemoteBundle": {},
|
||||
"subMetas": {}
|
||||
}
|
||||
150
tools/test-monthly-card-lifecycle.cjs
Normal file
150
tools/test-monthly-card-lifecycle.cjs
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const vm = require('node:vm');
|
||||
const ts = require(process.env.TYPESCRIPT_PATH || 'typescript');
|
||||
|
||||
const root = path.resolve(__dirname, '..');
|
||||
const read = file => fs.readFileSync(path.join(root, file), 'utf8');
|
||||
const source = ts.createSourceFile('JiaZai.ts', read('assets/Script/JiaZai.ts'), ts.ScriptTarget.Latest, true);
|
||||
const homeClass = source.statements.find(ts.isClassDeclaration);
|
||||
const methods = ['isHomeRuntimeAlive', 'rewarded', 'monthH'].map(name => {
|
||||
const member = homeClass.members.find(item => item.name?.getText(source) === name);
|
||||
assert.ok(member, name);
|
||||
return member.getText(source);
|
||||
}).join('\n');
|
||||
|
||||
function compile(code, context) {
|
||||
return vm.runInContext(ts.transpileModule(code, { compilerOptions: {
|
||||
target: ts.ScriptTarget.ES2018, module: ts.ModuleKind.CommonJS, experimentalDecorators: true,
|
||||
} }).outputText, context);
|
||||
}
|
||||
|
||||
function fixture() {
|
||||
const pending = {}, timers = [], stored = new Map(), tracked = [];
|
||||
const state = { scene: 'HomeScene', preparing: false, coinRefreshes: 0, healthRefreshes: 0, opened: 0, wins: 0, healthWrites: 0 };
|
||||
const info = { level: 30, coin: 100, hp: 8, hp_Max: 8, monthTime: 10 };
|
||||
const node = () => ({ destroyed: false, active: false, children: [], getChildByName: () => null });
|
||||
const cc = {
|
||||
_decorator: { ccclass: value => value }, Component: class {},
|
||||
isValid: value => !!value && !value.destroyed,
|
||||
director: { getScene: () => ({ name: state.scene }) }, Color: { RED: 'red' },
|
||||
tween: () => { const tween = { to: () => tween, start: () => tween }; return tween; },
|
||||
fx: {
|
||||
GameConfig: { GM_INFO: info, isNewPlayerB: () => false, isGameplayEntryPreparing: () => state.preparing },
|
||||
StorageMessage: { getStorage: key => stored.get(key), setStorage: (key, value) => stored.set(key, value) },
|
||||
GameTool: {
|
||||
changeCoin: amount => { info.coin += amount; },
|
||||
shushu_Track: (...args) => tracked.push(args),
|
||||
setUserHealth: (_, callback) => { state.healthWrites++; callback({}); },
|
||||
getHealth: () => {},
|
||||
},
|
||||
},
|
||||
};
|
||||
const context = vm.createContext({
|
||||
exports: {}, cc, setTimeout: callback => timers.push(callback),
|
||||
Utils: {
|
||||
monthGetReward: callback => { pending.reward = callback; },
|
||||
getMonthlyCard: callback => { pending.card = callback; },
|
||||
},
|
||||
NumberToImage: { numberToImageNodes: () => {} },
|
||||
});
|
||||
compile(read('assets/home_popup_queue/HomePopupQueue.ts'), context);
|
||||
context.HomePopupQueue = context.exports.default;
|
||||
const Home = compile(`class Home { ${methods} }; Home;`, context);
|
||||
const home = new Home(), queue = new context.HomePopupQueue();
|
||||
home.node = node();
|
||||
home.node.getComponent = () => queue;
|
||||
queue.node = home.node;
|
||||
home.getcard = node();
|
||||
const reward = node();
|
||||
home.getcard.getChildByName = name => name === 'mcReward' ? reward : null;
|
||||
home.cardTime = node();
|
||||
home.deferHomePopupWhileTransfer = () => false;
|
||||
home.updateCoin = () => state.coinRefreshes++;
|
||||
home.setHealthInfo = () => state.healthRefreshes++;
|
||||
home.startTimeCutDown = () => state.healthRefreshes++;
|
||||
home.openMonthCard = () => { state.opened++; home.monthlyCardNode = { active: true }; };
|
||||
home.openWin = () => state.wins++;
|
||||
return { home, queue, state, info, pending, timers, stored, tracked };
|
||||
}
|
||||
|
||||
const invalidate = {
|
||||
'node cleared': f => { f.home.node = null; },
|
||||
'node destroyed': f => { f.home.node.destroyed = true; },
|
||||
'component destroyed': f => { f.home.destroyed = true; },
|
||||
'entering gameplay': f => { f.state.preparing = true; },
|
||||
'scene changed': f => { f.state.scene = 'GameScene'; },
|
||||
};
|
||||
const rewardResponse = { code: 1, data: { monthCardReward: 1 } };
|
||||
|
||||
for (const [name, leave] of Object.entries(invalidate)) {
|
||||
test(`late monthly callbacks: ${name}`, () => {
|
||||
const f = fixture();
|
||||
f.home.rewarded(); f.home.monthH(); leave(f);
|
||||
f.pending.reward(rewardResponse);
|
||||
f.pending.card({ msg: '不在有效期' });
|
||||
f.pending.card({ msg: '有效期内' });
|
||||
assert.equal(f.info.coin, 600);
|
||||
assert.equal(f.tracked.length, 1);
|
||||
assert.equal(f.queue.tasks.length, 0);
|
||||
assert.equal(f.state.coinRefreshes + f.state.opened + f.state.wins, 0);
|
||||
});
|
||||
|
||||
test(`queued monthly popups: ${name}`, () => {
|
||||
const f = fixture();
|
||||
f.home.rewarded(); f.home.monthH();
|
||||
f.pending.reward(rewardResponse); f.pending.card({ msg: '不在有效期' });
|
||||
assert.equal(f.info.coin, 600);
|
||||
assert.equal(f.queue.tasks.length, 2);
|
||||
leave(f);
|
||||
let finished = 0;
|
||||
for (const task of f.queue.tasks) task.run(() => finished++);
|
||||
assert.equal(finished, 2);
|
||||
assert.equal(f.info.coin, 600);
|
||||
assert.equal(f.home.getcard.active, false);
|
||||
assert.equal(f.state.opened, 0);
|
||||
assert.equal(f.stored.has('monthlyCardDate'), false);
|
||||
});
|
||||
|
||||
test(`expired monthly UI timer: ${name}`, () => {
|
||||
const f = fixture(); f.home.rewarded();
|
||||
f.pending.reward({ code: 0, data: null }); leave(f);
|
||||
f.timers.forEach(callback => callback());
|
||||
assert.equal(f.info.hp_Max, 5);
|
||||
assert.equal(f.info.hp, 5);
|
||||
assert.equal(f.state.healthWrites, 1);
|
||||
assert.equal(f.state.coinRefreshes + f.state.healthRefreshes, 0);
|
||||
});
|
||||
}
|
||||
|
||||
test('normal reward is credited before popup and is not credited again when displayed', () => {
|
||||
const f = fixture(); f.home.rewarded(); f.pending.reward(rewardResponse);
|
||||
assert.equal(f.info.coin, 600);
|
||||
assert.equal(f.state.coinRefreshes, 1);
|
||||
assert.equal(f.home.getcard.active, false);
|
||||
let finished = 0;
|
||||
f.queue.tasks[0].run(() => finished++);
|
||||
assert.equal(f.home.getcard.active, true);
|
||||
assert.equal(f.info.coin, 600);
|
||||
assert.equal(f.tracked.length, 1);
|
||||
assert.equal(finished, 1);
|
||||
});
|
||||
|
||||
test('normal monthly popup records display date; already claimed reward does not credit coins', () => {
|
||||
const f = fixture(); f.home.rewarded(); f.pending.reward({ code: 0, data: {} });
|
||||
assert.equal(f.info.coin, 100);
|
||||
f.home.monthH(); f.pending.card({ msg: '不在有效期' });
|
||||
f.queue.tasks[0].run(() => {});
|
||||
assert.equal(f.state.opened, 1);
|
||||
assert.ok(f.stored.get('monthlyCardDate'));
|
||||
});
|
||||
|
||||
test('missing reward UI does not prevent credit or block the queue', () => {
|
||||
const f = fixture(); f.home.rewarded(); f.pending.reward(rewardResponse);
|
||||
f.home.getcard = null;
|
||||
let finished = 0; f.queue.tasks[0].run(() => finished++);
|
||||
assert.equal(f.info.coin, 600);
|
||||
assert.equal(finished, 1);
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user