@playcraft/build 0.0.13 → 0.0.15

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 (82) hide show
  1. package/dist/analyzers/scene-asset-collector.js +99 -9
  2. package/dist/base-builder.d.ts +15 -78
  3. package/dist/base-builder.js +34 -741
  4. package/dist/engines/engine-detector.d.ts +38 -0
  5. package/dist/engines/engine-detector.js +201 -0
  6. package/dist/engines/generic-adapter.d.ts +71 -0
  7. package/dist/engines/generic-adapter.js +378 -0
  8. package/dist/engines/index.d.ts +7 -0
  9. package/dist/engines/index.js +7 -0
  10. package/dist/engines/playcanvas-adapter.d.ts +85 -0
  11. package/dist/engines/playcanvas-adapter.js +813 -0
  12. package/dist/generators/config-generator.js +59 -1
  13. package/dist/index.d.ts +4 -0
  14. package/dist/index.js +4 -0
  15. package/dist/loaders/playcraft-loader.js +240 -5
  16. package/dist/platforms/adikteev.d.ts +1 -1
  17. package/dist/platforms/adikteev.js +30 -36
  18. package/dist/platforms/applovin.d.ts +1 -1
  19. package/dist/platforms/applovin.js +31 -36
  20. package/dist/platforms/base.d.ts +27 -5
  21. package/dist/platforms/base.js +79 -181
  22. package/dist/platforms/bigo.d.ts +1 -1
  23. package/dist/platforms/bigo.js +28 -28
  24. package/dist/platforms/facebook.d.ts +1 -1
  25. package/dist/platforms/facebook.js +21 -10
  26. package/dist/platforms/google.d.ts +1 -1
  27. package/dist/platforms/google.js +28 -21
  28. package/dist/platforms/index.d.ts +1 -0
  29. package/dist/platforms/index.js +4 -0
  30. package/dist/platforms/inmobi.d.ts +1 -1
  31. package/dist/platforms/inmobi.js +27 -34
  32. package/dist/platforms/ironsource.d.ts +1 -1
  33. package/dist/platforms/ironsource.js +37 -40
  34. package/dist/platforms/liftoff.d.ts +1 -1
  35. package/dist/platforms/liftoff.js +22 -30
  36. package/dist/platforms/mintegral.d.ts +10 -0
  37. package/dist/platforms/mintegral.js +65 -0
  38. package/dist/platforms/moloco.d.ts +1 -1
  39. package/dist/platforms/moloco.js +18 -20
  40. package/dist/platforms/playcraft.d.ts +1 -1
  41. package/dist/platforms/playcraft.js +2 -2
  42. package/dist/platforms/remerge.d.ts +1 -1
  43. package/dist/platforms/remerge.js +19 -20
  44. package/dist/platforms/snapchat.d.ts +1 -1
  45. package/dist/platforms/snapchat.js +32 -26
  46. package/dist/platforms/tiktok.d.ts +1 -1
  47. package/dist/platforms/tiktok.js +28 -24
  48. package/dist/platforms/unity.d.ts +1 -1
  49. package/dist/platforms/unity.js +30 -36
  50. package/dist/playable-builder.d.ts +1 -0
  51. package/dist/playable-builder.js +16 -2
  52. package/dist/types.d.ts +113 -1
  53. package/dist/types.js +77 -1
  54. package/dist/utils/ammo-detector.d.ts +9 -0
  55. package/dist/utils/ammo-detector.js +76 -0
  56. package/dist/utils/build-mode-detector.js +2 -0
  57. package/dist/utils/minify.d.ts +32 -0
  58. package/dist/utils/minify.js +82 -0
  59. package/dist/utils/obfuscate.d.ts +42 -0
  60. package/dist/utils/obfuscate.js +216 -0
  61. package/dist/vite/config-builder-generic.d.ts +70 -0
  62. package/dist/vite/config-builder-generic.js +251 -0
  63. package/dist/vite/config-builder.d.ts +8 -0
  64. package/dist/vite/config-builder.js +53 -16
  65. package/dist/vite/platform-configs.js +29 -1
  66. package/dist/vite/plugin-compress-js.d.ts +21 -0
  67. package/dist/vite/plugin-compress-js.js +213 -0
  68. package/dist/vite/plugin-esm-html-generator.js +5 -1
  69. package/dist/vite/plugin-obfuscate.d.ts +22 -0
  70. package/dist/vite/plugin-obfuscate.js +52 -0
  71. package/dist/vite/plugin-platform.d.ts +5 -0
  72. package/dist/vite/plugin-platform.js +499 -35
  73. package/dist/vite/plugin-playcanvas.js +21 -68
  74. package/dist/vite/plugin-source-builder.js +102 -21
  75. package/dist/vite-builder.d.ts +25 -7
  76. package/dist/vite-builder.js +141 -52
  77. package/package.json +4 -2
  78. package/physics/cannon-rigidbody-adapter.js +243 -22
  79. package/templates/__loading__.js +0 -12
  80. package/templates/index.esm.mjs +0 -11
  81. package/templates/patches/playcraft-cta-adapter.js +129 -31
  82. package/templates/patches/scene-physics-defaults.js +49 -0
@@ -3,6 +3,35 @@
3
3
  *
4
4
  * 分析 PlayCanvas 场景文件,收集所有依赖的资源 ID
5
5
  */
6
+ /**
7
+ * 构建脚本名 → 资源 ID 的映射表
8
+ * 遍历所有 script 类型的资源,从 data.scripts 中提取脚本名
9
+ */
10
+ function buildScriptNameIndex(assets) {
11
+ const index = new Map();
12
+ for (const [assetId, asset] of Object.entries(assets)) {
13
+ if (asset.type !== 'script')
14
+ continue;
15
+ const scripts = asset.data?.scripts;
16
+ if (scripts && typeof scripts === 'object' && !Array.isArray(scripts)) {
17
+ // ESM format: data.scripts is { scriptName: { attributes: ... } }
18
+ for (const scriptName of Object.keys(scripts)) {
19
+ if (!index.has(scriptName)) {
20
+ index.set(scriptName, assetId);
21
+ }
22
+ }
23
+ }
24
+ else if (Array.isArray(scripts)) {
25
+ // Classic format: data.scripts is [{ name: '...' }, ...]
26
+ for (const s of scripts) {
27
+ if (s?.name && !index.has(s.name)) {
28
+ index.set(s.name, assetId);
29
+ }
30
+ }
31
+ }
32
+ }
33
+ return index;
34
+ }
6
35
  /**
7
36
  * 分析场景的资源依赖
8
37
  * @param sceneData 场景数据对象
@@ -22,10 +51,12 @@ export async function analyzeSceneDependencies(sceneData, assets) {
22
51
  const entityCount = hasEntities ? Object.keys(sceneData.entities).length : 0;
23
52
  console.log(` [SceneAnalyzer] 场景 "${deps.sceneName}" (ID: ${deps.sceneId})`);
24
53
  console.log(` - 有 entities: ${hasEntities}, 实体数量: ${entityCount}`);
54
+ // 构建脚本名 → 资源 ID 映射(用于解析 script 组件引用)
55
+ const scriptNameIndex = buildScriptNameIndex(assets);
25
56
  // 1. 遍历所有实体
26
57
  if (sceneData.entities) {
27
58
  for (const [entityId, entity] of Object.entries(sceneData.entities)) {
28
- collectEntityAssets(entity, deps, assets);
59
+ collectEntityAssets(entity, deps, assets, scriptNameIndex);
29
60
  }
30
61
  }
31
62
  else {
@@ -109,7 +140,7 @@ function collectSettingsAssets(settings, deps, assets) {
109
140
  /**
110
141
  * 收集实体的资源引用
111
142
  */
112
- function collectEntityAssets(entity, deps, assets) {
143
+ function collectEntityAssets(entity, deps, assets, scriptNameIndex) {
113
144
  if (!entity || typeof entity !== 'object')
114
145
  return;
115
146
  // 检查实体是否引用了 template(template_id 字段)
@@ -124,7 +155,11 @@ function collectEntityAssets(entity, deps, assets) {
124
155
  if (entity.components) {
125
156
  for (const [componentName, componentData] of Object.entries(entity.components)) {
126
157
  if (componentData && typeof componentData === 'object') {
127
- // 递归扫描组件数据,查找资源 ID
158
+ // 特殊处理 script 组件:通过脚本名解析资源 ID
159
+ if (componentName === 'script') {
160
+ collectScriptComponentAssets(componentData, deps, assets, scriptNameIndex, entity.name);
161
+ }
162
+ // 递归扫描组件数据,查找资源 ID(对所有组件都做,包括 script)
128
163
  findAssetIds(componentData, deps, assets);
129
164
  }
130
165
  }
@@ -137,6 +172,45 @@ function collectEntityAssets(entity, deps, assets) {
137
172
  }
138
173
  }
139
174
  }
175
+ /**
176
+ * 处理 script 组件,将脚本名解析为资源 ID
177
+ * PlayCanvas script 组件结构:
178
+ * { order: ["scriptName1", "scriptName2"], scripts: { scriptName1: {...}, scriptName2: {...} } }
179
+ * 脚本名不是资源 ID,需要通过 scriptNameIndex 映射到对应的 script 资产
180
+ */
181
+ function collectScriptComponentAssets(scriptComponent, deps, assets, scriptNameIndex, entityName) {
182
+ // 从 order 数组或 scripts 对象键中收集脚本名
183
+ const scriptNames = new Set();
184
+ if (Array.isArray(scriptComponent.order)) {
185
+ for (const name of scriptComponent.order) {
186
+ if (typeof name === 'string') {
187
+ scriptNames.add(name);
188
+ }
189
+ }
190
+ }
191
+ if (scriptComponent.scripts && typeof scriptComponent.scripts === 'object') {
192
+ for (const name of Object.keys(scriptComponent.scripts)) {
193
+ scriptNames.add(name);
194
+ }
195
+ }
196
+ // 将脚本名映射到资源 ID
197
+ for (const scriptName of scriptNames) {
198
+ const assetId = scriptNameIndex.get(scriptName);
199
+ if (assetId && assets[assetId]) {
200
+ deps.directAssets.add(assetId);
201
+ deps.scripts.add(assetId);
202
+ console.log(` [Script] 实体 "${entityName || 'unnamed'}": 脚本 "${scriptName}" → 资源 ${assetId}`);
203
+ }
204
+ }
205
+ // 同时扫描 script 属性值中可能引用的其他资源(如 asset 类型的属性)
206
+ if (scriptComponent.scripts && typeof scriptComponent.scripts === 'object') {
207
+ for (const [scriptName, scriptConfig] of Object.entries(scriptComponent.scripts)) {
208
+ if (scriptConfig?.attributes && typeof scriptConfig.attributes === 'object') {
209
+ findAssetIds(scriptConfig.attributes, deps, assets);
210
+ }
211
+ }
212
+ }
213
+ }
140
214
  /**
141
215
  * 递归查找 JSON 中的资源 ID
142
216
  * PlayCanvas 中资源 ID 通常是数字或数字字符串
@@ -337,8 +411,8 @@ export async function collectScenesAssets(scenes, assets, globalScriptIds) {
337
411
  allAssetIds.add(id);
338
412
  }
339
413
  }
340
- // 收集所有 template 资源及其依赖
341
- // template 通常是运行时通过 assets.find() 动态实例化的,需要包含所有 preload 的模板
414
+ // 收集所有 template 资源及其依赖(含 preload=false 的插件模板如 _Guide、_ExplodeBall)
415
+ // template 通常由 GameplaySystem 等运行时通过 assets.find(name) 按名称动态加载
342
416
  console.log(`\n📦 收集 Template 资源依赖...`);
343
417
  const templateDeps = collectAllTemplatesDependencies(assets);
344
418
  let templateAssetsCount = 0;
@@ -349,19 +423,35 @@ export async function collectScenesAssets(scenes, assets, globalScriptIds) {
349
423
  }
350
424
  }
351
425
  console.log(` - 从 Template 添加了 ${templateAssetsCount} 个额外资源`);
426
+ // 当场景有脚本时,包含所有 audio 资产
427
+ // 脚本常通过 app.assets.find("sfx_xxx") 按名称查找音频,静态分析无法识别
428
+ const hasScripts = allAssetIds.size > 0 && (Array.from(allAssetIds).some(id => assets[id]?.type === 'script') ||
429
+ (globalScriptIds && globalScriptIds.size > 0));
430
+ if (hasScripts) {
431
+ let audioCount = 0;
432
+ for (const [assetId, asset] of Object.entries(assets)) {
433
+ if (asset.type === 'audio' && !allAssetIds.has(assetId)) {
434
+ allAssetIds.add(assetId);
435
+ audioCount++;
436
+ }
437
+ }
438
+ if (audioCount > 0) {
439
+ console.log(` - 场景有脚本,添加了 ${audioCount} 个 audio 资产(按名称动态引用)`);
440
+ }
441
+ }
352
442
  return allAssetIds;
353
443
  }
354
444
  /**
355
- * 收集所有 preload=true 的 template 资源及其依赖
356
- * 因为 template 通常是运行时动态实例化的,不一定在场景中直接引用
445
+ * 收集所有 template 资源及其依赖(含 preload=false 的插件模板)
446
+ * 插件模板(如 _Guide、_ExplodeBall)常由 GameplaySystem 按名称动态加载,preload 可能为 false
357
447
  */
358
448
  function collectAllTemplatesDependencies(assets) {
359
449
  const result = new Set();
360
450
  const visited = new Set();
361
451
  const queue = [];
362
- // 首先收集所有 preload=true template
452
+ // 收集所有 template(不再限制 preload=true,修复 "Failed to find plugin template" 错误)
363
453
  for (const [assetId, asset] of Object.entries(assets)) {
364
- if (asset.type === 'template' && asset.preload !== false) {
454
+ if (asset.type === 'template') {
365
455
  result.add(assetId);
366
456
  queue.push(assetId);
367
457
  }
@@ -1,93 +1,30 @@
1
- import type { BaseBuildMetadata } from './types.js';
2
- export interface BaseBuildOptions {
3
- outputDir: string;
4
- selectedScenes?: string[];
5
- analyze?: boolean;
6
- analyzeReportPath?: string;
7
- clean?: boolean;
8
- }
9
- export interface BaseBuildOutput {
10
- outputDir: string;
11
- metadata: BaseBuildMetadata;
12
- files: {
13
- html: string;
14
- engine: string | null;
15
- config: string;
16
- settings: string | null;
17
- modules: string | null;
18
- start: string;
19
- scenes: string[];
20
- assets: string[];
21
- };
22
- }
1
+ import type { BaseBuildOptions, BaseBuildOutput } from './types.js';
23
2
  /**
24
- * 基础构建器 - 生成可运行的多文件构建产物
3
+ * 基础构建器 - 路由到不同引擎适配器
25
4
  *
26
5
  * 职责:
27
- * 1. 从源代码或构建产物加载项目
28
- * 2. 确保所有必需文件存在且格式正确
29
- * 3. 输出可直接运行的多文件版本
30
- * 4. 不做任何内联或压缩
6
+ * 1. 确定引擎类型(从 options 或自动检测)
7
+ * 2. 路由到对应适配器执行 Base Build
8
+ *
9
+ * 适配器:
10
+ * - PlayCanvasAdapter:处理 PlayCanvas 项目(官方构建产物或源代码)
11
+ * - GenericAdapter:处理外部引擎(npm install + npm run build)
31
12
  */
32
13
  export declare class BaseBuilder {
33
14
  private projectDir;
34
15
  private options;
35
- private stateManager;
36
16
  constructor(projectDir: string, options: BaseBuildOptions);
37
17
  /**
38
18
  * 执行基础构建
19
+ * 根据引擎类型路由到对应适配器
39
20
  */
40
21
  build(): Promise<BaseBuildOutput>;
41
22
  /**
42
- * 保存构建元数据到输出目录
43
- */
44
- private saveBuildMetadata;
45
- /**
46
- * 检测项目类型
47
- */
48
- private detectProjectType;
49
- /**
50
- * 从官方构建产物构建
51
- */
52
- private buildFromOfficial;
53
- /**
54
- * 从输出目录检测构建模式
55
- */
56
- private detectBuildModeFromOutput;
57
- /**
58
- * 检测是否为 ESM 格式项目
59
- */
60
- private detectESMFormat;
61
- /**
62
- * 验证官方构建产物
63
- */
64
- private validateOfficialBuild;
65
- /**
66
- * 复制构建文件到输出目录
67
- */
68
- private copyBuildFiles;
69
- /**
70
- * 递归复制目录
71
- */
72
- private copyDirectory;
73
- /**
74
- * 从源代码构建(使用 Vite)
75
- */
76
- private buildFromSource;
77
- /**
78
- * 扫描输出文件
79
- */
80
- private scanOutputFiles;
81
- /**
82
- * 递归扫描目录
83
- */
84
- private scanDirectory;
85
- /**
86
- * 记录构建产物信息到状态管理器
87
- */
88
- private recordBuildOutput;
89
- /**
90
- * 生成构建分析报告
23
+ * 解析引擎类型
24
+ * 优先级:
25
+ * 1. options.engine(用户显式指定)
26
+ * 2. 自动检测
91
27
  */
92
- private generateAnalysisReport;
28
+ private resolveEngine;
93
29
  }
30
+ export type { BaseBuildOptions, BaseBuildOutput } from './types.js';