@mclawnet/agent 0.6.19 → 0.6.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/{chunk-RO47ET27.js → chunk-M2CDVPQF.js} +2 -2
  2. package/dist/{chunk-CBZIH6FY.js → chunk-PJ5M6Q36.js} +2 -2
  3. package/dist/chunk-PJ5M6Q36.js.map +1 -0
  4. package/dist/{chunk-MSDIRBXF.js → chunk-RIK7IXSW.js} +2 -2
  5. package/dist/index.js +2 -2
  6. package/dist/{linux-6AR7SXHW.js → linux-IHA4O633.js} +3 -3
  7. package/dist/{macos-BTP5JW3U.js → macos-G4VK2253.js} +8 -3
  8. package/dist/macos-G4VK2253.js.map +1 -0
  9. package/dist/service/index.js +5 -5
  10. package/dist/service/macos.d.ts.map +1 -1
  11. package/dist/start.js +2 -2
  12. package/dist/{windows-IQNSUMN6.js → windows-P6U3JLUZ.js} +3 -3
  13. package/package.json +4 -4
  14. package/skills/cocos-creator-3x-cn/SKILL.md +475 -0
  15. package/skills/cocos-creator-3x-cn/references/framework/asset-management.md +322 -0
  16. package/skills/cocos-creator-3x-cn/references/framework/component-system.md +348 -0
  17. package/skills/cocos-creator-3x-cn/references/framework/event-patterns.md +410 -0
  18. package/skills/cocos-creator-3x-cn/references/framework/playable-optimization.md +257 -0
  19. package/skills/cocos-creator-3x-cn/references/language/performance.md +363 -0
  20. package/skills/cocos-creator-3x-cn/references/language/quality-hygiene.md +307 -0
  21. package/skills/cocos-creator-3x-cn/references/review/architecture-review.md +183 -0
  22. package/skills/cocos-creator-3x-cn/references/review/quality-review.md +251 -0
  23. package/skills/cocos-performance-optimizer/SKILL.md +214 -0
  24. package/skills/game-development/2d-games/SKILL.md +129 -0
  25. package/skills/game-development/3d-games/SKILL.md +145 -0
  26. package/skills/game-development/SKILL.md +175 -0
  27. package/skills/game-development/game-art/SKILL.md +195 -0
  28. package/skills/game-development/game-audio/SKILL.md +200 -0
  29. package/skills/game-development/game-design/SKILL.md +139 -0
  30. package/skills/game-development/mobile-games/SKILL.md +118 -0
  31. package/skills/game-development/multiplayer/SKILL.md +142 -0
  32. package/skills/game-development/pc-games/SKILL.md +154 -0
  33. package/skills/game-development/vr-ar/SKILL.md +133 -0
  34. package/skills/game-development/web-games/SKILL.md +160 -0
  35. package/skills/game-engine/SKILL.md +140 -0
  36. package/skills/game-engine/assets/2d-maze-game.md +528 -0
  37. package/skills/game-engine/assets/2d-platform-game.md +1855 -0
  38. package/skills/game-engine/assets/gameBase-template-repo.md +310 -0
  39. package/skills/game-engine/assets/paddle-game-template.md +1528 -0
  40. package/skills/game-engine/assets/simple-2d-engine.md +507 -0
  41. package/skills/game-engine/references/3d-web-games.md +754 -0
  42. package/skills/game-engine/references/algorithms.md +843 -0
  43. package/skills/game-engine/references/basics.md +343 -0
  44. package/skills/game-engine/references/game-control-mechanisms.md +617 -0
  45. package/skills/game-engine/references/game-engine-core-principles.md +695 -0
  46. package/skills/game-engine/references/game-publishing.md +352 -0
  47. package/skills/game-engine/references/techniques.md +894 -0
  48. package/skills/game-engine/references/terminology.md +354 -0
  49. package/skills/game-engine/references/web-apis.md +1394 -0
  50. package/skills/theone-cocos-standards/SKILL.md +557 -0
  51. package/skills/theone-cocos-standards/references/framework/component-system.md +645 -0
  52. package/skills/theone-cocos-standards/references/framework/event-patterns.md +433 -0
  53. package/skills/theone-cocos-standards/references/framework/playable-optimization.md +429 -0
  54. package/skills/theone-cocos-standards/references/framework/size-optimization.md +308 -0
  55. package/skills/theone-cocos-standards/references/language/modern-typescript.md +658 -0
  56. package/skills/theone-cocos-standards/references/language/performance.md +580 -0
  57. package/skills/theone-cocos-standards/references/language/quality-hygiene.md +582 -0
  58. package/skills/theone-cocos-standards/references/review/architecture-review.md +250 -0
  59. package/skills/theone-cocos-standards/references/review/performance-review.md +288 -0
  60. package/skills/theone-cocos-standards/references/review/quality-review.md +239 -0
  61. package/dist/chunk-CBZIH6FY.js.map +0 -1
  62. package/dist/macos-BTP5JW3U.js.map +0 -1
  63. /package/dist/{chunk-RO47ET27.js.map → chunk-M2CDVPQF.js.map} +0 -0
  64. /package/dist/{chunk-MSDIRBXF.js.map → chunk-RIK7IXSW.js.map} +0 -0
  65. /package/dist/{linux-6AR7SXHW.js.map → linux-IHA4O633.js.map} +0 -0
  66. /package/dist/{windows-IQNSUMN6.js.map → windows-P6U3JLUZ.js.map} +0 -0
@@ -0,0 +1,429 @@
1
+ # Playable Ads Performance Optimization
2
+
3
+ ## DrawCall Batching (Critical for Playables)
4
+
5
+ **Target: <10 DrawCalls for smooth 60fps playables**
6
+
7
+ ```typescript
8
+ import { _decorator, Component, Sprite, SpriteAtlas, SpriteFrame } from 'cc';
9
+ const { ccclass, property } = _decorator;
10
+
11
+ @ccclass('SpriteAtlasManager')
12
+ export class SpriteAtlasManager extends Component {
13
+ // ✅ EXCELLENT: Use sprite atlas for DrawCall batching
14
+ @property(SpriteAtlas)
15
+ private readonly characterAtlas: SpriteAtlas | null = null;
16
+
17
+ @property(SpriteAtlas)
18
+ private readonly uiAtlas: SpriteAtlas | null = null;
19
+
20
+ private readonly spriteFrameCache: Map<string, SpriteFrame> = new Map();
21
+
22
+ protected onLoad(): void {
23
+ if (!this.characterAtlas || !this.uiAtlas) {
24
+ throw new Error('SpriteAtlasManager: atlases are required');
25
+ }
26
+
27
+ // ✅ EXCELLENT: Prewarm sprite frames from atlas
28
+ this.prewarmAtlas(this.characterAtlas, 'character');
29
+ this.prewarmAtlas(this.uiAtlas, 'ui');
30
+ }
31
+
32
+ private prewarmAtlas(atlas: SpriteAtlas, prefix: string): void {
33
+ const spriteFrames = atlas.getSpriteFrames();
34
+ for (const frame of spriteFrames) {
35
+ const key = `${prefix}_${frame.name}`;
36
+ this.spriteFrameCache.set(key, frame);
37
+ }
38
+ }
39
+
40
+ // ✅ EXCELLENT: Get sprite frame from cache (batched in same DrawCall)
41
+ public getSpriteFrame(atlasName: string, frameName: string): SpriteFrame | null {
42
+ const key = `${atlasName}_${frameName}`;
43
+ return this.spriteFrameCache.get(key) ?? null;
44
+ }
45
+ }
46
+
47
+ // Usage: All sprites from same atlas = single DrawCall
48
+ @ccclass('CharacterSprite')
49
+ export class CharacterSprite extends Component {
50
+ @property(Sprite)
51
+ private readonly sprite: Sprite | null = null;
52
+
53
+ private atlasManager!: SpriteAtlasManager;
54
+
55
+ protected start(): void {
56
+ const manager = this.node.parent?.getComponent(SpriteAtlasManager);
57
+ if (!manager) throw new Error('SpriteAtlasManager not found');
58
+ this.atlasManager = manager;
59
+
60
+ // ✅ GOOD: Set sprite frame from atlas (batched)
61
+ const frame = this.atlasManager.getSpriteFrame('character', 'idle_01');
62
+ if (frame && this.sprite) {
63
+ this.sprite.spriteFrame = frame;
64
+ }
65
+ }
66
+ }
67
+
68
+ // ❌ WRONG: Individual textures (multiple DrawCalls)
69
+ @property(SpriteFrame)
70
+ private characterIdleFrame: SpriteFrame | null = null; // DrawCall 1
71
+
72
+ @property(SpriteFrame)
73
+ private characterWalkFrame: SpriteFrame | null = null; // DrawCall 2
74
+
75
+ @property(SpriteFrame)
76
+ private characterJumpFrame: SpriteFrame | null = null; // DrawCall 3
77
+ // Result: 3 DrawCalls for 3 sprites!
78
+
79
+ // ✅ BETTER: Single atlas
80
+ @property(SpriteAtlas)
81
+ private characterAtlas: SpriteAtlas | null = null; // DrawCall 1 for all frames
82
+ ```
83
+
84
+ ## GPU Skinning (Skeletal Animations)
85
+
86
+ ```typescript
87
+ import { _decorator, Component, SkeletalAnimation } from 'cc';
88
+ const { ccclass, property } = _decorator;
89
+
90
+ @ccclass('AnimationController')
91
+ export class AnimationController extends Component {
92
+ @property(SkeletalAnimation)
93
+ private readonly skeleton: SkeletalAnimation | null = null;
94
+
95
+ protected onLoad(): void {
96
+ if (!this.skeleton) {
97
+ throw new Error('AnimationController: skeleton is required');
98
+ }
99
+
100
+ // ✅ EXCELLENT: Enable GPU skinning for better performance
101
+ // GPU handles bone transformations instead of CPU
102
+ this.skeleton.useBakedAnimation = true; // Baked animation data
103
+ }
104
+
105
+ public playAnimation(animName: string, loop: boolean = false): void {
106
+ if (!this.skeleton) return;
107
+
108
+ const state = this.skeleton.getState(animName);
109
+ if (state) {
110
+ state.wrapMode = loop ? SkeletalAnimation.WrapMode.Loop : SkeletalAnimation.WrapMode.Normal;
111
+ this.skeleton.play(animName);
112
+ }
113
+ }
114
+ }
115
+
116
+ // ❌ WRONG: CPU skinning (default, slower)
117
+ // Don't set useBakedAnimation to false for playables
118
+ ```
119
+
120
+ ## Object Pooling for Playables
121
+
122
+ ```typescript
123
+ import { _decorator, Component, Node, Prefab, instantiate, NodePool } from 'cc';
124
+ const { ccclass, property } = _decorator;
125
+
126
+ @ccclass('PlayableObjectPool')
127
+ export class PlayableObjectPool extends Component {
128
+ @property(Prefab)
129
+ private readonly bulletPrefab: Prefab | null = null;
130
+
131
+ @property(Prefab)
132
+ private readonly effectPrefab: Prefab | null = null;
133
+
134
+ private readonly bulletPool: NodePool = new NodePool();
135
+ private readonly effectPool: NodePool = new NodePool();
136
+ private static readonly PREWARM_COUNT: number = 20;
137
+
138
+ // ✅ EXCELLENT: Prewarm pools to avoid allocations during gameplay
139
+ protected onLoad(): void {
140
+ if (!this.bulletPrefab || !this.effectPrefab) {
141
+ throw new Error('PlayableObjectPool: prefabs are required');
142
+ }
143
+
144
+ // Prewarm bullet pool
145
+ for (let i = 0; i < PlayableObjectPool.PREWARM_COUNT; i++) {
146
+ const bullet = instantiate(this.bulletPrefab);
147
+ this.bulletPool.put(bullet);
148
+ }
149
+
150
+ // Prewarm effect pool
151
+ for (let i = 0; i < PlayableObjectPool.PREWARM_COUNT; i++) {
152
+ const effect = instantiate(this.effectPrefab);
153
+ this.effectPool.put(effect);
154
+ }
155
+ }
156
+
157
+ // ✅ EXCELLENT: Get from pool (zero allocations in gameplay)
158
+ public getBullet(): Node {
159
+ if (this.bulletPool.size() > 0) {
160
+ const bullet = this.bulletPool.get()!;
161
+ bullet.active = true;
162
+ return bullet;
163
+ }
164
+
165
+ // Fallback: create new (should be rare if prewarmed correctly)
166
+ if (!this.bulletPrefab) {
167
+ throw new Error('bulletPrefab is null');
168
+ }
169
+ return instantiate(this.bulletPrefab);
170
+ }
171
+
172
+ public returnBullet(bullet: Node): void {
173
+ bullet.active = false;
174
+ this.bulletPool.put(bullet);
175
+ }
176
+
177
+ protected onDestroy(): void {
178
+ this.bulletPool.clear();
179
+ this.effectPool.clear();
180
+ }
181
+ }
182
+
183
+ // ❌ WRONG: Creating/destroying objects during gameplay
184
+ public shoot(): void {
185
+ const bullet = instantiate(this.bulletPrefab!); // Allocates every time
186
+ this.scheduleOnce(() => {
187
+ bullet.destroy(); // Triggers GC
188
+ }, 2.0);
189
+ }
190
+ ```
191
+
192
+ ## Update Loop Optimization for Playables
193
+
194
+ ```typescript
195
+ import { _decorator, Component, Node, Vec3 } from 'cc';
196
+ const { ccclass, property } = _decorator;
197
+
198
+ @ccclass('OptimizedUpdate')
199
+ export class OptimizedUpdate extends Component {
200
+ @property([Node])
201
+ private readonly enemies: Node[] = [];
202
+
203
+ // ✅ EXCELLENT: Preallocate to avoid allocations in update
204
+ private readonly tempVec3: Vec3 = new Vec3();
205
+ private readonly activeEnemies: Node[] = [];
206
+ private activeEnemiesDirty: boolean = true;
207
+ private frameCount: number = 0;
208
+
209
+ // ✅ EXCELLENT: Update expensive operations every N frames
210
+ protected update(dt: number): void {
211
+ this.frameCount++;
212
+
213
+ // Cheap operations: every frame
214
+ this.updateMovement(dt);
215
+
216
+ // Expensive operations: every 10 frames (6 times/second at 60fps)
217
+ if (this.frameCount % 10 === 0) {
218
+ this.updateAI();
219
+ }
220
+
221
+ // Very expensive: every 60 frames (once per second at 60fps)
222
+ if (this.frameCount % 60 === 0) {
223
+ this.updatePathfinding();
224
+ }
225
+ }
226
+
227
+ private updateMovement(dt: number): void {
228
+ // Use cached active enemies list
229
+ const activeEnemies = this.getActiveEnemies();
230
+
231
+ for (const enemy of activeEnemies) {
232
+ // Reuse preallocated vector
233
+ enemy.getPosition(this.tempVec3);
234
+ this.tempVec3.y += 10 * dt;
235
+ enemy.setPosition(this.tempVec3);
236
+ }
237
+ }
238
+
239
+ private getActiveEnemies(): Node[] {
240
+ if (this.activeEnemiesDirty) {
241
+ this.activeEnemies.length = 0;
242
+ for (const enemy of this.enemies) {
243
+ if (enemy.active) {
244
+ this.activeEnemies.push(enemy);
245
+ }
246
+ }
247
+ this.activeEnemiesDirty = false;
248
+ }
249
+ return this.activeEnemies;
250
+ }
251
+
252
+ private updateAI(): void {
253
+ // Expensive AI logic
254
+ }
255
+
256
+ private updatePathfinding(): void {
257
+ // Very expensive pathfinding
258
+ }
259
+ }
260
+
261
+ // ❌ WRONG: All logic in update, allocations everywhere
262
+ protected update(dt: number): void {
263
+ // Allocates array every frame
264
+ const activeEnemies = this.enemies.filter(e => e.active);
265
+
266
+ for (const enemy of activeEnemies) {
267
+ // Allocates vector every frame
268
+ const pos = enemy.position.clone();
269
+ pos.y += 10 * dt;
270
+ enemy.setPosition(pos);
271
+ }
272
+
273
+ // Expensive operations every frame
274
+ this.updatePathfinding(); // 60 times/second!
275
+ this.updateAI(); // 60 times/second!
276
+ }
277
+ ```
278
+
279
+ ## Resource Loading and Preloading
280
+
281
+ ```typescript
282
+ import { _decorator, Component, resources, SpriteFrame, AudioClip } from 'cc';
283
+ const { ccclass } = _decorator;
284
+
285
+ @ccclass('ResourcePreloader')
286
+ export class ResourcePreloader extends Component {
287
+ private readonly loadedResources: Map<string, Asset> = new Map();
288
+
289
+ // ✅ EXCELLENT: Preload all resources at game start
290
+ protected async start(): Promise<void> {
291
+ await this.preloadAllResources();
292
+ }
293
+
294
+ private async preloadAllResources(): Promise<void> {
295
+ const resourcePaths = [
296
+ 'sprites/character',
297
+ 'sprites/enemies',
298
+ 'audio/bgm',
299
+ 'audio/sfx',
300
+ ];
301
+
302
+ const promises = resourcePaths.map(path => this.preloadResource(path));
303
+ await Promise.all(promises);
304
+
305
+ console.log('All resources preloaded');
306
+ }
307
+
308
+ private async preloadResource(path: string): Promise<void> {
309
+ return new Promise((resolve, reject) => {
310
+ resources.load(path, (err, asset) => {
311
+ if (err) {
312
+ console.error(`Failed to load ${path}:`, err);
313
+ reject(err);
314
+ return;
315
+ }
316
+
317
+ this.loadedResources.set(path, asset);
318
+ resolve();
319
+ });
320
+ });
321
+ }
322
+
323
+ public getResource<T extends Asset>(path: string): T | null {
324
+ return (this.loadedResources.get(path) as T) ?? null;
325
+ }
326
+
327
+ protected onDestroy(): void {
328
+ // ✅ EXCELLENT: Release all loaded resources
329
+ for (const [path, asset] of this.loadedResources) {
330
+ asset.decRef();
331
+ }
332
+ this.loadedResources.clear();
333
+ }
334
+ }
335
+
336
+ // ❌ WRONG: Loading resources during gameplay
337
+ protected update(dt: number): void {
338
+ if (this.shouldSpawnEnemy()) {
339
+ // Loading during gameplay causes frame drops!
340
+ resources.load('sprites/enemy', SpriteFrame, (err, sprite) => {
341
+ this.spawnEnemy(sprite);
342
+ });
343
+ }
344
+ }
345
+
346
+ // ✅ BETTER: Preload and reuse
347
+ protected start(): void {
348
+ resources.load('sprites/enemy', SpriteFrame, (err, sprite) => {
349
+ this.enemySprite = sprite;
350
+ });
351
+ }
352
+
353
+ protected update(dt: number): void {
354
+ if (this.shouldSpawnEnemy() && this.enemySprite) {
355
+ this.spawnEnemy(this.enemySprite); // Instant, no loading
356
+ }
357
+ }
358
+ ```
359
+
360
+ ## Memory Management for Playables
361
+
362
+ ```typescript
363
+ import { _decorator, Component, Node } from 'cc';
364
+ const { ccclass } = _decorator;
365
+
366
+ @ccclass('MemoryOptimized')
367
+ export class MemoryOptimized extends Component {
368
+ // ✅ EXCELLENT: Use typed arrays for large datasets
369
+ private positions: Float32Array = new Float32Array(300); // 100 Vec3s
370
+ private velocities: Float32Array = new Float32Array(300);
371
+
372
+ // ✅ EXCELLENT: Reuse arrays instead of creating new ones
373
+ private readonly tempArray: number[] = [];
374
+
375
+ protected update(dt: number): void {
376
+ // Reuse array, don't allocate
377
+ this.tempArray.length = 0;
378
+
379
+ for (let i = 0; i < 100; i++) {
380
+ this.tempArray.push(i * dt);
381
+ }
382
+ }
383
+
384
+ // ✅ EXCELLENT: WeakMap for caches (automatic cleanup)
385
+ private readonly nodeCache: WeakMap<Node, CachedData> = new WeakMap();
386
+
387
+ public getCachedData(node: Node): CachedData | undefined {
388
+ return this.nodeCache.get(node);
389
+ }
390
+
391
+ protected onDestroy(): void {
392
+ // ✅ EXCELLENT: Clear references
393
+ this.tempArray.length = 0;
394
+ // WeakMap entries are auto-cleared when nodes are destroyed
395
+ }
396
+ }
397
+ ```
398
+
399
+ ## Summary: Playable Optimization Checklist
400
+
401
+ **DrawCall Batching (<10 target):**
402
+ - [ ] Use sprite atlases for all sprites (not individual textures)
403
+ - [ ] Prewarm sprite frame cache in onLoad()
404
+ - [ ] Group UI elements into single atlas
405
+ - [ ] Use same material for similar objects
406
+
407
+ **Animation Performance:**
408
+ - [ ] Enable GPU skinning (useBakedAnimation = true)
409
+ - [ ] Bake skeletal animations
410
+ - [ ] Limit simultaneous animations
411
+
412
+ **Object Pooling:**
413
+ - [ ] Pool bullets, effects, enemies (anything spawned frequently)
414
+ - [ ] Prewarm pools in onLoad() (at least 20 objects)
415
+ - [ ] Never instantiate/destroy during gameplay
416
+
417
+ **Update Loop:**
418
+ - [ ] Zero allocations in update()
419
+ - [ ] Throttle expensive operations (every 10-60 frames)
420
+ - [ ] Cache active object lists
421
+ - [ ] Reuse preallocated vectors/arrays
422
+
423
+ **Resource Management:**
424
+ - [ ] Preload all resources at game start
425
+ - [ ] Never load resources during gameplay
426
+ - [ ] Release resources in onDestroy()
427
+ - [ ] Use WeakMap for auto-cleanup caches
428
+
429
+ **Target: 60fps with <10 DrawCalls and <5MB bundle size for playable ads.**