diff --git a/assets/Script/Reward.ts b/assets/Script/Reward.ts index 41af9bf0..45e3caab 100644 --- a/assets/Script/Reward.ts +++ b/assets/Script/Reward.ts @@ -30,17 +30,13 @@ export default class Reward extends cc.Component { } start() { - // ... 已有代码 ... this.node.on(cc.Node.EventType.TOUCH_END, this.onNodeClick, this); - } /** * 节点点击事件处理函数 */ onNodeClick() { - // console.log('Reward 节点被点击了', this.actionOver); - // 这里可以添加点击后的具体逻辑 if (this.actionOver == true) { cc.fx.AudioManager._instance.playEffect("anniu_little", null); this.actionOver = false; @@ -51,10 +47,6 @@ export default class Reward extends cc.Component { this.node.destroy(); }); } - else { - // 游戏整体加速 - // this.speedUpGame(); - } } @@ -151,7 +143,7 @@ export default class Reward extends cc.Component { const rewardIcon = this.getOrCreateRewardIcon(iconNode, rewardData.battlePass && rewardData.type === 'coin' ? { ...rewardData, spriteFrame: this.battlePassCoin } : rewardData); - if (rewardData.battlePass && rewardData.type !== 'coin' && rewardData.type !== 'infinite_health') { + if (rewardData.type !== 'coin' && rewardData.type !== 'infinite_health') { const prefix = rewardNode.getChildByName('xnode'); prefix.getComponent(cc.Sprite).spriteFrame = NumberToImage.publicFont.getSpriteFrame('big_cheng'); } @@ -162,16 +154,9 @@ export default class Reward extends cc.Component { if (rewardData.type == 'coin') NumberToImage.numberToImageNodesNumber(rewardData.count, 45, 5, "big_", label, true); else if (rewardData.type == 'infinite_health') { - if (durationUnits || rewardData.battlePass) { - this.renderDuration(label, rewardData.count); - rewardNode.getChildByName('xnode').active = false; - } else { - NumberToImage.getTimeMargin2(rewardData.count, 45, "coins", label, true); - if (rewardData.count > 3600) label.x -= 10; - rewardNode.getChildByName('xnode').opacity = 1; - } - } - else { + this.renderDuration(label, rewardData.count); + rewardNode.getChildByName('xnode').active = false; + } else { NumberToImage.numberToImageNodesNumber(rewardData.count, 50, 15, "big_", label, true); const xnode = rewardNode.getChildByName('xnode'); xnode.opacity = 0; @@ -189,8 +174,7 @@ export default class Reward extends cc.Component { xnode.x = label.x + (firstDigit.x - firstDigit.width * firstDigit.anchorX) * label.scaleX - 6 - xnode.width * (1 - xnode.anchorX) * xnode.scaleX; } - if (rewardData.type !== 'infinite_health' || durationUnits || rewardData.battlePass) - this.alignAmount(rewardNode, rewardData.type !== 'coin' && rewardData.type !== 'infinite_health'); + this.alignAmount(rewardNode, rewardData.type !== 'coin' && rewardData.type !== 'infinite_health'); rewardNode.getChildByName('label').active = false; if (iconNode) { cc.tween(iconNode) @@ -202,8 +186,7 @@ export default class Reward extends cc.Component { rewardNode.getChildByName('label').active = true; if (rewardNode.getChildByName('xnode').opacity == 1) { rewardNode.getChildByName('xnode').opacity = 0; - } - else if (rewardNode.getChildByName('xnode').opacity != 255) { + } else if (rewardNode.getChildByName('xnode').opacity != 255) { rewardNode.getChildByName('xnode').active = true; rewardNode.getChildByName('xnode').opacity = 255; } @@ -285,7 +268,4 @@ export default class Reward extends cc.Component { rewardIcon.setScale(rewardData.type === "cat_skin" ? 1.1 : 1); return rewardIcon; } - - - } diff --git a/assets/publicUI/prefab/rewardNode.prefab b/assets/publicUI/prefab/rewardNode.prefab index 67dc9606..b91ea01f 100644 --- a/assets/publicUI/prefab/rewardNode.prefab +++ b/assets/publicUI/prefab/rewardNode.prefab @@ -305,8 +305,8 @@ }, "_contentSize": { "__type__": "cc.Size", - "width": 84, - "height": 95 + "width": 190, + "height": 147 }, "_anchorPoint": { "__type__": "cc.Vec2", @@ -358,7 +358,7 @@ "_srcBlendFactor": 770, "_dstBlendFactor": 771, "_spriteFrame": { - "__uuid__": "d22678f9-a73b-4c94-af07-62a134fd2d30" + "__uuid__": "c331a597-3361-4765-8e44-9989c8e6648a" }, "_type": 0, "_sizeMode": 1, @@ -1356,8 +1356,8 @@ }, "_contentSize": { "__type__": "cc.Size", - "width": 36, - "height": 34 + "width": 31, + "height": 32 }, "_anchorPoint": { "__type__": "cc.Vec2", @@ -1409,7 +1409,7 @@ "_srcBlendFactor": 770, "_dstBlendFactor": 771, "_spriteFrame": { - "__uuid__": "fafa9ef2-f250-47c7-b198-49971d3a380d" + "__uuid__": "1d8908e8-0fc8-41b9-86b3-82c56da62633" }, "_type": 0, "_sizeMode": 1, diff --git a/build-templates/wechatgame/game.json b/build-templates/wechatgame/game.json index 195a3b5e..5bb1a2ae 100644 --- a/build-templates/wechatgame/game.json +++ b/build-templates/wechatgame/game.json @@ -36,7 +36,6 @@ "name": "cloud_rise_home", "root": "subpackages/cloud_rise_home" }, - { "name": "publicUI", "root": "subpackages/publicUI" @@ -61,10 +60,6 @@ "name": "jungle_treasure", "root": "subpackages/jungle_treasure" }, - { - "name": "custom", - "root": "subpackages/custom" - }, { "name": "action_bundle", "root": "subpackages/action_bundle" @@ -119,4 +114,4 @@ "iOSHighPerformance": true, "iOSHighPerformance+": true, "useNativePerformance": true -} +} \ No newline at end of file diff --git a/docs/level-resources.md b/docs/level-resources.md index 6f472323..f4eb4f23 100644 --- a/docs/level-resources.md +++ b/docs/level-resources.md @@ -24,6 +24,8 @@ packages/level-resources/publication.json: custom在微信配置为远程Bundle,抖音配置不变。Creator 2.4.15完整构建微信,填写HTTPS资源服务器地址。构建扩展自动生成levels-local内置目录、注入加载器、移除custom子包声明,并排除remote和subpackages/custom的微信上传。首次接入必须完整构建,单独运行资源发布命令不能更新客户端代码。 +微信构建后处理统一由 `packages/activity-bundles/main.js` 注册:先生成活动资源,再执行关卡打包,任一步失败都会使构建失败。`level-resources/main.js` 不再单独注册写入钩子。更新构建扩展后须重启 Creator,让新的统一入口生效;构建成功时控制台应同时出现 `[activity-bundles]` 和 `[level-resources]` 日志。 + ## 生成资源(不上传、不部署) ```powershell diff --git a/packages/activity-bundles/main.js b/packages/activity-bundles/main.js index c0599372..98208e92 100644 --- a/packages/activity-bundles/main.js +++ b/packages/activity-bundles/main.js @@ -1,10 +1,15 @@ 'use strict'; -const { pack } = require('./pack'); function onBuildFinished(options, callback) { if ((options.actualPlatform || options.platform) !== 'wechatgame') return callback(); try { - const result = pack(options.dest); + // One hook owns both postprocessors so a successful build cannot omit levels. + // Reload implementations because Creator keeps extensions alive between builds. + for (const name of ['./pack', '../level-resources/pack', '../level-resources/validation']) + delete require.cache[require.resolve(name)]; + const result = require('./pack').pack(options.dest); Editor.log('[activity-bundles] ZIP 与公共清单已生成:' + result.publishDir); + const levels = require('../level-resources/pack').pack(options.dest); + Editor.log('[level-resources] ' + levels.publishDir); callback(); } catch (error) { Editor.error(error); callback(error); } } diff --git a/packages/level-resources/main.js b/packages/level-resources/main.js index 95e98842..f490d68c 100644 --- a/packages/level-resources/main.js +++ b/packages/level-resources/main.js @@ -1,14 +1,7 @@ 'use strict'; -function finished(options, callback) { - if ((options.actualPlatform || options.platform) !== 'wechatgame') return callback(); - try { - // Creator keeps extensions alive across builds; reload the publisher after source updates. - for (const name of ['./pack', './validation']) delete require.cache[require.resolve(name)]; - Editor.log('[level-resources] ' + require('./pack').pack(options.dest).publishDir); callback(); - } - catch (error) { Editor.error(error); callback(error); } -} +// activity-bundles owns the ordered WeChat build hook. Keep the CLI publisher +// available here, without registering a second writer for game.js/settings.js. module.exports = { - load() { Editor.Builder.on('build-finished', finished); }, - unload() { Editor.Builder.removeListener('build-finished', finished); } + load() {}, + unload() {} }; diff --git a/tools/test-wechat-build-postprocess.cjs b/tools/test-wechat-build-postprocess.cjs new file mode 100644 index 00000000..20180f45 --- /dev/null +++ b/tools/test-wechat-build-postprocess.cjs @@ -0,0 +1,61 @@ +const test = require('node:test'); +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const vm = require('node:vm'); + +function fixture(failure) { + const events = [], errors = [], modules = {}, cache = {}; + for (const name of ['./pack', '../level-resources/pack', '../level-resources/validation']) { + cache[name] = { stale: true }; + modules[name] = { pack(dest) { + assert.equal(dest, 'output'); + events.push(name); + if (name === failure) throw new Error('pack failed: ' + name); + return { publishDir: name }; + } }; + } + const requireModule = name => { + assert.equal(cache[name], undefined, 'postprocessor must be reloaded'); + return modules[name]; + }; + requireModule.cache = cache; + requireModule.resolve = name => name; + let handler; + const Editor = { log() {}, error: error => errors.push(error), Builder: { + on(event, fn) { assert.equal(event, 'build-finished'); assert.equal(handler, undefined); handler = fn; }, + removeListener(event, fn) { assert.equal(event, 'build-finished'); assert.equal(fn, handler); handler = undefined; }, + } }; + const module = { exports: {} }; + vm.runInNewContext(fs.readFileSync('packages/activity-bundles/main.js', 'utf8'), + { module, require: requireModule, Editor }); + module.exports.load(); + const legacy = { exports: {} }; + vm.runInNewContext(fs.readFileSync('packages/level-resources/main.js', 'utf8'), { module: legacy, Editor }); + legacy.exports.load(); // Must not install a second writer. + return { events, errors, extension: module.exports, + run(options) { const calls = []; handler(options, error => calls.push(error)); return calls; } }; +} + +for (const options of [{ platform: 'wechatgame' }, { platform: 'mini-game', actualPlatform: 'wechatgame' }]) + test(`WeChat build runs both postprocessors in order (${JSON.stringify(options)})`, () => { + const f = fixture(); + assert.deepEqual(f.run({ ...options, dest: 'output' }), [undefined]); + assert.deepEqual(f.events, ['./pack', '../level-resources/pack']); + assert.deepEqual(f.errors, []); + f.extension.unload(); + }); + +test('other platforms do not run WeChat postprocessing', () => { + const f = fixture(); + assert.deepEqual(f.run({ platform: 'mini-game', actualPlatform: 'bytedance' }), [undefined]); + assert.deepEqual(f.events, []); +}); + +for (const failure of ['./pack', '../level-resources/pack']) + test(`failure in ${failure} rejects the build exactly once`, () => { + const f = fixture(failure), calls = f.run({ platform: 'wechatgame', dest: 'output' }); + assert.equal(calls.length, 1); + assert.match(calls[0].message, /pack failed/); + assert.equal(f.errors[0], calls[0]); + assert.deepEqual(f.events, failure === './pack' ? ['./pack'] : ['./pack', '../level-resources/pack']); + });