@playcraft/cli 0.0.43 → 0.0.46

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 (996) hide show
  1. package/dist/atom-tree/build-skeleton.js +180 -0
  2. package/dist/atom-tree/fusion-hints.js +86 -0
  3. package/dist/atom-tree/selection.js +402 -0
  4. package/dist/commands/build-all.js +33 -5
  5. package/dist/commands/build.js +13 -7
  6. package/dist/commands/create.js +774 -50
  7. package/dist/commands/image.js +11 -0
  8. package/dist/commands/prad.js +3 -3
  9. package/dist/commands/remix.js +20 -0
  10. package/dist/commands/skills.js +961 -185
  11. package/dist/commands/tools-detect.js +56 -0
  12. package/dist/commands/tools-generation.js +21 -0
  13. package/dist/commands/tools-video-review.js +100 -0
  14. package/dist/commands/tools.js +4 -0
  15. package/dist/index.js +2 -0
  16. package/dist/prad/check.test.js +23 -1
  17. package/dist/prad/skills-index.js +1 -1
  18. package/dist/remix/init-template.js +80 -0
  19. package/dist/scaffold/compose.js +211 -0
  20. package/engine-packs/phaser/game/adapters/phaser.ts +52 -0
  21. package/engine-packs/phaser/game/config/game-config.ts +46 -0
  22. package/engine-packs/phaser/game/contract/publish.ts +141 -0
  23. package/engine-packs/phaser/game/contract/types.ts +34 -0
  24. package/engine-packs/phaser/game/index.ts +81 -0
  25. package/engine-packs/phaser/game/runtime-contract.ts +28 -0
  26. package/engine-packs/phaser/manifest.json +1 -0
  27. package/engine-packs/phaser/package.deps.json +1 -0
  28. package/engine-packs/threejs/game/config/game-config.ts +46 -0
  29. package/engine-packs/threejs/game/contract/publish.ts +141 -0
  30. package/engine-packs/threejs/game/contract/types.ts +34 -0
  31. package/engine-packs/threejs/game/index.ts +76 -0
  32. package/engine-packs/threejs/game/runtime-contract.ts +15 -0
  33. package/engine-packs/threejs/manifest.json +1 -0
  34. package/engine-packs/threejs/package.deps.json +8 -0
  35. package/package.json +18 -4
  36. package/project-template/.claude/agents/artist.md +101 -0
  37. package/project-template/.claude/agents/developer.md +90 -93
  38. package/project-template/.claude/agents/game-designer.md +192 -0
  39. package/project-template/.claude/agents/refs/README.md +57 -51
  40. package/project-template/.claude/agents/refs/{designer-color-audio-recipes.md → artist-color-audio-recipes.md} +2 -2
  41. package/project-template/.claude/agents/refs/{designer-deliverable-spec.md → artist-deliverable-spec.md} +57 -57
  42. package/project-template/.claude/agents/refs/{designer-dimension-axis.md → artist-dimension-axis.md} +5 -5
  43. package/project-template/.claude/agents/refs/{designer-handoff-v2-checklist.md → artist-handoff-v2-checklist.md} +15 -15
  44. package/project-template/.claude/agents/refs/artist-legacy-fallback.md +14 -0
  45. package/project-template/.claude/agents/refs/{designer-master-composite-recipes.md → artist-master-composite-recipes.md} +3 -3
  46. package/project-template/.claude/agents/refs/artist-style-exploration-flow.md +55 -0
  47. package/project-template/.claude/agents/refs/developer-dev-handoff.md +83 -40
  48. package/project-template/.claude/agents/refs/developer-impl-cookbook.md +365 -67
  49. package/project-template/.claude/agents/refs/developer-legacy-fallback.md +15 -0
  50. package/project-template/.claude/agents/refs/developer-phase1-flow.md +131 -85
  51. package/project-template/.claude/agents/refs/framework-5-component-filter.md +252 -0
  52. package/project-template/.claude/agents/refs/framework-game-feel-juice.md +266 -0
  53. package/project-template/.claude/agents/refs/framework-mda.md +147 -0
  54. package/project-template/.claude/agents/refs/game-designer-gameplay-sufficiency.md +123 -0
  55. package/project-template/.claude/agents/refs/game-designer-legacy-fallback.md +15 -0
  56. package/project-template/.claude/agents/refs/game-designer-workflow-detail.md +69 -0
  57. package/project-template/.claude/agents/refs/implementation-plan-guide.md +316 -0
  58. package/project-template/.claude/agents/refs/reviewer-convergence-eval.md +247 -33
  59. package/project-template/.claude/agents/refs/reviewer-legacy-fallback.md +14 -0
  60. package/project-template/.claude/agents/refs/skill-selector-guide.md +465 -0
  61. package/project-template/.claude/agents/refs/skill-value-layers.md +145 -0
  62. package/project-template/.claude/agents/refs/storyboard-generation-guide.md +110 -0
  63. package/project-template/.claude/agents/refs/ta-atlas-deliverable-standard.md +4 -4
  64. package/project-template/.claude/agents/refs/ta-pipeline-cookbook.md +101 -104
  65. package/project-template/.claude/agents/refs/technical-artist-legacy-fallback.md +14 -0
  66. package/project-template/.claude/agents/reviewer.md +81 -95
  67. package/project-template/.claude/agents/technical-artist.md +71 -95
  68. package/project-template/.claude/hooks/README.md +83 -35
  69. package/project-template/.claude/hooks/asr-coverage-validate.mjs +19 -19
  70. package/project-template/.claude/hooks/block-developer-preflight.mjs +185 -0
  71. package/project-template/.claude/hooks/block-ring1-tasklist.mjs +95 -0
  72. package/project-template/.claude/hooks/gate-dispatcher.mjs +78 -0
  73. package/project-template/.claude/hooks/gate-runner.mjs +557 -0
  74. package/project-template/.claude/hooks/gate.mjs +170 -0
  75. package/project-template/.claude/hooks/snapshot-milestone.mjs +246 -0
  76. package/project-template/.claude/hooks/user-prompt.mjs +193 -0
  77. package/project-template/.claude/hooks/validate-atom-tree-selection.mjs +281 -0
  78. package/project-template/.claude/hooks/validate-workflow-stop.mjs +1535 -95
  79. package/project-template/.claude/settings.json +54 -9
  80. package/project-template/.claude/skills/brainstorming/SKILL.md +161 -0
  81. package/project-template/.claude/skills/brainstorming/scripts/frame-template.html +270 -0
  82. package/project-template/.claude/skills/brainstorming/scripts/helper.js +177 -0
  83. package/project-template/.claude/skills/brainstorming/scripts/server.cjs +354 -0
  84. package/project-template/.claude/skills/brainstorming/scripts/start-server.sh +148 -0
  85. package/project-template/.claude/skills/brainstorming/scripts/stop-server.sh +56 -0
  86. package/project-template/.claude/skills/brainstorming/scripts/wait-for-selection.sh +62 -0
  87. package/project-template/.claude/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
  88. package/project-template/.claude/skills/brainstorming/visual-companion.md +309 -0
  89. package/project-template/.claude/skills/playcraft-ad-psychology/SKILL.md +3 -3
  90. package/project-template/.claude/skills/playcraft-art-style-guide/SKILL.md +3 -3
  91. package/project-template/.claude/skills/playcraft-asset-state-sheet/SKILL.md +35 -25
  92. package/project-template/.claude/skills/playcraft-audio-generation/SKILL.md +15 -15
  93. package/project-template/.claude/skills/playcraft-build-optimizer/SKILL.md +5 -5
  94. package/project-template/.claude/skills/playcraft-image-generation/SKILL.md +5 -5
  95. package/project-template/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +5 -5
  96. package/project-template/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +116 -27
  97. package/project-template/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +1 -1
  98. package/project-template/.claude/skills/playcraft-image-processing/SKILL.md +219 -0
  99. package/project-template/.claude/skills/playcraft-playable-optimization/SKILL.md +161 -0
  100. package/project-template/.claude/skills/playcraft-research/SKILL.md +24 -21
  101. package/project-template/.claude/skills/playcraft-skill-recommender/SKILL.md +331 -0
  102. package/project-template/.claude/skills/playcraft-sprite-generation/SKILL.md +48 -48
  103. package/project-template/.claude/skills/playcraft-sprite-remix/SKILL.md +158 -0
  104. package/project-template/.claude/skills/playcraft-sprite-sheet/SKILL.md +100 -0
  105. package/project-template/.claude/skills/playcraft-storyboard/SKILL.md +4 -4
  106. package/project-template/.claude/skills/playcraft-style-qa/SKILL.md +45 -45
  107. package/project-template/.claude/skills/playcraft-text-rendering/SKILL.md +27 -27
  108. package/project-template/.claude/skills/session-analyzer/SKILL.md +386 -0
  109. package/project-template/.claude/skills/session-analyzer/scripts/execution-breakdown.mjs +182 -0
  110. package/project-template/.claude/skills/session-analyzer/scripts/find-turns.mjs +72 -0
  111. package/project-template/.claude/skills/session-analyzer/scripts/heavy-output.mjs +121 -0
  112. package/project-template/.claude/skills/session-analyzer/scripts/resolve-session.mjs +103 -0
  113. package/project-template/.claude/skills/session-analyzer/scripts/subagent-stats.mjs +127 -0
  114. package/project-template/.claude/skills/session-analyzer/scripts/subagent-tool-timeline.mjs +106 -0
  115. package/project-template/.claude/skills/session-analyzer/scripts/time-gaps.mjs +128 -0
  116. package/project-template/.claude/skills/session-analyzer/scripts/turn-timeline.mjs +67 -0
  117. package/project-template/.claude/snapshot.mjs +350 -0
  118. package/project-template/.codebuddy/settings.json +53 -0
  119. package/project-template/.cursor/hooks.json +1 -1
  120. package/project-template/.cursor/rules/playcraft-orchestrator.mdc +91 -86
  121. package/project-template/.cursor/rules/playcraft-subagent-boundary.mdc +16 -5
  122. package/project-template/CHANGELOG.md +105 -0
  123. package/project-template/CLAUDE.md +58 -254
  124. package/project-template/docs/DESIGN.md +65 -0
  125. package/project-template/docs/intent-clarifications.md +58 -0
  126. package/project-template/docs/pipeline-overview.md +69 -0
  127. package/project-template/docs/project-state.md +211 -0
  128. package/project-template/docs/team/agent-conduct.md +51 -105
  129. package/project-template/docs/team/agent-runtime-matrix.md +60 -74
  130. package/project-template/docs/team/atom-tree-format.md +169 -0
  131. package/project-template/docs/team/collaboration.md +319 -225
  132. package/project-template/docs/team/core-model.md +80 -46
  133. package/project-template/docs/team/game-designer-migration-todo.md +8 -0
  134. package/project-template/docs/team/harness-legacy-deprecation.md +23 -0
  135. package/project-template/docs/team/platform-capabilities.md +16 -13
  136. package/project-template/docs/team/workflow-changelog.md +95 -23
  137. package/project-template/docs/team/workflow-consistency-checklist.md +93 -45
  138. package/project-template/focus-lab/.gitkeep +0 -0
  139. package/project-template/game/.playcraft-scaffold-pending +0 -0
  140. package/project-template/game/index.ts +18 -0
  141. package/project-template/globals.d.ts +51 -0
  142. package/project-template/index.css +34 -0
  143. package/project-template/index.html +18 -0
  144. package/project-template/main.ts +9 -0
  145. package/project-template/package.json +79 -0
  146. package/project-template/skills/README.md +52 -0
  147. package/project-template/skills/_shared/agent-prep.md +136 -0
  148. package/project-template/skills/_shared/requirements.txt +1 -0
  149. package/project-template/skills/_shared/scripts/build-evidence-gate.mjs +87 -0
  150. package/project-template/skills/_shared/scripts/context-budget.mjs +215 -0
  151. package/project-template/skills/_shared/scripts/create-playable.mjs +140 -0
  152. package/project-template/skills/_shared/scripts/dev-start.mjs +151 -0
  153. package/project-template/skills/_shared/scripts/disclosure-config.mjs +480 -0
  154. package/project-template/skills/_shared/scripts/ensure-project.mjs +532 -0
  155. package/project-template/skills/_shared/scripts/gen-placeholder-audio.py +345 -0
  156. package/project-template/skills/_shared/scripts/gen-placeholder.py +244 -0
  157. package/project-template/skills/_shared/scripts/harness-smoke.mjs +257 -0
  158. package/project-template/skills/_shared/scripts/lib/validator-artifacts.mjs +129 -0
  159. package/project-template/skills/_shared/scripts/placeholder-pack-sheet.mjs +67 -0
  160. package/project-template/skills/_shared/scripts/placeholder_audio_lib.py +142 -0
  161. package/project-template/skills/_shared/scripts/placeholder_lib.py +993 -0
  162. package/project-template/skills/_shared/scripts/render-project-state.mjs +278 -0
  163. package/project-template/skills/_shared/scripts/ring-config.mjs +252 -0
  164. package/project-template/skills/_shared/scripts/skills-check.mjs +176 -0
  165. package/project-template/skills/_shared/scripts/slice-set.mjs +77 -0
  166. package/project-template/skills/_shared/scripts/state-advance-ring.mjs +63 -0
  167. package/project-template/skills/_shared/scripts/state-get.mjs +215 -0
  168. package/project-template/skills/_shared/scripts/state-handoff.mjs +120 -0
  169. package/project-template/skills/_shared/scripts/state-set.mjs +113 -0
  170. package/project-template/skills/_shared/scripts/state-store.mjs +893 -0
  171. package/project-template/skills/_shared/scripts/sync-template-skills.mjs +112 -0
  172. package/project-template/skills/_shared/scripts/verify-asset-code-sync.mjs +265 -0
  173. package/project-template/skills/_shared/scripts/verify-atom-conformance.mjs +181 -0
  174. package/project-template/skills/_shared/scripts/verify-env.mjs +285 -0
  175. package/project-template/skills/_shared/scripts/verify-placeholders.mjs +161 -0
  176. package/project-template/skills/_shared/scripts/workflow-doctor.mjs +348 -0
  177. package/project-template/skills/playable-animate/SKILL.md +52 -0
  178. package/project-template/skills/playable-animate/agents/openai.yaml +4 -0
  179. package/project-template/skills/playable-animate/references/board-refresh.md +30 -0
  180. package/project-template/skills/playable-animate/references/diagnosis-checklist.md +25 -0
  181. package/project-template/skills/playable-animate/references/entrance-sequencing.md +33 -0
  182. package/project-template/skills/playable-animate/references/interaction-timing.md +23 -0
  183. package/project-template/skills/playable-art/SKILL.md +203 -0
  184. package/project-template/skills/playable-art/agents/openai.yaml +4 -0
  185. package/project-template/skills/playable-art/references/alpha-postprocess.md +46 -0
  186. package/project-template/skills/playable-art/references/cta-art-spec.md +59 -0
  187. package/project-template/skills/playable-art/references/layout-proportions.md +30 -0
  188. package/project-template/skills/playable-art/references/prompt-patterns.md +83 -0
  189. package/project-template/skills/playable-art/references/reference-comparison.md +30 -0
  190. package/project-template/skills/playable-art/references/sheet-import-v2.md +91 -0
  191. package/project-template/skills/playable-art/scripts/build-atlas.py +332 -0
  192. package/project-template/skills/playable-art/scripts/chroma-key.py +50 -0
  193. package/project-template/skills/playable-art/scripts/extract-alpha-split.py +65 -0
  194. package/project-template/skills/playable-art/scripts/extract-dual-bg-alpha.py +118 -0
  195. package/project-template/skills/playable-art/scripts/import-gpt-art-sheets-v2.py +403 -0
  196. package/project-template/skills/playable-art/scripts/import-gpt-art-sheets.py +280 -0
  197. package/project-template/skills/playable-art/scripts/import-gpt-tile-sheet.py +114 -0
  198. package/project-template/skills/playable-art/scripts/import_gpt_art_pipeline.py +321 -0
  199. package/project-template/skills/playable-art/scripts/import_gpt_art_sheets_v2_test.py +126 -0
  200. package/project-template/skills/playable-art/scripts/placeholder_common.py +98 -0
  201. package/project-template/skills/playable-art/scripts/remove-bg.py +91 -0
  202. package/project-template/skills/playable-art/scripts/review-processed-assets.py +468 -0
  203. package/project-template/skills/playable-art/scripts/review_processed_assets_test.py +116 -0
  204. package/project-template/skills/playable-art/scripts/verify-alpha-clean.py +105 -0
  205. package/project-template/skills/playable-debug/SKILL.md +116 -0
  206. package/project-template/skills/playable-debug/agents/openai.yaml +4 -0
  207. package/project-template/skills/playable-debug/references/debug-config.md +40 -0
  208. package/project-template/skills/playable-focus/SKILL.md +148 -0
  209. package/project-template/skills/playable-focus/scripts/bootstrap-playground.mjs +84 -0
  210. package/project-template/skills/playable-focus/scripts/extract-focus-frames.mjs +87 -0
  211. package/project-template/skills/playable-focus/scripts/generate-focus-reports.mjs +121 -0
  212. package/project-template/skills/playable-focus/scripts/playground.mjs +390 -0
  213. package/project-template/skills/playable-focus/templates/focus-lab/frame.html +39 -0
  214. package/project-template/skills/playable-focus/templates/focus-lab/harness/clean-stage.js +114 -0
  215. package/project-template/skills/playable-focus/templates/focus-lab/harness/frame-lab-scene.js +94 -0
  216. package/project-template/skills/playable-focus/templates/focus-lab/harness/particle-lab-scene.js +224 -0
  217. package/project-template/skills/playable-focus/templates/focus-lab/model.html +16 -0
  218. package/project-template/skills/playable-focus/templates/focus-lab/particle.html +38 -0
  219. package/project-template/skills/playable-focus/templates/focus-lab/shatter.html +47 -0
  220. package/project-template/skills/playable-focus/templates/playground/registry.template.json +55 -0
  221. package/project-template/skills/playable-focus/templates/playground/vfx-catalog.template.json +280 -0
  222. package/project-template/skills/playable-fx-decompose/SKILL.md +212 -0
  223. package/project-template/skills/playable-fx-decompose/examples.md +89 -0
  224. package/project-template/skills/playable-fx-decompose/reference.md +201 -0
  225. package/project-template/skills/playable-fx-decompose/requirements.txt +2 -0
  226. package/project-template/skills/playable-fx-decompose/scripts/build-blank-tile-crack.py +192 -0
  227. package/project-template/skills/playable-fx-decompose/scripts/fix-shard-debris-frames.py +60 -0
  228. package/project-template/skills/playable-fx-decompose/scripts/generate-shard-debris.py +276 -0
  229. package/project-template/skills/playable-fx-peak/SKILL.md +237 -0
  230. package/project-template/skills/playable-fx-peak/requirements.txt +2 -0
  231. package/project-template/skills/playable-fx-peak/scripts/fix-frame-edges.py +70 -0
  232. package/project-template/skills/playable-fx-peak/scripts/repack-frame-sequence.py +526 -0
  233. package/project-template/skills/playable-fx-peak/scripts/validate-frame-anchors.py +130 -0
  234. package/project-template/skills/playable-placeholder/SKILL.md +239 -0
  235. package/project-template/skills/playable-record/SKILL.md +166 -0
  236. package/project-template/skills/playable-record/scripts/lib/build-artifact.mjs +92 -0
  237. package/project-template/skills/playable-record/scripts/lib/dev-server.mjs +104 -0
  238. package/project-template/skills/playable-record/scripts/lib/record-audio-bridge.js +141 -0
  239. package/project-template/skills/playable-record/scripts/lib/slice-structure-verify.mjs +199 -0
  240. package/project-template/skills/playable-record/scripts/record-playable.mjs +583 -0
  241. package/project-template/skills/playable-record/scripts/verify-build.mjs +185 -0
  242. package/project-template/skills/playable-record/scripts/verify-contract.mjs +261 -0
  243. package/project-template/skills/playable-record/scripts/verify-firstwin.mjs +398 -0
  244. package/project-template/skills/playable-record/scripts/verify-fusion.mjs +320 -0
  245. package/project-template/skills/playable-record/scripts/verify-lifecycle.mjs +78 -0
  246. package/project-template/skills/playable-record/scripts/verify-slice-artist.mjs +53 -0
  247. package/project-template/skills/playable-record/scripts/verify-slice-ta.mjs +53 -0
  248. package/project-template/skills/playable-record/scripts/verify-slice.mjs +142 -0
  249. package/project-template/skills/playable-record/scripts/verify-visual-ring.mjs +250 -0
  250. package/project-template/skills/playable-record/scripts/verify-visual-ring1.mjs +190 -0
  251. package/project-template/skills/playable-record/scripts/verify-vlm-video.mjs +227 -0
  252. package/project-template/skills/playable-validate/SKILL.md +260 -0
  253. package/project-template/skills/playable-validate/references/checklist-detail.md +36 -0
  254. package/project-template/skills/playable-validate/references/single-html-bundle.md +76 -0
  255. package/project-template/skills/playable-validate/validation-rules.md +200 -0
  256. package/project-template/skills/playable-verify-ui/SKILL.md +295 -0
  257. package/project-template/skills/playable-verify-ui/examples/asset-manifest.example.json +36 -0
  258. package/project-template/skills/playable-verify-ui/examples/mahjong-match.profile.yaml +334 -0
  259. package/project-template/skills/playable-verify-ui/profiles/template.profile.yaml +84 -0
  260. package/project-template/skills/playable-verify-ui/reference.md +165 -0
  261. package/project-template/skills/playable-verify-ui/references/phaser-patterns.md +67 -0
  262. package/project-template/skills/playable-verify-ui/references/scaling-decision-tree.md +51 -0
  263. package/project-template/skills/playable-verify-ui/requirements.txt +7 -0
  264. package/project-template/skills/playable-verify-ui/schema/asset-manifest.schema.json +68 -0
  265. package/project-template/skills/playable-verify-ui/schema/playable-ui-profile.schema.json +171 -0
  266. package/project-template/skills/playable-verify-ui/scripts/asset_manifest.py +231 -0
  267. package/project-template/skills/playable-verify-ui/scripts/lib/__init__.py +1 -0
  268. package/project-template/skills/playable-verify-ui/scripts/lib/config_expr.js +218 -0
  269. package/project-template/skills/playable-verify-ui/scripts/lib/node_utils.js +51 -0
  270. package/project-template/skills/playable-verify-ui/scripts/lib/profile_loader.py +59 -0
  271. package/project-template/skills/playable-verify-ui/scripts/lib/report.py +106 -0
  272. package/project-template/skills/playable-verify-ui/scripts/lib/runtime_contract.js +116 -0
  273. package/project-template/skills/playable-verify-ui/scripts/measure_frame_content.py +77 -0
  274. package/project-template/skills/playable-verify-ui/scripts/run_all.py +265 -0
  275. package/project-template/skills/playable-verify-ui/scripts/verify_asset_sizes.py +77 -0
  276. package/project-template/skills/playable-verify-ui/scripts/verify_assets_present.py +62 -0
  277. package/project-template/skills/playable-verify-ui/scripts/verify_atlas_budget.py +84 -0
  278. package/project-template/skills/playable-verify-ui/scripts/verify_atlas_frames.py +79 -0
  279. package/project-template/skills/playable-verify-ui/scripts/verify_bg_clean.py +365 -0
  280. package/project-template/skills/playable-verify-ui/scripts/verify_doc_asset_sync.py +90 -0
  281. package/project-template/skills/playable-verify-ui/scripts/verify_fetch_antipatterns.py +59 -0
  282. package/project-template/skills/playable-verify-ui/scripts/verify_game_config_load.js +54 -0
  283. package/project-template/skills/playable-verify-ui/scripts/verify_hardcoded_layout.js +64 -0
  284. package/project-template/skills/playable-verify-ui/scripts/verify_layout_regions.js +110 -0
  285. package/project-template/skills/playable-verify-ui/scripts/verify_profile_schema.py +37 -0
  286. package/project-template/skills/playable-verify-ui/scripts/verify_ring1_visual.py +211 -0
  287. package/project-template/skills/playable-verify-ui/scripts/verify_runtime_contract.js +58 -0
  288. package/project-template/skills/playable-verify-ui/scripts/verify_script_load_order.js +73 -0
  289. package/project-template/skills/playable-verify-ui/scripts/verify_slice_plan.py +238 -0
  290. package/project-template/skills/playable-verify-ui/scripts/verify_slice_plan_test.py +125 -0
  291. package/project-template/skills/playable-verify-ui/scripts/verify_text_overlap.py +333 -0
  292. package/project-template/skills/playable-verify-ui/scripts/verify_tile_consistency.py +323 -0
  293. package/project-template/skills/playable-verify-ui/scripts/verify_vision_evidence.py +894 -0
  294. package/project-template/skills/playable-verify-ui/scripts/verify_vision_evidence_test.py +122 -0
  295. package/project-template/skills/playable-verify-ui/scripts/verify_visual.py +422 -0
  296. package/project-template/templates/{designer-log.template.md → artist-log.template.md} +26 -31
  297. package/project-template/templates/atom-tree.template.json +133 -0
  298. package/project-template/templates/design-brief.template.md +59 -162
  299. package/project-template/templates/design-lens-checklist.reference.md +14 -14
  300. package/project-template/templates/design-methodology.md +25 -25
  301. package/project-template/templates/design.template.md +50 -0
  302. package/project-template/templates/developer-log.template.md +187 -63
  303. package/project-template/templates/five-axis-framework.md +89 -44
  304. package/project-template/templates/gen-placeholder-audio.template.mjs +63 -0
  305. package/project-template/templates/gen-placeholders.template.mjs +81 -0
  306. package/project-template/templates/intent-clarifications.template.md +7 -7
  307. package/project-template/templates/layout-spec.template.md +32 -20
  308. package/project-template/templates/plan.template.md +80 -0
  309. package/project-template/templates/project-state.template.md +90 -191
  310. package/project-template/templates/review-report.template.md +208 -24
  311. package/project-template/templates/style-exploration.template.md +8 -8
  312. package/project-template/templates/ta-log.template.md +58 -35
  313. package/project-template/tsconfig.json +20 -0
  314. package/project-template/vite.config.ts +27 -0
  315. package/project-templates/phaser/.claude/agents/artist.md +101 -0
  316. package/project-templates/phaser/.claude/agents/developer.md +123 -0
  317. package/project-templates/phaser/.claude/agents/game-designer.md +192 -0
  318. package/project-templates/phaser/.claude/agents/refs/README.md +77 -0
  319. package/project-templates/phaser/.claude/agents/refs/artist-art-style-catalog.md +533 -0
  320. package/project-templates/phaser/.claude/agents/refs/artist-color-audio-recipes.md +153 -0
  321. package/project-templates/phaser/.claude/agents/refs/artist-deliverable-spec.md +230 -0
  322. package/project-templates/phaser/.claude/agents/refs/artist-dimension-axis.md +27 -0
  323. package/project-templates/phaser/.claude/agents/refs/artist-handoff-v2-checklist.md +76 -0
  324. package/project-templates/phaser/.claude/agents/refs/artist-legacy-fallback.md +14 -0
  325. package/project-templates/phaser/.claude/agents/refs/artist-master-composite-recipes.md +208 -0
  326. package/project-templates/phaser/.claude/agents/refs/artist-style-exploration-flow.md +55 -0
  327. package/project-templates/phaser/.claude/agents/refs/developer-dev-handoff.md +152 -0
  328. package/project-templates/phaser/.claude/agents/refs/developer-impl-cookbook.md +432 -0
  329. package/project-templates/phaser/.claude/agents/refs/developer-legacy-fallback.md +15 -0
  330. package/project-templates/phaser/.claude/agents/refs/developer-phase1-flow.md +404 -0
  331. package/project-templates/phaser/.claude/agents/refs/framework-5-component-filter.md +252 -0
  332. package/project-templates/phaser/.claude/agents/refs/framework-game-feel-juice.md +266 -0
  333. package/project-templates/phaser/.claude/agents/refs/framework-mda.md +147 -0
  334. package/project-templates/phaser/.claude/agents/refs/game-designer-gameplay-sufficiency.md +123 -0
  335. package/project-templates/phaser/.claude/agents/refs/game-designer-legacy-fallback.md +15 -0
  336. package/project-templates/phaser/.claude/agents/refs/game-designer-workflow-detail.md +69 -0
  337. package/project-templates/phaser/.claude/agents/refs/implementation-plan-guide.md +309 -0
  338. package/project-templates/phaser/.claude/agents/refs/reviewer-convergence-eval.md +350 -0
  339. package/project-templates/phaser/.claude/agents/refs/reviewer-legacy-fallback.md +14 -0
  340. package/project-templates/phaser/.claude/agents/refs/reviewer-six-dimension-eval.md +6 -0
  341. package/project-templates/phaser/.claude/agents/refs/skill-selector-guide.md +465 -0
  342. package/project-templates/phaser/.claude/agents/refs/skill-value-layers.md +145 -0
  343. package/project-templates/phaser/.claude/agents/refs/storyboard-generation-guide.md +110 -0
  344. package/project-templates/phaser/.claude/agents/refs/ta-3d-flip-recipe.md +88 -0
  345. package/project-templates/phaser/.claude/agents/refs/ta-atlas-deliverable-standard.md +67 -0
  346. package/project-templates/phaser/.claude/agents/refs/ta-batch-pipeline-recipes.md +120 -0
  347. package/project-templates/phaser/.claude/agents/refs/ta-image-generation-detail.md +300 -0
  348. package/project-templates/phaser/.claude/agents/refs/ta-image-ops-reference.md +495 -0
  349. package/project-templates/phaser/.claude/agents/refs/ta-pipeline-cookbook.md +1141 -0
  350. package/project-templates/phaser/.claude/agents/refs/ta-tools-reference.md +111 -0
  351. package/project-templates/phaser/.claude/agents/refs/ta-vfx-preset-catalog.md +365 -0
  352. package/project-templates/phaser/.claude/agents/refs/technical-artist-legacy-fallback.md +14 -0
  353. package/project-templates/phaser/.claude/agents/reviewer.md +116 -0
  354. package/project-templates/phaser/.claude/agents/technical-artist.md +100 -0
  355. package/project-templates/phaser/.claude/hooks/README.md +120 -0
  356. package/project-templates/phaser/.claude/hooks/asr-coverage-validate.mjs +381 -0
  357. package/project-templates/phaser/.claude/hooks/block-developer-preflight.mjs +185 -0
  358. package/project-templates/phaser/.claude/hooks/block-ring1-tasklist.mjs +95 -0
  359. package/project-templates/phaser/.claude/hooks/gate-dispatcher.mjs +78 -0
  360. package/project-templates/phaser/.claude/hooks/gate-runner.mjs +557 -0
  361. package/project-templates/phaser/.claude/hooks/gate.mjs +171 -0
  362. package/project-templates/phaser/.claude/hooks/snapshot-milestone.mjs +247 -0
  363. package/project-templates/phaser/.claude/hooks/user-prompt.mjs +194 -0
  364. package/project-templates/phaser/.claude/hooks/validate-atom-tree-selection.mjs +281 -0
  365. package/project-templates/phaser/.claude/hooks/validate-workflow-stop.mjs +1889 -0
  366. package/project-templates/phaser/.claude/settings.json +81 -0
  367. package/project-templates/phaser/.claude/skills/brainstorming/SKILL.md +161 -0
  368. package/project-templates/phaser/.claude/skills/brainstorming/scripts/frame-template.html +270 -0
  369. package/project-templates/phaser/.claude/skills/brainstorming/scripts/helper.js +177 -0
  370. package/project-templates/phaser/.claude/skills/brainstorming/scripts/server.cjs +354 -0
  371. package/project-templates/phaser/.claude/skills/brainstorming/scripts/start-server.sh +148 -0
  372. package/project-templates/phaser/.claude/skills/brainstorming/scripts/stop-server.sh +56 -0
  373. package/project-templates/phaser/.claude/skills/brainstorming/scripts/wait-for-selection.sh +62 -0
  374. package/project-templates/phaser/.claude/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
  375. package/project-templates/phaser/.claude/skills/brainstorming/visual-companion.md +309 -0
  376. package/project-templates/phaser/.claude/skills/playcraft-ad-psychology/SKILL.md +182 -0
  377. package/project-templates/phaser/.claude/skills/playcraft-art-style-guide/SKILL.md +123 -0
  378. package/project-templates/phaser/.claude/skills/playcraft-asset-state-sheet/SKILL.md +205 -0
  379. package/project-templates/phaser/.claude/skills/playcraft-audio-generation/SKILL.md +280 -0
  380. package/project-templates/phaser/.claude/skills/playcraft-batch-pipeline/SKILL.md +184 -0
  381. package/project-templates/phaser/.claude/skills/playcraft-build-optimizer/SKILL.md +306 -0
  382. package/project-templates/phaser/.claude/skills/playcraft-image-generation/SKILL.md +298 -0
  383. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +123 -0
  384. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +254 -0
  385. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +324 -0
  386. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +97 -0
  387. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +118 -0
  388. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +137 -0
  389. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +397 -0
  390. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +296 -0
  391. package/project-templates/phaser/.claude/skills/playcraft-image-ops/SKILL.md +122 -0
  392. package/project-templates/phaser/.claude/skills/playcraft-image-processing/SKILL.md +219 -0
  393. package/project-templates/phaser/.claude/skills/playcraft-masking/SKILL.md +373 -0
  394. package/project-templates/phaser/.claude/skills/playcraft-playable-optimization/SKILL.md +161 -0
  395. package/project-templates/phaser/.claude/skills/playcraft-research/SKILL.md +215 -0
  396. package/project-templates/phaser/.claude/skills/playcraft-skill-recommender/SKILL.md +331 -0
  397. package/project-templates/phaser/.claude/skills/playcraft-sprite-generation/SKILL.md +423 -0
  398. package/project-templates/phaser/.claude/skills/playcraft-sprite-remix/SKILL.md +158 -0
  399. package/project-templates/phaser/.claude/skills/playcraft-sprite-sheet/SKILL.md +100 -0
  400. package/project-templates/phaser/.claude/skills/playcraft-storyboard/SKILL.md +167 -0
  401. package/project-templates/phaser/.claude/skills/playcraft-style-qa/SKILL.md +270 -0
  402. package/project-templates/phaser/.claude/skills/playcraft-text-rendering/SKILL.md +236 -0
  403. package/project-templates/phaser/.claude/skills/playcraft-vfx-animation/SKILL.md +130 -0
  404. package/project-templates/phaser/.claude/skills/playwright-cli/SKILL.md +390 -0
  405. package/project-templates/phaser/.claude/skills/playwright-cli/references/element-attributes.md +23 -0
  406. package/project-templates/phaser/.claude/skills/playwright-cli/references/playwright-tests.md +39 -0
  407. package/project-templates/phaser/.claude/skills/playwright-cli/references/request-mocking.md +87 -0
  408. package/project-templates/phaser/.claude/skills/playwright-cli/references/running-code.md +240 -0
  409. package/project-templates/phaser/.claude/skills/playwright-cli/references/session-management.md +226 -0
  410. package/project-templates/phaser/.claude/skills/playwright-cli/references/spec-driven-testing.md +308 -0
  411. package/project-templates/phaser/.claude/skills/playwright-cli/references/storage-state.md +275 -0
  412. package/project-templates/phaser/.claude/skills/playwright-cli/references/test-generation.md +134 -0
  413. package/project-templates/phaser/.claude/skills/playwright-cli/references/tracing.md +142 -0
  414. package/project-templates/phaser/.claude/skills/playwright-cli/references/video-recording.md +153 -0
  415. package/project-templates/phaser/.claude/skills/session-analyzer/SKILL.md +386 -0
  416. package/project-templates/phaser/.claude/skills/session-analyzer/scripts/execution-breakdown.mjs +182 -0
  417. package/project-templates/phaser/.claude/skills/session-analyzer/scripts/find-turns.mjs +72 -0
  418. package/project-templates/phaser/.claude/skills/session-analyzer/scripts/heavy-output.mjs +121 -0
  419. package/project-templates/phaser/.claude/skills/session-analyzer/scripts/resolve-session.mjs +103 -0
  420. package/project-templates/phaser/.claude/skills/session-analyzer/scripts/subagent-stats.mjs +127 -0
  421. package/project-templates/phaser/.claude/skills/session-analyzer/scripts/subagent-tool-timeline.mjs +106 -0
  422. package/project-templates/phaser/.claude/skills/session-analyzer/scripts/time-gaps.mjs +128 -0
  423. package/project-templates/phaser/.claude/skills/session-analyzer/scripts/turn-timeline.mjs +67 -0
  424. package/project-templates/phaser/.claude/snapshot.mjs +257 -0
  425. package/project-templates/phaser/.cursor/hooks.json +17 -0
  426. package/project-templates/phaser/.cursor/rules/playcraft-orchestrator.mdc +142 -0
  427. package/project-templates/phaser/.cursor/rules/playcraft-subagent-boundary.mdc +29 -0
  428. package/project-templates/phaser/.playcraft-engine +1 -0
  429. package/project-templates/phaser/CHANGELOG.md +105 -0
  430. package/project-templates/phaser/CLAUDE.md +84 -0
  431. package/project-templates/phaser/assets/audio/bgm/.gitkeep +0 -0
  432. package/project-templates/phaser/assets/audio/sfx/.gitkeep +0 -0
  433. package/project-templates/phaser/assets/bundles/.gitkeep +0 -0
  434. package/project-templates/phaser/assets/images/bg/.gitkeep +0 -0
  435. package/project-templates/phaser/assets/images/reference/.gitkeep +0 -0
  436. package/project-templates/phaser/assets/images/storyboard/.gitkeep +0 -0
  437. package/project-templates/phaser/assets/images/tiles/.gitkeep +0 -0
  438. package/project-templates/phaser/assets/images/ui/.gitkeep +0 -0
  439. package/project-templates/phaser/assets/images/vfx/.gitkeep +0 -0
  440. package/project-templates/phaser/assets/models/.gitkeep +0 -0
  441. package/project-templates/phaser/docs/DESIGN.md +65 -0
  442. package/project-templates/phaser/docs/intent-clarifications.md +58 -0
  443. package/project-templates/phaser/docs/pipeline-overview.md +69 -0
  444. package/project-templates/phaser/docs/project-state.md +211 -0
  445. package/project-templates/phaser/docs/scaffold-manifest.md +10 -0
  446. package/project-templates/phaser/docs/team/agent-conduct.md +67 -0
  447. package/project-templates/phaser/docs/team/agent-runtime-matrix.md +80 -0
  448. package/project-templates/phaser/docs/team/atom-tree-format.md +114 -0
  449. package/project-templates/phaser/docs/team/collaboration.md +391 -0
  450. package/project-templates/phaser/docs/team/core-model.md +85 -0
  451. package/project-templates/phaser/docs/team/game-designer-migration-todo.md +8 -0
  452. package/project-templates/phaser/docs/team/harness-legacy-deprecation.md +23 -0
  453. package/project-templates/phaser/docs/team/platform-capabilities.md +18 -0
  454. package/project-templates/phaser/docs/team/workflow-changelog.md +137 -0
  455. package/project-templates/phaser/docs/team/workflow-consistency-checklist.md +240 -0
  456. package/project-templates/phaser/focus-lab/.gitkeep +0 -0
  457. package/project-templates/phaser/game/adapters/phaser.ts +52 -0
  458. package/project-templates/phaser/game/config/.gitkeep +0 -0
  459. package/project-templates/phaser/game/config/game-config.ts +46 -0
  460. package/project-templates/phaser/game/contract/publish.ts +141 -0
  461. package/project-templates/phaser/game/contract/types.ts +34 -0
  462. package/project-templates/phaser/game/gameplay/.gitkeep +0 -0
  463. package/project-templates/phaser/game/index.ts +81 -0
  464. package/project-templates/phaser/game/runtime-contract.ts +28 -0
  465. package/project-templates/phaser/game/scenes/.gitkeep +0 -0
  466. package/project-templates/phaser/globals.d.ts +51 -0
  467. package/project-templates/phaser/index.css +34 -0
  468. package/project-templates/phaser/index.html +18 -0
  469. package/project-templates/phaser/main.ts +9 -0
  470. package/project-templates/phaser/package.json +79 -0
  471. package/project-templates/phaser/skills/README.md +52 -0
  472. package/project-templates/phaser/skills/_shared/agent-prep.md +136 -0
  473. package/project-templates/phaser/skills/_shared/requirements.txt +1 -0
  474. package/project-templates/phaser/skills/_shared/scripts/build-evidence-gate.mjs +87 -0
  475. package/project-templates/phaser/skills/_shared/scripts/context-budget.mjs +215 -0
  476. package/project-templates/phaser/skills/_shared/scripts/create-playable.mjs +140 -0
  477. package/project-templates/phaser/skills/_shared/scripts/dev-start.mjs +151 -0
  478. package/project-templates/phaser/skills/_shared/scripts/disclosure-config.mjs +480 -0
  479. package/project-templates/phaser/skills/_shared/scripts/ensure-project.mjs +532 -0
  480. package/project-templates/phaser/skills/_shared/scripts/gen-placeholder-audio.py +345 -0
  481. package/project-templates/phaser/skills/_shared/scripts/gen-placeholder.py +244 -0
  482. package/project-templates/phaser/skills/_shared/scripts/harness-smoke.mjs +257 -0
  483. package/project-templates/phaser/skills/_shared/scripts/lib/validator-artifacts.mjs +129 -0
  484. package/project-templates/phaser/skills/_shared/scripts/placeholder-pack-sheet.mjs +67 -0
  485. package/project-templates/phaser/skills/_shared/scripts/placeholder_audio_lib.py +142 -0
  486. package/project-templates/phaser/skills/_shared/scripts/placeholder_lib.py +993 -0
  487. package/project-templates/phaser/skills/_shared/scripts/render-project-state.mjs +278 -0
  488. package/project-templates/phaser/skills/_shared/scripts/ring-config.mjs +252 -0
  489. package/project-templates/phaser/skills/_shared/scripts/skills-check.mjs +176 -0
  490. package/project-templates/phaser/skills/_shared/scripts/slice-set.mjs +77 -0
  491. package/project-templates/phaser/skills/_shared/scripts/state-advance-ring.mjs +63 -0
  492. package/project-templates/phaser/skills/_shared/scripts/state-get.mjs +215 -0
  493. package/project-templates/phaser/skills/_shared/scripts/state-handoff.mjs +120 -0
  494. package/project-templates/phaser/skills/_shared/scripts/state-set.mjs +113 -0
  495. package/project-templates/phaser/skills/_shared/scripts/state-store.mjs +893 -0
  496. package/project-templates/phaser/skills/_shared/scripts/sync-template-skills.mjs +112 -0
  497. package/project-templates/phaser/skills/_shared/scripts/verify-asset-code-sync.mjs +265 -0
  498. package/project-templates/phaser/skills/_shared/scripts/verify-atom-conformance.mjs +181 -0
  499. package/project-templates/phaser/skills/_shared/scripts/verify-env.mjs +285 -0
  500. package/project-templates/phaser/skills/_shared/scripts/verify-placeholders.mjs +161 -0
  501. package/project-templates/phaser/skills/_shared/scripts/workflow-doctor.mjs +348 -0
  502. package/project-templates/phaser/skills/playable-animate/SKILL.md +52 -0
  503. package/project-templates/phaser/skills/playable-animate/agents/openai.yaml +4 -0
  504. package/project-templates/phaser/skills/playable-animate/references/board-refresh.md +30 -0
  505. package/project-templates/phaser/skills/playable-animate/references/diagnosis-checklist.md +25 -0
  506. package/project-templates/phaser/skills/playable-animate/references/entrance-sequencing.md +33 -0
  507. package/project-templates/phaser/skills/playable-animate/references/interaction-timing.md +23 -0
  508. package/project-templates/phaser/skills/playable-art/SKILL.md +203 -0
  509. package/project-templates/phaser/skills/playable-art/agents/openai.yaml +4 -0
  510. package/project-templates/phaser/skills/playable-art/references/alpha-postprocess.md +46 -0
  511. package/project-templates/phaser/skills/playable-art/references/cta-art-spec.md +59 -0
  512. package/project-templates/phaser/skills/playable-art/references/layout-proportions.md +30 -0
  513. package/project-templates/phaser/skills/playable-art/references/prompt-patterns.md +83 -0
  514. package/project-templates/phaser/skills/playable-art/references/reference-comparison.md +30 -0
  515. package/project-templates/phaser/skills/playable-art/references/sheet-import-v2.md +91 -0
  516. package/project-templates/phaser/skills/playable-art/scripts/build-atlas.py +332 -0
  517. package/project-templates/phaser/skills/playable-art/scripts/chroma-key.py +50 -0
  518. package/project-templates/phaser/skills/playable-art/scripts/extract-alpha-split.py +65 -0
  519. package/project-templates/phaser/skills/playable-art/scripts/extract-dual-bg-alpha.py +118 -0
  520. package/project-templates/phaser/skills/playable-art/scripts/import-gpt-art-sheets-v2.py +403 -0
  521. package/project-templates/phaser/skills/playable-art/scripts/import-gpt-art-sheets.py +280 -0
  522. package/project-templates/phaser/skills/playable-art/scripts/import-gpt-tile-sheet.py +114 -0
  523. package/project-templates/phaser/skills/playable-art/scripts/import_gpt_art_pipeline.py +321 -0
  524. package/project-templates/phaser/skills/playable-art/scripts/import_gpt_art_sheets_v2_test.py +126 -0
  525. package/project-templates/phaser/skills/playable-art/scripts/placeholder_common.py +98 -0
  526. package/project-templates/phaser/skills/playable-art/scripts/remove-bg.py +91 -0
  527. package/project-templates/phaser/skills/playable-art/scripts/review-processed-assets.py +468 -0
  528. package/project-templates/phaser/skills/playable-art/scripts/review_processed_assets_test.py +116 -0
  529. package/project-templates/phaser/skills/playable-art/scripts/verify-alpha-clean.py +105 -0
  530. package/project-templates/phaser/skills/playable-debug/SKILL.md +116 -0
  531. package/project-templates/phaser/skills/playable-debug/agents/openai.yaml +4 -0
  532. package/project-templates/phaser/skills/playable-debug/references/debug-config.md +40 -0
  533. package/project-templates/phaser/skills/playable-focus/SKILL.md +148 -0
  534. package/project-templates/phaser/skills/playable-focus/scripts/bootstrap-playground.mjs +84 -0
  535. package/project-templates/phaser/skills/playable-focus/scripts/extract-focus-frames.mjs +87 -0
  536. package/project-templates/phaser/skills/playable-focus/scripts/generate-focus-reports.mjs +121 -0
  537. package/project-templates/phaser/skills/playable-focus/scripts/playground.mjs +390 -0
  538. package/project-templates/phaser/skills/playable-focus/templates/focus-lab/frame.html +39 -0
  539. package/project-templates/phaser/skills/playable-focus/templates/focus-lab/harness/clean-stage.js +114 -0
  540. package/project-templates/phaser/skills/playable-focus/templates/focus-lab/harness/frame-lab-scene.js +94 -0
  541. package/project-templates/phaser/skills/playable-focus/templates/focus-lab/harness/particle-lab-scene.js +224 -0
  542. package/project-templates/phaser/skills/playable-focus/templates/focus-lab/model.html +16 -0
  543. package/project-templates/phaser/skills/playable-focus/templates/focus-lab/particle.html +38 -0
  544. package/project-templates/phaser/skills/playable-focus/templates/focus-lab/shatter.html +47 -0
  545. package/project-templates/phaser/skills/playable-fx-decompose/SKILL.md +212 -0
  546. package/project-templates/phaser/skills/playable-fx-decompose/examples.md +89 -0
  547. package/project-templates/phaser/skills/playable-fx-decompose/reference.md +201 -0
  548. package/project-templates/phaser/skills/playable-fx-decompose/requirements.txt +2 -0
  549. package/project-templates/phaser/skills/playable-fx-decompose/scripts/build-blank-tile-crack.py +192 -0
  550. package/project-templates/phaser/skills/playable-fx-decompose/scripts/fix-shard-debris-frames.py +60 -0
  551. package/project-templates/phaser/skills/playable-fx-decompose/scripts/generate-shard-debris.py +276 -0
  552. package/project-templates/phaser/skills/playable-fx-peak/SKILL.md +237 -0
  553. package/project-templates/phaser/skills/playable-fx-peak/requirements.txt +2 -0
  554. package/project-templates/phaser/skills/playable-fx-peak/scripts/fix-frame-edges.py +70 -0
  555. package/project-templates/phaser/skills/playable-fx-peak/scripts/repack-frame-sequence.py +526 -0
  556. package/project-templates/phaser/skills/playable-fx-peak/scripts/validate-frame-anchors.py +130 -0
  557. package/project-templates/phaser/skills/playable-placeholder/SKILL.md +239 -0
  558. package/project-templates/phaser/skills/playable-record/SKILL.md +166 -0
  559. package/project-templates/phaser/skills/playable-record/scripts/lib/build-artifact.mjs +92 -0
  560. package/project-templates/phaser/skills/playable-record/scripts/lib/dev-server.mjs +104 -0
  561. package/project-templates/phaser/skills/playable-record/scripts/lib/record-audio-bridge.js +141 -0
  562. package/project-templates/phaser/skills/playable-record/scripts/lib/slice-structure-verify.mjs +199 -0
  563. package/project-templates/phaser/skills/playable-record/scripts/record-playable.mjs +583 -0
  564. package/project-templates/phaser/skills/playable-record/scripts/verify-build.mjs +185 -0
  565. package/project-templates/phaser/skills/playable-record/scripts/verify-contract.mjs +261 -0
  566. package/project-templates/phaser/skills/playable-record/scripts/verify-firstwin.mjs +398 -0
  567. package/project-templates/phaser/skills/playable-record/scripts/verify-fusion.mjs +320 -0
  568. package/project-templates/phaser/skills/playable-record/scripts/verify-lifecycle.mjs +78 -0
  569. package/project-templates/phaser/skills/playable-record/scripts/verify-slice-artist.mjs +53 -0
  570. package/project-templates/phaser/skills/playable-record/scripts/verify-slice-ta.mjs +53 -0
  571. package/project-templates/phaser/skills/playable-record/scripts/verify-slice.mjs +142 -0
  572. package/project-templates/phaser/skills/playable-record/scripts/verify-visual-ring.mjs +250 -0
  573. package/project-templates/phaser/skills/playable-record/scripts/verify-visual-ring1.mjs +190 -0
  574. package/project-templates/phaser/skills/playable-record/scripts/verify-vlm-video.mjs +227 -0
  575. package/project-templates/phaser/skills/playable-validate/SKILL.md +260 -0
  576. package/project-templates/phaser/skills/playable-validate/references/checklist-detail.md +36 -0
  577. package/project-templates/phaser/skills/playable-validate/references/single-html-bundle.md +76 -0
  578. package/project-templates/phaser/skills/playable-validate/validation-rules.md +200 -0
  579. package/project-templates/phaser/skills/playable-verify-ui/SKILL.md +295 -0
  580. package/project-templates/phaser/skills/playable-verify-ui/examples/asset-manifest.example.json +36 -0
  581. package/project-templates/phaser/skills/playable-verify-ui/examples/mahjong-match.profile.yaml +334 -0
  582. package/project-templates/phaser/skills/playable-verify-ui/profiles/template.profile.yaml +84 -0
  583. package/project-templates/phaser/skills/playable-verify-ui/reference.md +165 -0
  584. package/project-templates/phaser/skills/playable-verify-ui/references/phaser-patterns.md +67 -0
  585. package/project-templates/phaser/skills/playable-verify-ui/references/scaling-decision-tree.md +51 -0
  586. package/project-templates/phaser/skills/playable-verify-ui/requirements.txt +7 -0
  587. package/project-templates/phaser/skills/playable-verify-ui/schema/asset-manifest.schema.json +68 -0
  588. package/project-templates/phaser/skills/playable-verify-ui/schema/playable-ui-profile.schema.json +171 -0
  589. package/project-templates/phaser/skills/playable-verify-ui/scripts/asset_manifest.py +231 -0
  590. package/project-templates/phaser/skills/playable-verify-ui/scripts/lib/__init__.py +1 -0
  591. package/project-templates/phaser/skills/playable-verify-ui/scripts/lib/config_expr.js +218 -0
  592. package/project-templates/phaser/skills/playable-verify-ui/scripts/lib/node_utils.js +51 -0
  593. package/project-templates/phaser/skills/playable-verify-ui/scripts/lib/profile_loader.py +59 -0
  594. package/project-templates/phaser/skills/playable-verify-ui/scripts/lib/report.py +106 -0
  595. package/project-templates/phaser/skills/playable-verify-ui/scripts/lib/runtime_contract.js +116 -0
  596. package/project-templates/phaser/skills/playable-verify-ui/scripts/measure_frame_content.py +77 -0
  597. package/project-templates/phaser/skills/playable-verify-ui/scripts/run_all.py +265 -0
  598. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_asset_sizes.py +77 -0
  599. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_assets_present.py +62 -0
  600. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_atlas_budget.py +84 -0
  601. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_atlas_frames.py +79 -0
  602. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_bg_clean.py +365 -0
  603. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_doc_asset_sync.py +90 -0
  604. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_fetch_antipatterns.py +59 -0
  605. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_game_config_load.js +54 -0
  606. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_hardcoded_layout.js +64 -0
  607. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_layout_regions.js +110 -0
  608. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_profile_schema.py +37 -0
  609. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_ring1_visual.py +211 -0
  610. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_runtime_contract.js +58 -0
  611. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_script_load_order.js +73 -0
  612. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_slice_plan.py +238 -0
  613. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_slice_plan_test.py +125 -0
  614. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_text_overlap.py +333 -0
  615. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_tile_consistency.py +323 -0
  616. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_vision_evidence.py +894 -0
  617. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_vision_evidence_test.py +122 -0
  618. package/project-templates/phaser/skills/playable-verify-ui/scripts/verify_visual.py +422 -0
  619. package/project-templates/phaser/ta-workspace/scripts/.gitkeep +0 -0
  620. package/project-templates/phaser/templates/artist-log.template.md +182 -0
  621. package/project-templates/phaser/templates/atom-tree.template.json +133 -0
  622. package/project-templates/phaser/templates/design-brief.template.md +92 -0
  623. package/project-templates/phaser/templates/design-lens-checklist.reference.md +117 -0
  624. package/project-templates/phaser/templates/design-methodology.md +99 -0
  625. package/project-templates/phaser/templates/design.template.md +50 -0
  626. package/project-templates/phaser/templates/developer-log.template.md +258 -0
  627. package/project-templates/phaser/templates/five-axis-framework.md +194 -0
  628. package/project-templates/phaser/templates/gen-placeholder-audio.template.mjs +63 -0
  629. package/project-templates/phaser/templates/gen-placeholders.template.mjs +81 -0
  630. package/project-templates/phaser/templates/intent-clarifications.template.md +58 -0
  631. package/project-templates/phaser/templates/layout-spec.template.md +198 -0
  632. package/project-templates/phaser/templates/plan.template.md +80 -0
  633. package/project-templates/phaser/templates/project-state.template.md +136 -0
  634. package/project-templates/phaser/templates/review-report.template.md +275 -0
  635. package/project-templates/phaser/templates/style-exploration.template.md +93 -0
  636. package/project-templates/phaser/templates/ta-log.template.md +394 -0
  637. package/project-templates/phaser/tsconfig.json +20 -0
  638. package/project-templates/phaser/vite.config.ts +27 -0
  639. package/project-templates/threejs/.claude/agents/artist.md +101 -0
  640. package/project-templates/threejs/.claude/agents/developer.md +123 -0
  641. package/project-templates/threejs/.claude/agents/game-designer.md +192 -0
  642. package/project-templates/threejs/.claude/agents/refs/README.md +77 -0
  643. package/project-templates/threejs/.claude/agents/refs/artist-art-style-catalog.md +533 -0
  644. package/project-templates/threejs/.claude/agents/refs/artist-color-audio-recipes.md +153 -0
  645. package/project-templates/threejs/.claude/agents/refs/artist-deliverable-spec.md +230 -0
  646. package/project-templates/threejs/.claude/agents/refs/artist-dimension-axis.md +27 -0
  647. package/project-templates/threejs/.claude/agents/refs/artist-handoff-v2-checklist.md +76 -0
  648. package/project-templates/threejs/.claude/agents/refs/artist-legacy-fallback.md +14 -0
  649. package/project-templates/threejs/.claude/agents/refs/artist-master-composite-recipes.md +208 -0
  650. package/project-templates/threejs/.claude/agents/refs/artist-style-exploration-flow.md +55 -0
  651. package/project-templates/threejs/.claude/agents/refs/developer-dev-handoff.md +152 -0
  652. package/project-templates/threejs/.claude/agents/refs/developer-impl-cookbook.md +432 -0
  653. package/project-templates/threejs/.claude/agents/refs/developer-legacy-fallback.md +15 -0
  654. package/project-templates/threejs/.claude/agents/refs/developer-phase1-flow.md +404 -0
  655. package/project-templates/threejs/.claude/agents/refs/framework-5-component-filter.md +252 -0
  656. package/project-templates/threejs/.claude/agents/refs/framework-game-feel-juice.md +266 -0
  657. package/project-templates/threejs/.claude/agents/refs/framework-mda.md +147 -0
  658. package/project-templates/threejs/.claude/agents/refs/game-designer-gameplay-sufficiency.md +123 -0
  659. package/project-templates/threejs/.claude/agents/refs/game-designer-legacy-fallback.md +15 -0
  660. package/project-templates/threejs/.claude/agents/refs/game-designer-workflow-detail.md +69 -0
  661. package/project-templates/threejs/.claude/agents/refs/implementation-plan-guide.md +309 -0
  662. package/project-templates/threejs/.claude/agents/refs/reviewer-convergence-eval.md +350 -0
  663. package/project-templates/threejs/.claude/agents/refs/reviewer-legacy-fallback.md +14 -0
  664. package/project-templates/threejs/.claude/agents/refs/reviewer-six-dimension-eval.md +6 -0
  665. package/project-templates/threejs/.claude/agents/refs/skill-selector-guide.md +465 -0
  666. package/project-templates/threejs/.claude/agents/refs/skill-value-layers.md +145 -0
  667. package/project-templates/threejs/.claude/agents/refs/storyboard-generation-guide.md +110 -0
  668. package/project-templates/threejs/.claude/agents/refs/ta-3d-flip-recipe.md +88 -0
  669. package/project-templates/threejs/.claude/agents/refs/ta-atlas-deliverable-standard.md +67 -0
  670. package/project-templates/threejs/.claude/agents/refs/ta-batch-pipeline-recipes.md +120 -0
  671. package/project-templates/threejs/.claude/agents/refs/ta-image-generation-detail.md +300 -0
  672. package/project-templates/threejs/.claude/agents/refs/ta-image-ops-reference.md +495 -0
  673. package/project-templates/threejs/.claude/agents/refs/ta-pipeline-cookbook.md +1141 -0
  674. package/project-templates/threejs/.claude/agents/refs/ta-tools-reference.md +111 -0
  675. package/project-templates/threejs/.claude/agents/refs/ta-vfx-preset-catalog.md +365 -0
  676. package/project-templates/threejs/.claude/agents/refs/technical-artist-legacy-fallback.md +14 -0
  677. package/project-templates/threejs/.claude/agents/reviewer.md +116 -0
  678. package/project-templates/threejs/.claude/agents/technical-artist.md +100 -0
  679. package/project-templates/threejs/.claude/hooks/README.md +120 -0
  680. package/project-templates/threejs/.claude/hooks/asr-coverage-validate.mjs +381 -0
  681. package/project-templates/threejs/.claude/hooks/block-developer-preflight.mjs +185 -0
  682. package/project-templates/threejs/.claude/hooks/block-ring1-tasklist.mjs +95 -0
  683. package/project-templates/threejs/.claude/hooks/gate-dispatcher.mjs +78 -0
  684. package/project-templates/threejs/.claude/hooks/gate-runner.mjs +557 -0
  685. package/project-templates/threejs/.claude/hooks/gate.mjs +171 -0
  686. package/project-templates/threejs/.claude/hooks/snapshot-milestone.mjs +247 -0
  687. package/project-templates/threejs/.claude/hooks/user-prompt.mjs +194 -0
  688. package/project-templates/threejs/.claude/hooks/validate-atom-tree-selection.mjs +281 -0
  689. package/project-templates/threejs/.claude/hooks/validate-workflow-stop.mjs +1889 -0
  690. package/project-templates/threejs/.claude/settings.json +81 -0
  691. package/project-templates/threejs/.claude/skills/brainstorming/SKILL.md +161 -0
  692. package/project-templates/threejs/.claude/skills/brainstorming/scripts/frame-template.html +270 -0
  693. package/project-templates/threejs/.claude/skills/brainstorming/scripts/helper.js +177 -0
  694. package/project-templates/threejs/.claude/skills/brainstorming/scripts/server.cjs +354 -0
  695. package/project-templates/threejs/.claude/skills/brainstorming/scripts/start-server.sh +148 -0
  696. package/project-templates/threejs/.claude/skills/brainstorming/scripts/stop-server.sh +56 -0
  697. package/project-templates/threejs/.claude/skills/brainstorming/scripts/wait-for-selection.sh +62 -0
  698. package/project-templates/threejs/.claude/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
  699. package/project-templates/threejs/.claude/skills/brainstorming/visual-companion.md +309 -0
  700. package/project-templates/threejs/.claude/skills/playcraft-ad-psychology/SKILL.md +182 -0
  701. package/project-templates/threejs/.claude/skills/playcraft-art-style-guide/SKILL.md +123 -0
  702. package/project-templates/threejs/.claude/skills/playcraft-asset-state-sheet/SKILL.md +205 -0
  703. package/project-templates/threejs/.claude/skills/playcraft-audio-generation/SKILL.md +280 -0
  704. package/project-templates/threejs/.claude/skills/playcraft-batch-pipeline/SKILL.md +184 -0
  705. package/project-templates/threejs/.claude/skills/playcraft-build-optimizer/SKILL.md +306 -0
  706. package/project-templates/threejs/.claude/skills/playcraft-image-generation/SKILL.md +298 -0
  707. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +123 -0
  708. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +254 -0
  709. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +324 -0
  710. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +97 -0
  711. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +118 -0
  712. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +137 -0
  713. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +397 -0
  714. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +296 -0
  715. package/project-templates/threejs/.claude/skills/playcraft-image-ops/SKILL.md +122 -0
  716. package/project-templates/threejs/.claude/skills/playcraft-image-processing/SKILL.md +219 -0
  717. package/project-templates/threejs/.claude/skills/playcraft-masking/SKILL.md +373 -0
  718. package/project-templates/threejs/.claude/skills/playcraft-playable-optimization/SKILL.md +161 -0
  719. package/project-templates/threejs/.claude/skills/playcraft-research/SKILL.md +215 -0
  720. package/project-templates/threejs/.claude/skills/playcraft-skill-recommender/SKILL.md +331 -0
  721. package/project-templates/threejs/.claude/skills/playcraft-sprite-generation/SKILL.md +423 -0
  722. package/project-templates/threejs/.claude/skills/playcraft-sprite-remix/SKILL.md +158 -0
  723. package/project-templates/threejs/.claude/skills/playcraft-sprite-sheet/SKILL.md +100 -0
  724. package/project-templates/threejs/.claude/skills/playcraft-storyboard/SKILL.md +167 -0
  725. package/project-templates/threejs/.claude/skills/playcraft-style-qa/SKILL.md +270 -0
  726. package/project-templates/threejs/.claude/skills/playcraft-text-rendering/SKILL.md +236 -0
  727. package/project-templates/threejs/.claude/skills/playcraft-vfx-animation/SKILL.md +130 -0
  728. package/project-templates/threejs/.claude/skills/playwright-cli/SKILL.md +390 -0
  729. package/project-templates/threejs/.claude/skills/playwright-cli/references/element-attributes.md +23 -0
  730. package/project-templates/threejs/.claude/skills/playwright-cli/references/playwright-tests.md +39 -0
  731. package/project-templates/threejs/.claude/skills/playwright-cli/references/request-mocking.md +87 -0
  732. package/project-templates/threejs/.claude/skills/playwright-cli/references/running-code.md +240 -0
  733. package/project-templates/threejs/.claude/skills/playwright-cli/references/session-management.md +226 -0
  734. package/project-templates/threejs/.claude/skills/playwright-cli/references/spec-driven-testing.md +308 -0
  735. package/project-templates/threejs/.claude/skills/playwright-cli/references/storage-state.md +275 -0
  736. package/project-templates/threejs/.claude/skills/playwright-cli/references/test-generation.md +134 -0
  737. package/project-templates/threejs/.claude/skills/playwright-cli/references/tracing.md +142 -0
  738. package/project-templates/threejs/.claude/skills/playwright-cli/references/video-recording.md +153 -0
  739. package/project-templates/threejs/.claude/skills/session-analyzer/SKILL.md +386 -0
  740. package/project-templates/threejs/.claude/skills/session-analyzer/scripts/execution-breakdown.mjs +182 -0
  741. package/project-templates/threejs/.claude/skills/session-analyzer/scripts/find-turns.mjs +72 -0
  742. package/project-templates/threejs/.claude/skills/session-analyzer/scripts/heavy-output.mjs +121 -0
  743. package/project-templates/threejs/.claude/skills/session-analyzer/scripts/resolve-session.mjs +103 -0
  744. package/project-templates/threejs/.claude/skills/session-analyzer/scripts/subagent-stats.mjs +127 -0
  745. package/project-templates/threejs/.claude/skills/session-analyzer/scripts/subagent-tool-timeline.mjs +106 -0
  746. package/project-templates/threejs/.claude/skills/session-analyzer/scripts/time-gaps.mjs +128 -0
  747. package/project-templates/threejs/.claude/skills/session-analyzer/scripts/turn-timeline.mjs +67 -0
  748. package/project-templates/threejs/.claude/snapshot.mjs +257 -0
  749. package/project-templates/threejs/.cursor/hooks.json +17 -0
  750. package/project-templates/threejs/.cursor/rules/playcraft-orchestrator.mdc +142 -0
  751. package/project-templates/threejs/.cursor/rules/playcraft-subagent-boundary.mdc +29 -0
  752. package/project-templates/threejs/.playcraft-engine +1 -0
  753. package/project-templates/threejs/CHANGELOG.md +105 -0
  754. package/project-templates/threejs/CLAUDE.md +84 -0
  755. package/project-templates/threejs/assets/audio/bgm/.gitkeep +0 -0
  756. package/project-templates/threejs/assets/audio/sfx/.gitkeep +0 -0
  757. package/project-templates/threejs/assets/bundles/.gitkeep +0 -0
  758. package/project-templates/threejs/assets/images/bg/.gitkeep +0 -0
  759. package/project-templates/threejs/assets/images/reference/.gitkeep +0 -0
  760. package/project-templates/threejs/assets/images/storyboard/.gitkeep +0 -0
  761. package/project-templates/threejs/assets/images/tiles/.gitkeep +0 -0
  762. package/project-templates/threejs/assets/images/ui/.gitkeep +0 -0
  763. package/project-templates/threejs/assets/images/vfx/.gitkeep +0 -0
  764. package/project-templates/threejs/assets/models/.gitkeep +0 -0
  765. package/project-templates/threejs/docs/DESIGN.md +65 -0
  766. package/project-templates/threejs/docs/intent-clarifications.md +58 -0
  767. package/project-templates/threejs/docs/pipeline-overview.md +69 -0
  768. package/project-templates/threejs/docs/project-state.md +211 -0
  769. package/project-templates/threejs/docs/scaffold-manifest.md +10 -0
  770. package/project-templates/threejs/docs/team/agent-conduct.md +67 -0
  771. package/project-templates/threejs/docs/team/agent-runtime-matrix.md +80 -0
  772. package/project-templates/threejs/docs/team/atom-tree-format.md +114 -0
  773. package/project-templates/threejs/docs/team/collaboration.md +391 -0
  774. package/project-templates/threejs/docs/team/core-model.md +85 -0
  775. package/project-templates/threejs/docs/team/game-designer-migration-todo.md +8 -0
  776. package/project-templates/threejs/docs/team/harness-legacy-deprecation.md +23 -0
  777. package/project-templates/threejs/docs/team/platform-capabilities.md +18 -0
  778. package/project-templates/threejs/docs/team/workflow-changelog.md +137 -0
  779. package/project-templates/threejs/docs/team/workflow-consistency-checklist.md +240 -0
  780. package/project-templates/threejs/focus-lab/.gitkeep +0 -0
  781. package/project-templates/threejs/game/config/.gitkeep +0 -0
  782. package/project-templates/threejs/game/config/game-config.ts +46 -0
  783. package/project-templates/threejs/game/contract/publish.ts +141 -0
  784. package/project-templates/threejs/game/contract/types.ts +34 -0
  785. package/project-templates/threejs/game/gameplay/.gitkeep +0 -0
  786. package/project-templates/threejs/game/index.ts +76 -0
  787. package/project-templates/threejs/game/runtime-contract.ts +15 -0
  788. package/project-templates/threejs/game/scenes/.gitkeep +0 -0
  789. package/project-templates/threejs/globals.d.ts +51 -0
  790. package/project-templates/threejs/index.css +34 -0
  791. package/project-templates/threejs/index.html +18 -0
  792. package/project-templates/threejs/main.ts +9 -0
  793. package/project-templates/threejs/package.json +79 -0
  794. package/project-templates/threejs/skills/README.md +52 -0
  795. package/project-templates/threejs/skills/_shared/agent-prep.md +136 -0
  796. package/project-templates/threejs/skills/_shared/requirements.txt +1 -0
  797. package/project-templates/threejs/skills/_shared/scripts/build-evidence-gate.mjs +87 -0
  798. package/project-templates/threejs/skills/_shared/scripts/context-budget.mjs +215 -0
  799. package/project-templates/threejs/skills/_shared/scripts/create-playable.mjs +140 -0
  800. package/project-templates/threejs/skills/_shared/scripts/dev-start.mjs +151 -0
  801. package/project-templates/threejs/skills/_shared/scripts/disclosure-config.mjs +480 -0
  802. package/project-templates/threejs/skills/_shared/scripts/ensure-project.mjs +532 -0
  803. package/project-templates/threejs/skills/_shared/scripts/gen-placeholder-audio.py +345 -0
  804. package/project-templates/threejs/skills/_shared/scripts/gen-placeholder.py +244 -0
  805. package/project-templates/threejs/skills/_shared/scripts/harness-smoke.mjs +257 -0
  806. package/project-templates/threejs/skills/_shared/scripts/lib/validator-artifacts.mjs +129 -0
  807. package/project-templates/threejs/skills/_shared/scripts/placeholder-pack-sheet.mjs +67 -0
  808. package/project-templates/threejs/skills/_shared/scripts/placeholder_audio_lib.py +142 -0
  809. package/project-templates/threejs/skills/_shared/scripts/placeholder_lib.py +993 -0
  810. package/project-templates/threejs/skills/_shared/scripts/render-project-state.mjs +278 -0
  811. package/project-templates/threejs/skills/_shared/scripts/ring-config.mjs +252 -0
  812. package/project-templates/threejs/skills/_shared/scripts/skills-check.mjs +176 -0
  813. package/project-templates/threejs/skills/_shared/scripts/slice-set.mjs +77 -0
  814. package/project-templates/threejs/skills/_shared/scripts/state-advance-ring.mjs +63 -0
  815. package/project-templates/threejs/skills/_shared/scripts/state-get.mjs +215 -0
  816. package/project-templates/threejs/skills/_shared/scripts/state-handoff.mjs +120 -0
  817. package/project-templates/threejs/skills/_shared/scripts/state-set.mjs +113 -0
  818. package/project-templates/threejs/skills/_shared/scripts/state-store.mjs +893 -0
  819. package/project-templates/threejs/skills/_shared/scripts/sync-template-skills.mjs +112 -0
  820. package/project-templates/threejs/skills/_shared/scripts/verify-asset-code-sync.mjs +265 -0
  821. package/project-templates/threejs/skills/_shared/scripts/verify-atom-conformance.mjs +181 -0
  822. package/project-templates/threejs/skills/_shared/scripts/verify-env.mjs +285 -0
  823. package/project-templates/threejs/skills/_shared/scripts/verify-placeholders.mjs +161 -0
  824. package/project-templates/threejs/skills/_shared/scripts/workflow-doctor.mjs +348 -0
  825. package/project-templates/threejs/skills/playable-animate/SKILL.md +52 -0
  826. package/project-templates/threejs/skills/playable-animate/agents/openai.yaml +4 -0
  827. package/project-templates/threejs/skills/playable-animate/references/board-refresh.md +30 -0
  828. package/project-templates/threejs/skills/playable-animate/references/diagnosis-checklist.md +25 -0
  829. package/project-templates/threejs/skills/playable-animate/references/entrance-sequencing.md +33 -0
  830. package/project-templates/threejs/skills/playable-animate/references/interaction-timing.md +23 -0
  831. package/project-templates/threejs/skills/playable-art/SKILL.md +203 -0
  832. package/project-templates/threejs/skills/playable-art/agents/openai.yaml +4 -0
  833. package/project-templates/threejs/skills/playable-art/references/alpha-postprocess.md +46 -0
  834. package/project-templates/threejs/skills/playable-art/references/cta-art-spec.md +59 -0
  835. package/project-templates/threejs/skills/playable-art/references/layout-proportions.md +30 -0
  836. package/project-templates/threejs/skills/playable-art/references/prompt-patterns.md +83 -0
  837. package/project-templates/threejs/skills/playable-art/references/reference-comparison.md +30 -0
  838. package/project-templates/threejs/skills/playable-art/references/sheet-import-v2.md +91 -0
  839. package/project-templates/threejs/skills/playable-art/scripts/build-atlas.py +332 -0
  840. package/project-templates/threejs/skills/playable-art/scripts/chroma-key.py +50 -0
  841. package/project-templates/threejs/skills/playable-art/scripts/extract-alpha-split.py +65 -0
  842. package/project-templates/threejs/skills/playable-art/scripts/extract-dual-bg-alpha.py +118 -0
  843. package/project-templates/threejs/skills/playable-art/scripts/import-gpt-art-sheets-v2.py +403 -0
  844. package/project-templates/threejs/skills/playable-art/scripts/import-gpt-art-sheets.py +280 -0
  845. package/project-templates/threejs/skills/playable-art/scripts/import-gpt-tile-sheet.py +114 -0
  846. package/project-templates/threejs/skills/playable-art/scripts/import_gpt_art_pipeline.py +321 -0
  847. package/project-templates/threejs/skills/playable-art/scripts/import_gpt_art_sheets_v2_test.py +126 -0
  848. package/project-templates/threejs/skills/playable-art/scripts/placeholder_common.py +98 -0
  849. package/project-templates/threejs/skills/playable-art/scripts/remove-bg.py +91 -0
  850. package/project-templates/threejs/skills/playable-art/scripts/review-processed-assets.py +468 -0
  851. package/project-templates/threejs/skills/playable-art/scripts/review_processed_assets_test.py +116 -0
  852. package/project-templates/threejs/skills/playable-art/scripts/verify-alpha-clean.py +105 -0
  853. package/project-templates/threejs/skills/playable-debug/SKILL.md +116 -0
  854. package/project-templates/threejs/skills/playable-debug/agents/openai.yaml +4 -0
  855. package/project-templates/threejs/skills/playable-debug/references/debug-config.md +40 -0
  856. package/project-templates/threejs/skills/playable-focus/SKILL.md +148 -0
  857. package/project-templates/threejs/skills/playable-focus/scripts/bootstrap-playground.mjs +84 -0
  858. package/project-templates/threejs/skills/playable-focus/scripts/extract-focus-frames.mjs +87 -0
  859. package/project-templates/threejs/skills/playable-focus/scripts/generate-focus-reports.mjs +121 -0
  860. package/project-templates/threejs/skills/playable-focus/scripts/playground.mjs +390 -0
  861. package/project-templates/threejs/skills/playable-focus/templates/focus-lab/frame.html +39 -0
  862. package/project-templates/threejs/skills/playable-focus/templates/focus-lab/harness/clean-stage.js +114 -0
  863. package/project-templates/threejs/skills/playable-focus/templates/focus-lab/harness/frame-lab-scene.js +94 -0
  864. package/project-templates/threejs/skills/playable-focus/templates/focus-lab/harness/particle-lab-scene.js +224 -0
  865. package/project-templates/threejs/skills/playable-focus/templates/focus-lab/model.html +16 -0
  866. package/project-templates/threejs/skills/playable-focus/templates/focus-lab/particle.html +38 -0
  867. package/project-templates/threejs/skills/playable-focus/templates/focus-lab/shatter.html +47 -0
  868. package/project-templates/threejs/skills/playable-fx-decompose/SKILL.md +212 -0
  869. package/project-templates/threejs/skills/playable-fx-decompose/examples.md +89 -0
  870. package/project-templates/threejs/skills/playable-fx-decompose/reference.md +201 -0
  871. package/project-templates/threejs/skills/playable-fx-decompose/requirements.txt +2 -0
  872. package/project-templates/threejs/skills/playable-fx-decompose/scripts/build-blank-tile-crack.py +192 -0
  873. package/project-templates/threejs/skills/playable-fx-decompose/scripts/fix-shard-debris-frames.py +60 -0
  874. package/project-templates/threejs/skills/playable-fx-decompose/scripts/generate-shard-debris.py +276 -0
  875. package/project-templates/threejs/skills/playable-fx-peak/SKILL.md +237 -0
  876. package/project-templates/threejs/skills/playable-fx-peak/requirements.txt +2 -0
  877. package/project-templates/threejs/skills/playable-fx-peak/scripts/fix-frame-edges.py +70 -0
  878. package/project-templates/threejs/skills/playable-fx-peak/scripts/repack-frame-sequence.py +526 -0
  879. package/project-templates/threejs/skills/playable-fx-peak/scripts/validate-frame-anchors.py +130 -0
  880. package/project-templates/threejs/skills/playable-placeholder/SKILL.md +239 -0
  881. package/project-templates/threejs/skills/playable-record/SKILL.md +166 -0
  882. package/project-templates/threejs/skills/playable-record/scripts/lib/build-artifact.mjs +92 -0
  883. package/project-templates/threejs/skills/playable-record/scripts/lib/dev-server.mjs +104 -0
  884. package/project-templates/threejs/skills/playable-record/scripts/lib/record-audio-bridge.js +141 -0
  885. package/project-templates/threejs/skills/playable-record/scripts/lib/slice-structure-verify.mjs +199 -0
  886. package/project-templates/threejs/skills/playable-record/scripts/record-playable.mjs +583 -0
  887. package/project-templates/threejs/skills/playable-record/scripts/verify-build.mjs +185 -0
  888. package/project-templates/threejs/skills/playable-record/scripts/verify-contract.mjs +261 -0
  889. package/project-templates/threejs/skills/playable-record/scripts/verify-firstwin.mjs +398 -0
  890. package/project-templates/threejs/skills/playable-record/scripts/verify-fusion.mjs +320 -0
  891. package/project-templates/threejs/skills/playable-record/scripts/verify-lifecycle.mjs +78 -0
  892. package/project-templates/threejs/skills/playable-record/scripts/verify-slice-artist.mjs +53 -0
  893. package/project-templates/threejs/skills/playable-record/scripts/verify-slice-ta.mjs +53 -0
  894. package/project-templates/threejs/skills/playable-record/scripts/verify-slice.mjs +142 -0
  895. package/project-templates/threejs/skills/playable-record/scripts/verify-visual-ring.mjs +250 -0
  896. package/project-templates/threejs/skills/playable-record/scripts/verify-visual-ring1.mjs +190 -0
  897. package/project-templates/threejs/skills/playable-record/scripts/verify-vlm-video.mjs +227 -0
  898. package/project-templates/threejs/skills/playable-validate/SKILL.md +260 -0
  899. package/project-templates/threejs/skills/playable-validate/references/checklist-detail.md +36 -0
  900. package/project-templates/threejs/skills/playable-validate/references/single-html-bundle.md +76 -0
  901. package/project-templates/threejs/skills/playable-validate/validation-rules.md +200 -0
  902. package/project-templates/threejs/skills/playable-verify-ui/SKILL.md +295 -0
  903. package/project-templates/threejs/skills/playable-verify-ui/examples/asset-manifest.example.json +36 -0
  904. package/project-templates/threejs/skills/playable-verify-ui/examples/mahjong-match.profile.yaml +334 -0
  905. package/project-templates/threejs/skills/playable-verify-ui/profiles/template.profile.yaml +84 -0
  906. package/project-templates/threejs/skills/playable-verify-ui/reference.md +165 -0
  907. package/project-templates/threejs/skills/playable-verify-ui/references/phaser-patterns.md +67 -0
  908. package/project-templates/threejs/skills/playable-verify-ui/references/scaling-decision-tree.md +51 -0
  909. package/project-templates/threejs/skills/playable-verify-ui/requirements.txt +7 -0
  910. package/project-templates/threejs/skills/playable-verify-ui/schema/asset-manifest.schema.json +68 -0
  911. package/project-templates/threejs/skills/playable-verify-ui/schema/playable-ui-profile.schema.json +171 -0
  912. package/project-templates/threejs/skills/playable-verify-ui/scripts/asset_manifest.py +231 -0
  913. package/project-templates/threejs/skills/playable-verify-ui/scripts/lib/__init__.py +1 -0
  914. package/project-templates/threejs/skills/playable-verify-ui/scripts/lib/config_expr.js +218 -0
  915. package/project-templates/threejs/skills/playable-verify-ui/scripts/lib/node_utils.js +51 -0
  916. package/project-templates/threejs/skills/playable-verify-ui/scripts/lib/profile_loader.py +59 -0
  917. package/project-templates/threejs/skills/playable-verify-ui/scripts/lib/report.py +106 -0
  918. package/project-templates/threejs/skills/playable-verify-ui/scripts/lib/runtime_contract.js +116 -0
  919. package/project-templates/threejs/skills/playable-verify-ui/scripts/measure_frame_content.py +77 -0
  920. package/project-templates/threejs/skills/playable-verify-ui/scripts/run_all.py +265 -0
  921. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_asset_sizes.py +77 -0
  922. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_assets_present.py +62 -0
  923. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_atlas_budget.py +84 -0
  924. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_atlas_frames.py +79 -0
  925. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_bg_clean.py +365 -0
  926. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_doc_asset_sync.py +90 -0
  927. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_fetch_antipatterns.py +59 -0
  928. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_game_config_load.js +54 -0
  929. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_hardcoded_layout.js +64 -0
  930. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_layout_regions.js +110 -0
  931. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_profile_schema.py +37 -0
  932. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_ring1_visual.py +211 -0
  933. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_runtime_contract.js +58 -0
  934. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_script_load_order.js +73 -0
  935. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_slice_plan.py +238 -0
  936. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_slice_plan_test.py +125 -0
  937. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_text_overlap.py +333 -0
  938. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_tile_consistency.py +323 -0
  939. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_vision_evidence.py +894 -0
  940. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_vision_evidence_test.py +122 -0
  941. package/project-templates/threejs/skills/playable-verify-ui/scripts/verify_visual.py +422 -0
  942. package/project-templates/threejs/ta-workspace/scripts/.gitkeep +0 -0
  943. package/project-templates/threejs/templates/artist-log.template.md +182 -0
  944. package/project-templates/threejs/templates/atom-tree.template.json +133 -0
  945. package/project-templates/threejs/templates/design-brief.template.md +92 -0
  946. package/project-templates/threejs/templates/design-lens-checklist.reference.md +117 -0
  947. package/project-templates/threejs/templates/design-methodology.md +99 -0
  948. package/project-templates/threejs/templates/design.template.md +50 -0
  949. package/project-templates/threejs/templates/developer-log.template.md +258 -0
  950. package/project-templates/threejs/templates/five-axis-framework.md +194 -0
  951. package/project-templates/threejs/templates/gen-placeholder-audio.template.mjs +63 -0
  952. package/project-templates/threejs/templates/gen-placeholders.template.mjs +81 -0
  953. package/project-templates/threejs/templates/intent-clarifications.template.md +58 -0
  954. package/project-templates/threejs/templates/layout-spec.template.md +198 -0
  955. package/project-templates/threejs/templates/plan.template.md +80 -0
  956. package/project-templates/threejs/templates/project-state.template.md +136 -0
  957. package/project-templates/threejs/templates/review-report.template.md +275 -0
  958. package/project-templates/threejs/templates/style-exploration.template.md +93 -0
  959. package/project-templates/threejs/templates/ta-log.template.md +394 -0
  960. package/project-templates/threejs/tsconfig.json +20 -0
  961. package/project-templates/threejs/vite.config.ts +27 -0
  962. package/dist/atom-plan/validate-atom-plan.js +0 -298
  963. package/dist/playable/base-builder.js +0 -265
  964. package/dist/playable/builder.js +0 -1462
  965. package/dist/playable/converter.js +0 -150
  966. package/dist/playable/index.js +0 -3
  967. package/dist/playable/platforms/base.js +0 -12
  968. package/dist/playable/platforms/facebook.js +0 -37
  969. package/dist/playable/platforms/index.js +0 -24
  970. package/dist/playable/platforms/snapchat.js +0 -59
  971. package/dist/playable/playable-builder.js +0 -521
  972. package/dist/playable/types.js +0 -1
  973. package/dist/playable/vite/config-builder.js +0 -136
  974. package/dist/playable/vite/platform-configs.js +0 -102
  975. package/dist/playable/vite/plugin-model-compression.js +0 -63
  976. package/dist/playable/vite/plugin-platform.js +0 -65
  977. package/dist/playable/vite/plugin-playcanvas.js +0 -454
  978. package/dist/playable/vite-builder.js +0 -125
  979. package/project-template/.claude/agents/designer.md +0 -124
  980. package/project-template/.claude/agents/pm.md +0 -166
  981. package/project-template/.claude/agents/refs/designer-style-exploration-flow.md +0 -67
  982. package/project-template/.claude/agents/refs/pm-workflow-detail.md +0 -567
  983. package/project-template/.claude/hooks/validate-atom-plan.mjs +0 -224
  984. package/project-template/.claude/settings.local.json +0 -4
  985. package/project-template/.claude/skills/playcraft-workflow/SKILL.md +0 -485
  986. package/project-template/docs/team/atom-plan-format.md +0 -173
  987. package/project-template/templates/atom-plan.template.json +0 -44
  988. package/project-template/templates/atom-plan.template.md +0 -108
  989. /package/dist/{atom-plan → asr}/validate-asr-coverage.js +0 -0
  990. /package/{project-template → engine-packs/phaser}/game/config/.gitkeep +0 -0
  991. /package/{project-template → engine-packs/phaser}/game/gameplay/.gitkeep +0 -0
  992. /package/{project-template → engine-packs/phaser}/game/scenes/.gitkeep +0 -0
  993. /package/{project-template/logs → engine-packs/threejs/game/config}/.gitkeep +0 -0
  994. /package/{project-template/ta-workspace/logs → engine-packs/threejs/game/gameplay}/.gitkeep +0 -0
  995. /package/{project-template/ta-workspace/tmp → engine-packs/threejs/game/scenes}/.gitkeep +0 -0
  996. /package/project-template/.claude/agents/refs/{designer-art-style-catalog.md → artist-art-style-catalog.md} +0 -0
@@ -1,1462 +0,0 @@
1
- import fs from 'fs/promises';
2
- import path from 'path';
3
- import { fileURLToPath } from 'url';
4
- import archiver from 'archiver';
5
- import { OnePageConverter } from './converter.js';
6
- import { createPlatformAdapter } from './platforms/index.js';
7
- const __filename = fileURLToPath(import.meta.url);
8
- const __dirname = path.dirname(__filename);
9
- export class PlayableBuilder {
10
- projectDir;
11
- options;
12
- manifest = null;
13
- converter;
14
- platformAdapter;
15
- engineCode = '';
16
- startScript = '';
17
- modulesScript = ''; // __modules__.js 内容
18
- configJson = null;
19
- sizeReport = {
20
- engine: 0,
21
- assets: {},
22
- total: 0,
23
- limit: 0,
24
- };
25
- constructor(projectDir, options) {
26
- this.projectDir = projectDir;
27
- this.options = options;
28
- this.converter = new OnePageConverter(projectDir, options);
29
- this.platformAdapter = createPlatformAdapter(options);
30
- this.sizeReport.limit = this.platformAdapter.getSizeLimit();
31
- }
32
- /**
33
- * 加载项目
34
- */
35
- async loadProject() {
36
- // 优先检查是否是构建后的项目(推荐方式)
37
- const isBuild = await this.detectBuildProject();
38
- if (isBuild) {
39
- console.log('✅ 检测到构建后的项目,使用构建版本(推荐)');
40
- await this.loadBuildProject();
41
- return;
42
- }
43
- // 检测项目格式(源代码)
44
- console.log('⚠️ 未检测到构建版本,将从源代码打包(可能不完整)');
45
- const format = await this.detectProjectFormat();
46
- if (format === 'playcraft') {
47
- await this.loadPlayCraftProject();
48
- }
49
- else if (format === 'playcanvas') {
50
- await this.loadPlayCanvasProject();
51
- }
52
- else {
53
- throw new Error('无法识别项目格式。请确保项目包含 manifest.json(PlayCraft)或 assets.json(PlayCanvas)\n\n' +
54
- '💡 推荐:先使用 PlayCanvas REST API 下载构建版本,然后再打包为 Playable Ad。');
55
- }
56
- if (!this.manifest) {
57
- throw new Error('Manifest is null');
58
- }
59
- // 收集所有资产文件
60
- // 注意:PlayCanvas 场景数据已在 convertPlayCanvasToManifest 中转换为 data URL
61
- // 只需要添加资产文件
62
- for (const asset of this.manifest.assets) {
63
- if (asset.file) {
64
- this.converter.addAsset(asset.path, asset.type);
65
- }
66
- }
67
- }
68
- /**
69
- * 检测是否是构建后的项目
70
- */
71
- async detectBuildProject() {
72
- const buildIndicators = [
73
- path.join(this.projectDir, 'index.html'),
74
- path.join(this.projectDir, '__start__.js'),
75
- path.join(this.projectDir, 'config.json'),
76
- ];
77
- // 至少需要 index.html 和 config.json
78
- try {
79
- await fs.access(buildIndicators[0]);
80
- await fs.access(buildIndicators[2]);
81
- return true;
82
- }
83
- catch (error) {
84
- return false;
85
- }
86
- }
87
- /**
88
- * 加载构建后的项目(官方推荐方式)
89
- */
90
- async loadBuildProject() {
91
- try {
92
- // 读取 config.json
93
- const configPath = path.join(this.projectDir, 'config.json');
94
- const configContent = await fs.readFile(configPath, 'utf-8');
95
- this.configJson = JSON.parse(configContent);
96
- // 读取 __start__.js
97
- const startScriptPath = path.join(this.projectDir, '__start__.js');
98
- try {
99
- const originalStartScript = await fs.readFile(startScriptPath, 'utf-8');
100
- // 包装官方启动脚本,添加日志追踪
101
- this.startScript = this.wrapOfficialStartScript(originalStartScript);
102
- }
103
- catch (error) {
104
- console.warn('未找到 __start__.js,将使用默认启动脚本');
105
- this.startScript = this.generateDefaultStartScript();
106
- }
107
- // 读取 __modules__.js(用于加载 WASM 模块如 Ammo.js)
108
- const modulesScriptPath = path.join(this.projectDir, '__modules__.js');
109
- try {
110
- this.modulesScript = await fs.readFile(modulesScriptPath, 'utf-8');
111
- }
112
- catch (error) {
113
- // 如果没有 __modules__.js,使用默认的模块加载器
114
- this.modulesScript = this.generateDefaultModulesScript();
115
- }
116
- // 从 config.json 构建 manifest
117
- this.manifest = this.convertBuildConfigToManifest(this.configJson);
118
- // 关键:将所有资产添加到 converter 以进行 Base64 编码
119
- for (const asset of this.manifest.assets) {
120
- if (asset.path) {
121
- this.converter.addAsset(asset.path, asset.type);
122
- }
123
- }
124
- // 也处理场景文件(如果不是 data URL)
125
- for (const scene of this.manifest.scenes) {
126
- if (scene.path && !scene.path.startsWith('data:')) {
127
- this.converter.addAsset(scene.path, 'scene');
128
- }
129
- }
130
- console.log(`✅ 成功加载构建项目,共 ${this.manifest.assets.length} 个资产`);
131
- }
132
- catch (error) {
133
- throw new Error(`无法加载构建项目: ${error.message}`);
134
- }
135
- }
136
- /**
137
- * 生成默认的模块加载脚本
138
- */
139
- generateDefaultModulesScript() {
140
- return `
141
- // #region agent log
142
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:modulesScript:entry',message:'Modules script executing',data:{hasPc:typeof pc!=='undefined'},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'F'})}).catch(()=>{});
143
- // #endregion
144
-
145
- var loadModules = function (modules, urlPrefix, doneCallback) {
146
- // #region agent log
147
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:modulesScript:loadModulesCalled',message:'loadModules function called',data:{modulesCount:modules?modules.length:0,hasUrlPrefix:!!urlPrefix},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'F'})}).catch(()=>{});
148
- // #endregion
149
-
150
- if (typeof modules === "undefined" || modules.length === 0) {
151
- setTimeout(doneCallback);
152
- } else {
153
- var remaining = modules.length;
154
- var moduleLoaded = function() {
155
- if (--remaining === 0) {
156
- // #region agent log
157
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:modulesScript:allModulesLoaded',message:'All modules loaded',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'F'})}).catch(()=>{});
158
- // #endregion
159
- doneCallback();
160
- }
161
- };
162
-
163
- modules.forEach(function (m) {
164
- pc.WasmModule.setConfig(m.moduleName, {
165
- glueUrl: urlPrefix + m.glueUrl,
166
- wasmUrl: urlPrefix + m.wasmUrl,
167
- fallbackUrl: urlPrefix + m.fallbackUrl
168
- });
169
-
170
- if (!m.hasOwnProperty('preload') || m.preload) {
171
- if (m.moduleName === 'BASIS') {
172
- pc.basisInitialize();
173
- moduleLoaded();
174
- } else if (m.moduleName === 'DracoDecoderModule') {
175
- if (pc.dracoInitialize) {
176
- pc.dracoInitialize();
177
- moduleLoaded();
178
- } else {
179
- pc.WasmModule.getInstance(m.moduleName, function() { moduleLoaded(); });
180
- }
181
- } else {
182
- pc.WasmModule.getInstance(m.moduleName, function() { moduleLoaded(); });
183
- }
184
- } else {
185
- moduleLoaded();
186
- }
187
- });
188
- }
189
- };
190
- window.loadModules = loadModules;
191
-
192
- // #region agent log
193
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:modulesScript:loadModulesDefined',message:'loadModules defined on window',data:{hasLoadModules:typeof window.loadModules==='function'},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'F'})}).catch(()=>{});
194
- // #endregion
195
- `;
196
- }
197
- /**
198
- * 将构建配置转换为 manifest 格式
199
- */
200
- convertBuildConfigToManifest(config) {
201
- const scenes = [];
202
- const assets = [];
203
- // 处理场景
204
- if (config.scenes) {
205
- for (const scene of config.scenes) {
206
- scenes.push({
207
- id: scene.id || scene.name,
208
- name: scene.name,
209
- path: scene.url || `${scene.name}.json`,
210
- });
211
- }
212
- }
213
- // 处理资产 - config.assets 是一个对象(以 ID 为 key),不是数组!
214
- if (config.assets) {
215
- for (const [id, asset] of Object.entries(config.assets)) {
216
- const assetData = asset;
217
- // 从 file.url 中提取不带查询参数的路径
218
- let filePath = assetData.file?.url || '';
219
- if (filePath.includes('?')) {
220
- filePath = filePath.split('?')[0];
221
- }
222
- assets.push({
223
- id: id,
224
- name: assetData.name,
225
- type: assetData.type,
226
- path: filePath,
227
- // 保留所有原始字段
228
- preload: assetData.preload !== false,
229
- tags: assetData.tags || [],
230
- i18n: assetData.i18n || {},
231
- data: assetData.data || null,
232
- file: assetData.file ? {
233
- filename: assetData.file.filename,
234
- size: assetData.file.size || 0,
235
- hash: assetData.file.hash || '',
236
- url: filePath, // 使用不带查询参数的路径
237
- } : undefined,
238
- });
239
- }
240
- }
241
- return {
242
- format: 'playcanvas-build',
243
- version: '1.0.0',
244
- project: {
245
- id: config.project_id || 'build',
246
- name: config.project_name || 'Build Project',
247
- },
248
- scenes,
249
- assets,
250
- };
251
- }
252
- /**
253
- * 检测项目格式
254
- */
255
- async detectProjectFormat() {
256
- const manifestPath = path.join(this.projectDir, 'manifest.json');
257
- const assetsJsonPath = path.join(this.projectDir, 'assets.json');
258
- try {
259
- await fs.access(manifestPath);
260
- return 'playcraft';
261
- }
262
- catch (error) {
263
- // manifest.json 不存在
264
- }
265
- try {
266
- await fs.access(assetsJsonPath);
267
- return 'playcanvas';
268
- }
269
- catch (error) {
270
- // assets.json 不存在
271
- }
272
- return 'unknown';
273
- }
274
- /**
275
- * 加载 PlayCraft 格式项目
276
- */
277
- async loadPlayCraftProject() {
278
- const manifestPath = path.join(this.projectDir, 'manifest.json');
279
- try {
280
- const manifestContent = await fs.readFile(manifestPath, 'utf-8');
281
- this.manifest = JSON.parse(manifestContent);
282
- }
283
- catch (error) {
284
- throw new Error(`无法加载 manifest.json: ${error.message}`);
285
- }
286
- }
287
- /**
288
- * 加载 PlayCanvas 格式项目
289
- */
290
- async loadPlayCanvasProject() {
291
- const assetsJsonPath = path.join(this.projectDir, 'assets.json');
292
- const scenesJsonPath = path.join(this.projectDir, 'scenes.json');
293
- try {
294
- // 读取 assets.json
295
- const assetsContent = await fs.readFile(assetsJsonPath, 'utf-8');
296
- const assetsJson = JSON.parse(assetsContent);
297
- // 读取 scenes.json
298
- let scenesJson = {};
299
- try {
300
- const scenesContent = await fs.readFile(scenesJsonPath, 'utf-8');
301
- scenesJson = JSON.parse(scenesContent);
302
- }
303
- catch (error) {
304
- console.warn('未找到 scenes.json,将不包含场景信息');
305
- }
306
- // 转换为 PlayCraft manifest 格式
307
- this.manifest = this.convertPlayCanvasToManifest(assetsJson, scenesJson);
308
- }
309
- catch (error) {
310
- throw new Error(`无法加载 PlayCanvas 项目: ${error.message}`);
311
- }
312
- }
313
- /**
314
- * 将 PlayCanvas 格式转换为 PlayCraft manifest 格式
315
- */
316
- convertPlayCanvasToManifest(assetsJson, scenesJson) {
317
- const assets = [];
318
- const scenes = [];
319
- // 构建文件夹路径映射
320
- const folderMap = new Map();
321
- for (const [id, asset] of Object.entries(assetsJson)) {
322
- const assetData = asset;
323
- if (assetData.type === 'folder') {
324
- const folderPath = this.buildFolderPath(assetData, assetsJson, folderMap);
325
- folderMap.set(id, folderPath);
326
- }
327
- }
328
- // 转换资产 - 保留完整的资产信息
329
- for (const [id, asset] of Object.entries(assetsJson)) {
330
- const assetData = asset;
331
- if (assetData.type === 'folder')
332
- continue;
333
- const treePath = this.buildAssetTreePath(assetData, folderMap);
334
- const filePath = assetData.file
335
- ? `files/assets/${id}/1/${assetData.file.filename}`
336
- : '';
337
- assets.push({
338
- id: id,
339
- name: assetData.name,
340
- type: assetData.type,
341
- path: filePath,
342
- // 保留原始的 preload、tags、i18n、data 字段
343
- preload: assetData.preload !== false,
344
- tags: assetData.tags || [],
345
- i18n: assetData.i18n || {},
346
- data: assetData.data || null,
347
- file: assetData.file ? {
348
- filename: assetData.file.filename,
349
- size: assetData.file.size || 0,
350
- hash: assetData.file.hash || '',
351
- url: assetData.file.url || filePath,
352
- } : undefined,
353
- });
354
- }
355
- // 转换场景(PlayCanvas 场景数据内嵌在 scenes.json 中)
356
- for (const [id, scene] of Object.entries(scenesJson)) {
357
- const sceneData = scene;
358
- // 将场景数据直接转换为 JSON 字符串,然后 Base64 编码
359
- const sceneJsonStr = JSON.stringify(sceneData);
360
- const base64Data = Buffer.from(sceneJsonStr).toString('base64');
361
- const dataUrl = `data:application/json;base64,${base64Data}`;
362
- scenes.push({
363
- id: id,
364
- name: sceneData.name || id,
365
- path: dataUrl, // 直接使用 data URL
366
- isMain: false,
367
- });
368
- }
369
- return {
370
- format: 'playcanvas-converted',
371
- version: '1.0.0',
372
- project: {
373
- id: 'unknown',
374
- name: 'Converted Project',
375
- description: 'PlayCanvas project converted to PlayCraft format',
376
- },
377
- scenes,
378
- assets,
379
- };
380
- }
381
- /**
382
- * 构建文件夹路径
383
- */
384
- buildFolderPath(folder, assetsJson, folderMap) {
385
- if (!folder.path || folder.path.length === 0) {
386
- return folder.name;
387
- }
388
- const parentId = folder.path[folder.path.length - 1];
389
- const parentPath = folderMap.get(parentId);
390
- if (parentPath) {
391
- return `${parentPath}/${folder.name}`;
392
- }
393
- // 如果父文件夹还没有处理,递归处理
394
- const parentFolder = assetsJson[parentId];
395
- if (parentFolder && parentFolder.type === 'folder') {
396
- const parentPath = this.buildFolderPath(parentFolder, assetsJson, folderMap);
397
- folderMap.set(parentId, parentPath);
398
- return `${parentPath}/${folder.name}`;
399
- }
400
- return folder.name;
401
- }
402
- /**
403
- * 构建资产树形路径
404
- */
405
- buildAssetTreePath(asset, folderMap) {
406
- if (!asset.path || asset.path.length === 0) {
407
- return '';
408
- }
409
- const paths = [];
410
- for (const folderId of asset.path) {
411
- const folderPath = folderMap.get(folderId);
412
- if (folderPath) {
413
- paths.push(folderPath);
414
- }
415
- }
416
- return paths.join('/');
417
- }
418
- /**
419
- * 编码资产为 Base64
420
- */
421
- async encodeAssets() {
422
- await this.converter.encodeAssets();
423
- // 更新大小报告
424
- const assets = this.converter.getAssets();
425
- for (const asset of assets) {
426
- const name = path.basename(asset.path);
427
- this.sizeReport.assets[name] = asset.size;
428
- }
429
- }
430
- /**
431
- * 生成运行时配置
432
- */
433
- async generateConfig() {
434
- // 加载 PlayCanvas Engine
435
- await this.loadEngine();
436
- // 对于构建后的项目,使用原始配置并更新 URL
437
- // 对于源码项目,生成新配置
438
- if (this.manifest?.format === 'playcanvas-build' && this.configJson) {
439
- await this.updateBuildConfigUrls();
440
- }
441
- else {
442
- await this.generateRuntimeConfig();
443
- }
444
- // 生成启动脚本
445
- await this.generateStartScript();
446
- }
447
- /**
448
- * 更新构建配置中的资产 URL 为 data URL
449
- * 这样可以保留原始配置的所有属性,只替换 URL
450
- */
451
- async updateBuildConfigUrls() {
452
- if (!this.configJson || !this.configJson.assets) {
453
- return;
454
- }
455
- let updatedCount = 0;
456
- // 遍历所有资产,更新 URL 为 data URL
457
- for (const [id, asset] of Object.entries(this.configJson.assets)) {
458
- const assetData = asset;
459
- if (assetData.file && assetData.file.url) {
460
- // 移除查询参数
461
- let cleanUrl = assetData.file.url;
462
- if (cleanUrl.includes('?')) {
463
- cleanUrl = cleanUrl.split('?')[0];
464
- }
465
- // 获取 data URL
466
- const dataUrl = this.converter.getDataUrl(cleanUrl);
467
- if (dataUrl) {
468
- // 更新 URL 为 data URL
469
- assetData.file.url = dataUrl;
470
- // 关键:清空 hash,防止 PlayCanvas 追加 ?t=hash
471
- assetData.file.hash = '';
472
- updatedCount++;
473
- }
474
- }
475
- }
476
- // 更新场景 URL
477
- if (this.configJson.scenes) {
478
- for (const scene of this.configJson.scenes) {
479
- if (scene.url && !scene.url.startsWith('data:')) {
480
- // 移除查询参数
481
- let cleanUrl = scene.url;
482
- if (cleanUrl.includes('?')) {
483
- cleanUrl = cleanUrl.split('?')[0];
484
- }
485
- const dataUrl = this.converter.getDataUrl(cleanUrl);
486
- if (dataUrl) {
487
- scene.url = dataUrl;
488
- updatedCount++;
489
- }
490
- }
491
- }
492
- }
493
- console.log(`✅ 已更新 ${updatedCount} 个资产 URL 为内嵌 data URL`);
494
- }
495
- /**
496
- * 加载 PlayCanvas Engine
497
- */
498
- async loadEngine() {
499
- // 1. 首先尝试从本地加载(如果提供了路径)
500
- if (this.options.enginePath) {
501
- try {
502
- this.engineCode = await fs.readFile(this.options.enginePath, 'utf-8');
503
- this.sizeReport.engine = Buffer.from(this.engineCode).length;
504
- return;
505
- }
506
- catch (error) {
507
- console.warn(`无法从本地加载 engine: ${error.message}`);
508
- }
509
- }
510
- // 2. 尝试从项目目录加载
511
- const localEnginePaths = [
512
- path.join(this.projectDir, 'playcanvas-stable.min.js'),
513
- path.join(this.projectDir, 'playcanvas.min.js'),
514
- path.join(this.projectDir, '__lib__.js'),
515
- ];
516
- for (const enginePath of localEnginePaths) {
517
- try {
518
- this.engineCode = await fs.readFile(enginePath, 'utf-8');
519
- this.sizeReport.engine = Buffer.from(this.engineCode).length;
520
- console.log(`从本地加载 Engine: ${enginePath}`);
521
- return;
522
- }
523
- catch (error) {
524
- // 继续尝试下一个
525
- }
526
- }
527
- // 3. 从 CDN 下载(如果提供了 URL)
528
- if (this.options.engineUrl) {
529
- try {
530
- const response = await fetch(this.options.engineUrl, {
531
- headers: {
532
- 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
533
- 'Accept': '*/*',
534
- },
535
- });
536
- if (response.ok) {
537
- this.engineCode = await response.text();
538
- this.sizeReport.engine = Buffer.from(this.engineCode).length;
539
- return;
540
- }
541
- }
542
- catch (error) {
543
- console.warn(`无法从 URL 下载 engine: ${error.message}`);
544
- }
545
- }
546
- // 4. 使用默认 CDN 版本
547
- const version = this.options.engineVersion || '2.15.1';
548
- // 尝试多个 CDN(优先使用官方 GitHub CDN)
549
- const cdnUrls = [
550
- // 官方 PlayCanvas CDN (GitHub releases)
551
- `https://code.playcanvas.com/playcanvas-${version}.min.js`,
552
- // jsDelivr (NPM 镜像)
553
- `https://cdn.jsdelivr.net/npm/playcanvas@${version}/build/playcanvas.min.js`,
554
- // unpkg (备用)
555
- `https://unpkg.com/playcanvas@${version}/build/playcanvas.min.js`,
556
- ];
557
- let lastError = null;
558
- for (const cdnUrl of cdnUrls) {
559
- try {
560
- console.log(`从 CDN 下载 Engine: ${cdnUrl}`);
561
- const response = await fetch(cdnUrl, {
562
- headers: {
563
- 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
564
- 'Accept': '*/*',
565
- },
566
- });
567
- if (response.ok) {
568
- this.engineCode = await response.text();
569
- this.sizeReport.engine = Buffer.from(this.engineCode).length;
570
- console.log(`✓ 成功下载 Engine (${(this.sizeReport.engine / 1024 / 1024).toFixed(2)} MB)`);
571
- return;
572
- }
573
- else {
574
- lastError = new Error(`HTTP ${response.status}: ${response.statusText}`);
575
- }
576
- }
577
- catch (error) {
578
- lastError = error;
579
- console.warn(`CDN 失败: ${cdnUrl}`);
580
- // 继续尝试下一个 CDN
581
- }
582
- }
583
- throw new Error(`无法从任何 CDN 加载 PlayCanvas Engine: ${lastError?.message}。请提供本地 engine 文件或检查网络连接。`);
584
- }
585
- /**
586
- * 生成运行时配置 - 使用官方 PlayCanvas config.json 格式
587
- */
588
- async generateRuntimeConfig() {
589
- if (!this.manifest) {
590
- throw new Error('Manifest not loaded');
591
- }
592
- // 构建官方格式的 config.json
593
- // assets 是以 ID 为 key 的对象,不是数组
594
- const assetsObject = {};
595
- for (const asset of this.manifest.assets) {
596
- // 从路径中移除查询参数,用于查找 data URL
597
- let cleanPath = asset.path;
598
- if (cleanPath.includes('?')) {
599
- cleanPath = cleanPath.split('?')[0];
600
- }
601
- // 尝试获取 data URL
602
- let dataUrl = this.converter.getDataUrl(cleanPath);
603
- // 如果没有找到,尝试用原始文件的 URL(去掉查询参数)
604
- if (!dataUrl && asset.file?.url) {
605
- let cleanFileUrl = asset.file.url;
606
- if (cleanFileUrl.includes('?')) {
607
- cleanFileUrl = cleanFileUrl.split('?')[0];
608
- }
609
- dataUrl = this.converter.getDataUrl(cleanFileUrl);
610
- }
611
- // 如果还是找不到,尝试用文件名
612
- if (!dataUrl && asset.file?.filename) {
613
- dataUrl = this.converter.getDataUrl(asset.file.filename);
614
- }
615
- // 构建资产配置
616
- const assetConfig = {
617
- name: asset.name,
618
- type: asset.type,
619
- preload: asset.preload !== false,
620
- tags: asset.tags || [],
621
- i18n: asset.i18n || {},
622
- id: parseInt(asset.id) || asset.id, // 确保 ID 是数字(如果原本是数字)
623
- data: asset.data || null,
624
- };
625
- // 只有有文件的资产才设置 file 字段
626
- if (asset.file || dataUrl) {
627
- // 关键修复:如果使用 data URL,清空 hash,防止 ?t=hash 被追加
628
- const isDataUrl = dataUrl && dataUrl.startsWith('data:');
629
- assetConfig.file = {
630
- filename: asset.file?.filename || path.basename(cleanPath),
631
- size: asset.file?.size || 0,
632
- // 关键:如果 URL 是 data URL,清空 hash,否则 PlayCanvas 会追加 ?t=hash
633
- hash: isDataUrl ? '' : (asset.file?.hash || ''),
634
- // 使用 data URL 替换原始 URL
635
- url: dataUrl || cleanPath,
636
- };
637
- }
638
- assetsObject[asset.id] = assetConfig;
639
- }
640
- // 场景配置 - 使用官方格式
641
- const scenes = this.manifest.scenes.map(scene => ({
642
- name: scene.name,
643
- // 场景 URL 使用文件名格式(会被 Base64 编码后的 data URL 替换)
644
- url: scene.path.startsWith('data:')
645
- ? scene.path
646
- : (this.converter.getDataUrl(scene.path) || `${scene.id}.json`),
647
- }));
648
- // 官方 config.json 格式
649
- this.configJson = {
650
- application_properties: {
651
- width: 1280,
652
- height: 720,
653
- fillMode: 'FILL_WINDOW',
654
- resolutionMode: 'AUTO',
655
- useDevicePixelRatio: true,
656
- antiAlias: true,
657
- transparentCanvas: false,
658
- preserveDrawingBuffer: false,
659
- useLegacyScripts: false,
660
- useKeyboard: true,
661
- useMouse: true,
662
- useTouch: true,
663
- useGamepads: false,
664
- scripts: [],
665
- layers: {
666
- '0': { name: 'World', opaqueSortMode: 2, transparentSortMode: 3 },
667
- '1': { name: 'Depth', opaqueSortMode: 2, transparentSortMode: 3 },
668
- '2': { name: 'Skybox', opaqueSortMode: 0, transparentSortMode: 3 },
669
- '3': { name: 'Immediate', opaqueSortMode: 0, transparentSortMode: 3 },
670
- '4': { name: 'UI', opaqueSortMode: 1, transparentSortMode: 1 },
671
- },
672
- layerOrder: [
673
- { layer: 0, transparent: false, enabled: true },
674
- { layer: 1, transparent: false, enabled: true },
675
- { layer: 2, transparent: false, enabled: true },
676
- { layer: 0, transparent: true, enabled: true },
677
- { layer: 3, transparent: false, enabled: true },
678
- { layer: 3, transparent: true, enabled: true },
679
- { layer: 4, transparent: true, enabled: true },
680
- ],
681
- batchGroups: [],
682
- i18nAssets: [],
683
- externalScripts: [],
684
- libraries: [],
685
- },
686
- scenes: scenes,
687
- assets: assetsObject,
688
- };
689
- }
690
- /**
691
- * 生成启动脚本
692
- */
693
- async generateStartScript() {
694
- // 如果已经有启动脚本(从 loadBuildProject 加载),则跳过
695
- if (this.startScript) {
696
- console.log('✅ 使用已加载的启动脚本');
697
- return;
698
- }
699
- // 尝试从项目目录读取启动脚本
700
- const startScriptPaths = [
701
- path.join(this.projectDir, '__start__.js'),
702
- path.join(this.projectDir, 'start.js'),
703
- ];
704
- for (const scriptPath of startScriptPaths) {
705
- try {
706
- const originalScript = await fs.readFile(scriptPath, 'utf-8');
707
- this.startScript = this.wrapOfficialStartScript(originalScript);
708
- console.log(`✅ 从 ${path.basename(scriptPath)} 加载启动脚本`);
709
- return;
710
- }
711
- catch (error) {
712
- // 继续尝试
713
- }
714
- }
715
- // 如果找不到,生成默认启动脚本
716
- console.log('⚠️ 未找到启动脚本,使用默认脚本');
717
- this.startScript = this.generateDefaultStartScript();
718
- }
719
- /**
720
- * 包装官方启动脚本,添加日志追踪
721
- */
722
- wrapOfficialStartScript(originalScript) {
723
- // 在脚本开头添加日志
724
- const logEntry = `// #region agent log
725
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:officialStartScript:entry',message:'Official start script executing',data:{hasWindowConfig:!!window.CONFIG,hasConfigFilename:!!window.CONFIG_FILENAME,hasScenePath:!!window.SCENE_PATH,hasPreloadModules:!!window.PRELOAD_MODULES,hasLoadModules:typeof window.loadModules==='function'},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'G'})}).catch(()=>{});
726
- // #endregion
727
- `;
728
- // 在 main() 函数调用前添加日志
729
- const logBeforeMain = `// #region agent log
730
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:officialStartScript:beforeMain',message:'Before main() call',data:{hasCreateGraphicsDevice:typeof createGraphicsDevice==='function',hasInitApp:typeof initApp==='function',hasConfigure:typeof configure==='function'},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'G'})}).catch(()=>{});
731
- // #endregion
732
- `;
733
- // 简单包装:在开头和 main() 调用前添加日志
734
- let wrappedScript = originalScript;
735
- // 在脚本开头添加入口日志(查找第一个 (function() { 或类似的模式)
736
- if (wrappedScript.trim().startsWith('(function')) {
737
- wrappedScript = wrappedScript.replace(/^\(function\s*\(\)\s*\{/, `(function () {${logEntry}`);
738
- }
739
- else {
740
- wrappedScript = logEntry + wrappedScript;
741
- }
742
- // 在 main() 调用前添加日志
743
- wrappedScript = wrappedScript.replace(/(\s*)main\(\);/g, `${logBeforeMain}$1main();`);
744
- return wrappedScript;
745
- }
746
- /**
747
- * 生成默认启动脚本 - 使用官方 PlayCanvas 初始化方式
748
- * 关键:使用 app.configure() 加载配置,这是官方推荐的方式
749
- */
750
- generateDefaultStartScript() {
751
- return `
752
- (function () {
753
- // #region agent log
754
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:startScript:entry',message:'Start script executing',data:{hasWindowConfig:!!window.CONFIG,hasPlayCanvasConfig:!!window.PLAYCANVAS_CONFIG,hasConfigFilename:!!window.CONFIG_FILENAME},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'G'})}).catch(()=>{});
755
- // #endregion
756
-
757
- var CANVAS_ID = 'application-canvas';
758
-
759
- // 创建或获取 Canvas
760
- var canvas = document.getElementById(CANVAS_ID);
761
- if (!canvas) {
762
- canvas = document.createElement('canvas');
763
- canvas.setAttribute('id', CANVAS_ID);
764
- canvas.setAttribute('tabindex', 0);
765
- canvas.onselectstart = function () { return false; };
766
- canvas.style['-webkit-user-select'] = 'none';
767
- document.body.appendChild(canvas);
768
- }
769
-
770
- // 获取内联配置 - 优先使用 window.CONFIG(与注入的变量名一致)
771
- var CONFIG = window.CONFIG || window.PLAYCANVAS_CONFIG;
772
- if (!CONFIG) {
773
- // #region agent log
774
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:startScript:configNotFound',message:'Config not found',data:{hasWindowConfig:!!window.CONFIG,hasPlayCanvasConfig:!!window.PLAYCANVAS_CONFIG,hasConfigFilename:!!window.CONFIG_FILENAME},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'G'})}).catch(()=>{});
775
- // #endregion
776
- console.error('CONFIG not found');
777
- return;
778
- }
779
-
780
- // #region agent log
781
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:startScript:configFound',message:'Config found, creating app',data:{hasScenes:!!(CONFIG.scenes&&CONFIG.scenes.length>0),scenesCount:CONFIG.scenes?CONFIG.scenes.length:0},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'G'})}).catch(()=>{});
782
- // #endregion
783
-
784
- // 将配置转为 data URL,供 app.configure() 使用
785
- var configJson = JSON.stringify(CONFIG);
786
- var configDataUrl = 'data:application/json;base64,' + btoa(unescape(encodeURIComponent(configJson)));
787
-
788
- // 创建应用 - 使用旧版兼容的 pc.Application
789
- try {
790
- var app = new pc.Application(canvas, {
791
- mouse: new pc.Mouse(canvas),
792
- touch: pc.platform && pc.platform.touch ? new pc.TouchDevice(canvas) : null,
793
- keyboard: new pc.Keyboard(window),
794
- graphicsDeviceOptions: {
795
- alpha: false,
796
- antialias: true,
797
- depth: true,
798
- stencil: true,
799
- preserveDrawingBuffer: false
800
- }
801
- });
802
-
803
- // #region agent log
804
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:startScript:appCreated',message:'App created successfully',data:{hasApp:!!app,appIsPlaying:app?app.isPlaying:false},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'G'})}).catch(()=>{});
805
- // #endregion
806
-
807
- // 将 app 暴露到全局作用域,以便调试
808
- window.app = app;
809
-
810
- app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);
811
- app.setCanvasResolution(pc.RESOLUTION_AUTO);
812
-
813
- window.addEventListener('resize', function() {
814
- app.resizeCanvas();
815
- });
816
-
817
- // 使用 app.configure() 加载配置 - 这是官方推荐的方式
818
- app.configure(configDataUrl, function(err) {
819
- // #region agent log
820
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:startScript:configureCallback',message:'app.configure callback',data:{hasError:!!err,error:err?err.message:null},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'G'})}).catch(()=>{});
821
- // #endregion
822
-
823
- if (err) {
824
- console.error('Configure error:', err);
825
- return;
826
- }
827
-
828
- // 预加载资产
829
- app.preload(function(err) {
830
- // #region agent log
831
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:startScript:preloadCallback',message:'app.preload callback',data:{hasError:!!err,error:err?err.message:null},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'G'})}).catch(()=>{});
832
- // #endregion
833
-
834
- if (err) {
835
- console.error('Preload error:', err);
836
- }
837
-
838
- // 加载场景
839
- if (CONFIG.scenes && CONFIG.scenes.length > 0) {
840
- var sceneUrl = CONFIG.scenes[0].url;
841
- app.scenes.loadScene(sceneUrl, function(err, entity) {
842
- // #region agent log
843
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:startScript:loadSceneCallback',message:'app.scenes.loadScene callback',data:{hasError:!!err,error:err?err.message:null,hasEntity:!!entity},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'G'})}).catch(()=>{});
844
- // #endregion
845
-
846
- if (err) {
847
- console.error('Scene load error:', err);
848
- }
849
- // 启动应用
850
- app.start();
851
- // #region agent log
852
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:startScript:appStarted',message:'app.start called',data:{appIsPlaying:app.isPlaying},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'G'})}).catch(()=>{});
853
- // #endregion
854
- });
855
- } else {
856
- app.start();
857
- // #region agent log
858
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:startScript:appStarted',message:'app.start called (no scenes)',data:{appIsPlaying:app.isPlaying},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'G'})}).catch(()=>{});
859
- // #endregion
860
- }
861
- });
862
- });
863
- } catch (e) {
864
- // #region agent log
865
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:startScript:error',message:'Error creating app',data:{error:e.message,stack:e.stack?e.stack.substring(0,500):''},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'G'})}).catch(()=>{});
866
- // #endregion
867
- console.error('Error creating app:', e);
868
- }
869
- })();
870
- `;
871
- }
872
- /**
873
- * 应用平台配置
874
- */
875
- async applyPlatformConfig() {
876
- this.platformAdapter.validateOptions();
877
- }
878
- /**
879
- * 输出文件
880
- */
881
- async output() {
882
- const outputDir = this.options.outputDir || path.join(this.projectDir, 'dist');
883
- await fs.mkdir(outputDir, { recursive: true });
884
- const format = this.options.format || this.platformAdapter.getDefaultFormat();
885
- if (format === 'html') {
886
- return await this.outputHTML(outputDir);
887
- }
888
- else {
889
- return await this.outputZIP(outputDir);
890
- }
891
- }
892
- /**
893
- * 输出 HTML 文件
894
- */
895
- async outputHTML(outputDir) {
896
- const htmlTemplate = await this.loadHTMLTemplate();
897
- const assets = this.converter.getAssets();
898
- // 创建 URL 映射
899
- const urlMap = new Map();
900
- for (const asset of assets) {
901
- const dataUrl = this.converter.getDataUrl(asset.path);
902
- if (dataUrl) {
903
- urlMap.set(asset.path, dataUrl);
904
- urlMap.set(`/${asset.path}`, dataUrl);
905
- const fileName = path.basename(asset.path);
906
- urlMap.set(fileName, dataUrl);
907
- }
908
- }
909
- // 替换 URL
910
- let html = this.converter.replaceUrlsWithBase64(htmlTemplate, urlMap);
911
- // 内联脚本(如果需要)
912
- if (this.options.inlineGameScripts !== false) {
913
- html = await this.converter.inlineScripts(html);
914
- }
915
- // 注入 PlayCanvas Engine
916
- const engineScript = `<script>${this.engineCode}</script>`;
917
- html = html.replace('</head>', `${engineScript}</head>`);
918
- // 生成配置 data URL(官方启动脚本使用 app.configure(CONFIG_FILENAME) 来加载配置)
919
- const configJsonStr = JSON.stringify(this.configJson);
920
- const configBase64 = Buffer.from(configJsonStr).toString('base64');
921
- const configDataUrl = `data:application/json;base64,${configBase64}`;
922
- // 同时内联配置对象到 window.CONFIG,以便启动脚本可以直接使用
923
- // 这样可以避免通过 data URL 加载时可能的数据丢失问题
924
- const configInlineScript = `<script>
925
- window.CONFIG = ${configJsonStr};
926
- // #region agent log
927
- (function(){var fontAsset=window.CONFIG&&window.CONFIG.assets&&window.CONFIG.assets['269207482']?window.CONFIG.assets['269207482']:null;fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:configInline:validation',message:'Config object validation',data:{hasFontAsset:!!fontAsset,fontAssetHasData:!!(fontAsset&&fontAsset.data),fontAssetHasInfo:!!(fontAsset&&fontAsset.data&&fontAsset.data.info),fontAssetHasMaps:!!(fontAsset&&fontAsset.data&&fontAsset.data.info&&fontAsset.data.info.maps),mapsValue:fontAsset&&fontAsset.data&&fontAsset.data.info?fontAsset.data.info.maps:null},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'E'})}).catch(()=>{});})();
928
- // #endregion
929
- </script>`;
930
- html = html.replace('</head>', `${configInlineScript}</head>`);
931
- // 生成场景 data URL(如果有场景)
932
- let sceneDataUrl = '';
933
- if (this.configJson.scenes && this.configJson.scenes.length > 0) {
934
- const sceneUrl = this.configJson.scenes[0].url;
935
- if (sceneUrl && sceneUrl.startsWith('data:')) {
936
- sceneDataUrl = sceneUrl;
937
- }
938
- else {
939
- // 尝试获取场景的 data URL
940
- const scenePath = this.configJson.scenes[0].url || '';
941
- sceneDataUrl = this.converter.getDataUrl(scenePath) || scenePath;
942
- }
943
- }
944
- // 生成设置脚本 - 使用 data URL 替代文件路径
945
- // 这样官方的 __start__.js 可以正常工作
946
- // 同时添加补丁脚本,让启动脚本优先使用 window.CONFIG
947
- const settingsScript = this.generateSettingsScript(configDataUrl, sceneDataUrl);
948
- html = html.replace('</head>', `<script>${settingsScript}</script></head>`);
949
- // 添加补丁脚本,修改 app.configure 来使用内联的配置对象
950
- const configPatchScript = this.generateConfigPatchScript();
951
- html = html.replace('</head>', `<script>${configPatchScript}</script></head>`);
952
- // 注入模块加载脚本(用于 WASM 模块如 Ammo.js)
953
- if (this.modulesScript) {
954
- const scriptLength = this.modulesScript.length;
955
- const modulesScriptTag = `<script>
956
- // #region agent log
957
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:outputHTML:modulesScriptInjected',message:'Modules script injected',data:{scriptLength:${scriptLength}},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'F'})}).catch(()=>{});
958
- // #endregion
959
- ${this.modulesScript}</script>`;
960
- html = html.replace('</body>', `${modulesScriptTag}</body>`);
961
- }
962
- else {
963
- // 添加日志:模块脚本为空
964
- const logScript = `<script>
965
- // #region agent log
966
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:outputHTML:modulesScriptEmpty',message:'Modules script is empty',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'F'})}).catch(()=>{});
967
- // #endregion
968
- </script>`;
969
- html = html.replace('</body>', `${logScript}</body>`);
970
- }
971
- // 注入启动脚本
972
- if (this.startScript) {
973
- const scriptLength = this.startScript.length;
974
- const startScriptTag = `<script>
975
- // #region agent log
976
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:outputHTML:startScriptInjected',message:'Start script injected',data:{scriptLength:${scriptLength}},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'G'})}).catch(()=>{});
977
- try {
978
- // #endregion
979
- ${this.startScript}
980
- // #region agent log
981
- } catch(e) {
982
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:outputHTML:startScriptError',message:'Start script execution error',data:{error:e.message,stack:e.stack?e.stack.substring(0,500):''},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'G'})}).catch(()=>{});
983
- throw e;
984
- }
985
- // #endregion
986
- </script>`;
987
- html = html.replace('</body>', `${startScriptTag}</body>`);
988
- }
989
- else {
990
- // 添加日志:启动脚本为空
991
- const logScript = `<script>
992
- // #region agent log
993
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:outputHTML:startScriptEmpty',message:'Start script is empty',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'G'})}).catch(()=>{});
994
- // #endregion
995
- </script>`;
996
- html = html.replace('</body>', `${logScript}</body>`);
997
- }
998
- // 应用平台特定的修改
999
- html = this.platformAdapter.modifyHTML(html, assets);
1000
- // 添加平台脚本
1001
- const platformScript = this.platformAdapter.getPlatformScript();
1002
- html = html.replace('</body>', `<script>${platformScript}</script></body>`);
1003
- const outputPath = path.join(outputDir, 'index.html');
1004
- await fs.writeFile(outputPath, html, 'utf-8');
1005
- // 更新大小报告
1006
- const htmlSize = Buffer.from(html, 'utf-8').length;
1007
- this.sizeReport.total = htmlSize;
1008
- this.sizeReport.assets['index.html'] = htmlSize;
1009
- this.sizeReport.assets['PlayCanvas Engine'] = this.sizeReport.engine;
1010
- return outputPath;
1011
- }
1012
- /**
1013
- * 生成配置补丁脚本
1014
- * 修改 app.configure 方法,优先使用内联的 window.CONFIG 对象
1015
- * 这样可以避免通过 data URL 加载时可能的数据丢失问题
1016
- */
1017
- generateConfigPatchScript() {
1018
- return `
1019
- (function() {
1020
- // #region agent log
1021
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:init',message:'Patch script started',data:{hasWindowConfig:!!window.CONFIG},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{});
1022
- // #endregion
1023
-
1024
- // 等待 PlayCanvas 引擎加载
1025
- function patchConfigure() {
1026
- if (typeof pc === 'undefined' || !pc.Application) {
1027
- setTimeout(patchConfigure, 10);
1028
- return;
1029
- }
1030
-
1031
- // #region agent log
1032
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:pcReady',message:'PlayCanvas engine loaded, patching configure',data:{hasWindowConfig:!!window.CONFIG,hasFontAsset:!!(window.CONFIG&&window.CONFIG.assets&&window.CONFIG.assets['269207482'])},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'B'})}).catch(()=>{});
1033
- // #endregion
1034
-
1035
- var ApplicationPrototype = pc.Application.prototype;
1036
- var originalConfigure = ApplicationPrototype.configure;
1037
-
1038
- // 检查字体资产数据完整性
1039
- if (window.CONFIG && window.CONFIG.assets && window.CONFIG.assets['269207482']) {
1040
- var fontAsset = window.CONFIG.assets['269207482'];
1041
- // #region agent log
1042
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:checkFontAsset',message:'Font asset data check',data:{hasData:!!fontAsset.data,hasInfo:!!(fontAsset.data&&fontAsset.data.info),hasMaps:!!(fontAsset.data&&fontAsset.data.info&&fontAsset.data.info.maps),mapsValue:fontAsset.data&&fontAsset.data.info?fontAsset.data.info.maps:null},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{});
1043
- // #endregion
1044
- }
1045
-
1046
- // 拦截 _parseApplicationProperties 方法
1047
- if (ApplicationPrototype._parseApplicationProperties) {
1048
- var originalParseApplicationProperties = ApplicationPrototype._parseApplicationProperties;
1049
- ApplicationPrototype._parseApplicationProperties = function(config, callback) {
1050
- // #region agent log
1051
- var fontAsset = config&&config.assets&&config.assets['269207482']?config.assets['269207482']:null;
1052
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:beforeParseApplicationProperties',message:'Before _parseApplicationProperties',data:{hasFontAsset:!!fontAsset,fontAssetHasMaps:!!(fontAsset&&fontAsset.data&&fontAsset.data.info&&fontAsset.data.info.maps)},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{});
1053
- // #endregion
1054
-
1055
- try {
1056
- var result = originalParseApplicationProperties.call(this, config, callback);
1057
- // #region agent log
1058
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:afterParseApplicationProperties',message:'After _parseApplicationProperties',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{});
1059
- // #endregion
1060
- return result;
1061
- } catch (e) {
1062
- // #region agent log
1063
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:parseApplicationPropertiesError',message:'Error in _parseApplicationProperties',data:{error:e.message},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{});
1064
- // #endregion
1065
- throw e;
1066
- }
1067
- };
1068
- }
1069
-
1070
- // 拦截 _parseAssets 方法来追踪字体资产解析
1071
- if (ApplicationPrototype._parseAssets) {
1072
- var originalParseAssets = ApplicationPrototype._parseAssets;
1073
- ApplicationPrototype._parseAssets = function(config) {
1074
- // #region agent log
1075
- var fontAsset = config&&config.assets&&config.assets['269207482']?config.assets['269207482']:null;
1076
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:beforeParseAssets',message:'Before _parseAssets',data:{hasFontAsset:!!fontAsset,fontAssetHasData:!!(fontAsset&&fontAsset.data),fontAssetHasInfo:!!(fontAsset&&fontAsset.data&&fontAsset.data.info),fontAssetHasMaps:!!(fontAsset&&fontAsset.data&&fontAsset.data.info&&fontAsset.data.info.maps)},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{});
1077
- // #endregion
1078
-
1079
- try {
1080
- var result = originalParseAssets.call(this, config);
1081
-
1082
- // #region agent log
1083
- var fontAssetAfter = this.assets&&this.assets.get('269207482')?this.assets.get('269207482'):null;
1084
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:afterParseAssets',message:'After _parseAssets',data:{hasFontAsset:!!fontAssetAfter,fontAssetHasData:!!(fontAssetAfter&&fontAssetAfter.data),fontAssetHasInfo:!!(fontAssetAfter&&fontAssetAfter.data&&fontAssetAfter.data.info),fontAssetHasMaps:!!(fontAssetAfter&&fontAssetAfter.data&&fontAssetAfter.data.info&&fontAssetAfter.data.info.maps)},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{});
1085
- // #endregion
1086
-
1087
- return result;
1088
- } catch (e) {
1089
- // #region agent log
1090
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:parseAssetsError',message:'Error in _parseAssets',data:{error:e.message,stack:e.stack?e.stack.substring(0,500):''},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{});
1091
- // #endregion
1092
- throw e;
1093
- }
1094
- };
1095
- }
1096
-
1097
- // 重写 configure 方法
1098
- ApplicationPrototype.configure = function(url, callback) {
1099
- // #region agent log
1100
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:configureCalled',message:'app.configure called',data:{urlType:typeof url,urlIsDataUrl:typeof url==='string'&&url.startsWith('data:'),hasWindowConfig:!!window.CONFIG},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{});
1101
- // #endregion
1102
-
1103
- // 如果 window.CONFIG 存在且 url 是 data URL,直接使用 window.CONFIG
1104
- if (window.CONFIG && typeof url === 'string' && url.startsWith('data:')) {
1105
- // #region agent log
1106
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:usingInlineConfig',message:'Using inline CONFIG instead of data URL',data:{fontAssetHasMaps:!!(window.CONFIG.assets&&window.CONFIG.assets['269207482']&&window.CONFIG.assets['269207482'].data&&window.CONFIG.assets['269207482'].data.info&&window.CONFIG.assets['269207482'].data.info.maps)},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{});
1107
- // #endregion
1108
-
1109
- // 使用内部方法直接解析配置对象
1110
- try {
1111
- // #region agent log
1112
- var configBeforeParse = JSON.stringify(window.CONFIG.assets&&window.CONFIG.assets['269207482']?window.CONFIG.assets['269207482'].data:null).substring(0,200);
1113
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:beforeParse',message:'Before _parseApplicationProperties',data:{fontAssetDataPreview:configBeforeParse},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{});
1114
- // #endregion
1115
-
1116
- this._parseApplicationProperties(window.CONFIG, callback);
1117
- } catch (e) {
1118
- // #region agent log
1119
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:parseError',message:'Error in _parseApplicationProperties',data:{error:e.message,stack:e.stack?e.stack.substring(0,500):''},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'C'})}).catch(()=>{});
1120
- // #endregion
1121
-
1122
- // 如果失败,回退到原始方法
1123
- if (originalConfigure) {
1124
- return originalConfigure.call(this, url, callback);
1125
- } else {
1126
- if (callback) callback(e);
1127
- }
1128
- }
1129
- return;
1130
- }
1131
-
1132
- // #region agent log
1133
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:usingOriginal',message:'Using original configure method',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'A'})}).catch(()=>{});
1134
- // #endregion
1135
-
1136
- // 否则使用原始方法
1137
- if (originalConfigure) {
1138
- return originalConfigure.call(this, url, callback);
1139
- }
1140
- };
1141
-
1142
- // 拦截关键方法以追踪初始化流程
1143
- if (ApplicationPrototype.preload) {
1144
- var originalPreload = ApplicationPrototype.preload;
1145
- ApplicationPrototype.preload = function(callback) {
1146
- // #region agent log
1147
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:preloadCalled',message:'app.preload called',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H'})}).catch(()=>{});
1148
- // #endregion
1149
- return originalPreload.call(this, function(err) {
1150
- // #region agent log
1151
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:preloadComplete',message:'app.preload complete',data:{hasError:!!err,error:err?err.message:null},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H'})}).catch(()=>{});
1152
- // #endregion
1153
- if (callback) callback(err);
1154
- });
1155
- };
1156
- }
1157
-
1158
- if (ApplicationPrototype.scenes && ApplicationPrototype.scenes.loadScene) {
1159
- var originalLoadScene = ApplicationPrototype.scenes.loadScene;
1160
- ApplicationPrototype.scenes.loadScene = function(url, callback) {
1161
- // #region agent log
1162
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:loadSceneCalled',message:'app.scenes.loadScene called',data:{url:typeof url==='string'?url.substring(0,100):url},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H'})}).catch(()=>{});
1163
- // #endregion
1164
- return originalLoadScene.call(this, url, function(err, entity) {
1165
- // #region agent log
1166
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:loadSceneComplete',message:'app.scenes.loadScene complete',data:{hasError:!!err,error:err?err.message:null,hasEntity:!!entity},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'H'})}).catch(()=>{});
1167
- // #endregion
1168
- if (callback) callback(err, entity);
1169
- });
1170
- };
1171
- }
1172
-
1173
- if (ApplicationPrototype.start) {
1174
- var originalStart = ApplicationPrototype.start;
1175
- ApplicationPrototype.start = function() {
1176
- var appInstance = this;
1177
- // #region agent log
1178
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:startCalled',message:'app.start called',data:{isPlaying:appInstance.isPlaying},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'I'})}).catch(()=>{});
1179
- // #endregion
1180
- var result = originalStart.call(appInstance);
1181
- // #region agent log
1182
- setTimeout(function() {
1183
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:startComplete',message:'app.start complete',data:{isPlaying:appInstance.isPlaying},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'J'})}).catch(()=>{});
1184
- }, 100);
1185
- // #endregion
1186
- return result;
1187
- };
1188
- }
1189
-
1190
- // #region agent log
1191
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:patchComplete',message:'Patch applied successfully',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'D'})}).catch(()=>{});
1192
- // #endregion
1193
- }
1194
-
1195
- patchConfigure();
1196
-
1197
- // 拦截 loadModules 函数(启动脚本中的关键函数)
1198
- if (window.loadModules) {
1199
- var originalLoadModules = window.loadModules;
1200
- window.loadModules = function(modules, urlPrefix, doneCallback) {
1201
- // #region agent log
1202
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:loadModulesCalled',message:'loadModules called',data:{modulesCount:modules?modules.length:0,hasUrlPrefix:!!urlPrefix},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'F'})}).catch(()=>{});
1203
- // #endregion
1204
- return originalLoadModules.call(this, modules, urlPrefix, function() {
1205
- // #region agent log
1206
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:loadModulesComplete',message:'loadModules complete',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'F'})}).catch(()=>{});
1207
- // #endregion
1208
- if (doneCallback) doneCallback();
1209
- });
1210
- };
1211
- } else {
1212
- // #region agent log
1213
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:loadModulesNotDefined',message:'loadModules not defined yet',data:{},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'F'})}).catch(()=>{});
1214
- // #endregion
1215
- }
1216
-
1217
- // 追踪启动脚本执行
1218
- // #region agent log
1219
- var originalOnLoad = window.onload;
1220
- window.onload = function() {
1221
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:windowOnLoad',message:'window.onload fired',data:{hasCONFIG_FILENAME:!!window.CONFIG_FILENAME,hasSCENE_PATH:!!window.SCENE_PATH,hasPRELOAD_MODULES:!!window.PRELOAD_MODULES,preloadModulesCount:window.PRELOAD_MODULES?window.PRELOAD_MODULES.length:0},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'F'})}).catch(()=>{});
1222
- if (originalOnLoad) originalOnLoad();
1223
- };
1224
-
1225
- // 检查启动脚本是否会在 DOMContentLoaded 时执行
1226
- if (document.readyState === 'loading') {
1227
- document.addEventListener('DOMContentLoaded', function() {
1228
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:domContentLoaded',message:'DOMContentLoaded fired',data:{hasCONFIG_FILENAME:!!window.CONFIG_FILENAME,hasSCENE_PATH:!!window.SCENE_PATH,hasPRELOAD_MODULES:!!window.PRELOAD_MODULES},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'F'})}).catch(()=>{});
1229
- });
1230
- } else {
1231
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:domAlreadyLoaded',message:'DOM already loaded',data:{readyState:document.readyState,hasCONFIG_FILENAME:!!window.CONFIG_FILENAME,hasSCENE_PATH:!!window.SCENE_PATH,hasPRELOAD_MODULES:!!window.PRELOAD_MODULES},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'F'})}).catch(()=>{});
1232
- }
1233
-
1234
- // 添加定时器来检查启动脚本是否执行
1235
- setTimeout(function() {
1236
- // #region agent log
1237
- var appExists = typeof app !== 'undefined';
1238
- var canvas = document.getElementById('application-canvas');
1239
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:startupCheck2s',message:'Startup check after 2s',data:{hasApp:appExists,appIsPlaying:appExists&&app.isPlaying,hasCanvas:!!canvas,canvasWidth:canvas?canvas.width:0,canvasHeight:canvas?canvas.height:0},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'F'})}).catch(()=>{});
1240
- // #endregion
1241
- }, 2000);
1242
-
1243
- setTimeout(function() {
1244
- // #region agent log
1245
- var appExists = typeof app !== 'undefined';
1246
- var canvas = document.getElementById('application-canvas');
1247
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:startupCheck5s',message:'Startup check after 5s',data:{hasApp:appExists,appIsPlaying:appExists&&app.isPlaying,hasCanvas:!!canvas,canvasWidth:canvas?canvas.width:0,canvasHeight:canvas?canvas.height:0},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'F'})}).catch(()=>{});
1248
- // #endregion
1249
- }, 5000);
1250
-
1251
- setTimeout(function() {
1252
- // #region agent log
1253
- var appExists = typeof app !== 'undefined';
1254
- fetch('http://127.0.0.1:7243/ingest/cd641f99-8aa7-4e81-8bdc-9c76de322a79',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({location:'builder.ts:patchConfigure:startupCheck5s',message:'Startup check after 5s',data:{hasApp:appExists,appIsPlaying:appExists&&app.isPlaying,hasCanvas:!!document.getElementById('application-canvas'),canvasWidth:document.getElementById('application-canvas')?document.getElementById('application-canvas').width:0,canvasHeight:document.getElementById('application-canvas')?document.getElementById('application-canvas').height:0},timestamp:Date.now(),sessionId:'debug-session',runId:'run1',hypothesisId:'F'})}).catch(()=>{});
1255
- // #endregion
1256
- }, 5000);
1257
- // #endregion
1258
- })();
1259
- `;
1260
- }
1261
- /**
1262
- * 生成设置脚本 - 替代原始的 __settings__.js
1263
- * 使用 data URL 替代文件路径,以支持单 HTML 文件运行
1264
- */
1265
- generateSettingsScript(configDataUrl, sceneDataUrl) {
1266
- const appProps = this.configJson.application_properties || {};
1267
- const scripts = appProps.scripts || [];
1268
- // 处理预加载模块(如 Ammo.js)- 转换为 data URL
1269
- const preloadModules = this.generatePreloadModules();
1270
- return `
1271
- window.ASSET_PREFIX = "";
1272
- window.SCRIPT_PREFIX = "";
1273
- window.SCENE_PATH = "${sceneDataUrl || ''}";
1274
- window.CONTEXT_OPTIONS = {
1275
- 'antialias': ${appProps.antiAlias !== false},
1276
- 'alpha': ${appProps.transparentCanvas === true},
1277
- 'preserveDrawingBuffer': ${appProps.preserveDrawingBuffer === true},
1278
- 'deviceTypes': ['webgl2', 'webgl1'],
1279
- 'powerPreference': "default"
1280
- };
1281
- window.SCRIPTS = [${scripts.join(', ')}];
1282
- window.CONFIG_FILENAME = "${configDataUrl}";
1283
- window.INPUT_SETTINGS = {
1284
- useKeyboard: ${appProps.useKeyboard !== false},
1285
- useMouse: ${appProps.useMouse !== false},
1286
- useGamepads: ${appProps.useGamepads === true},
1287
- useTouch: ${appProps.useTouch !== false}
1288
- };
1289
- pc.script.legacy = ${appProps.useLegacyScripts === true};
1290
- window.PRELOAD_MODULES = ${JSON.stringify(preloadModules)};
1291
- `;
1292
- }
1293
- /**
1294
- * 生成预加载模块配置
1295
- * 对于 playable ads,只使用 JS fallback 版本,跳过 WASM(避免 data URL 加载问题)
1296
- */
1297
- generatePreloadModules() {
1298
- const modules = [];
1299
- // 查找 wasm 类型的资产(如 Ammo.js)
1300
- for (const [id, asset] of Object.entries(this.configJson.assets || {})) {
1301
- const assetData = asset;
1302
- if (assetData.type === 'wasm' && assetData.data) {
1303
- const moduleData = assetData.data;
1304
- const fallbackAssetId = moduleData.fallbackScriptId;
1305
- let fallbackUrl = '';
1306
- // 只获取 fallback script 的 data URL(纯 JS 版本)
1307
- if (fallbackAssetId && this.configJson.assets[fallbackAssetId]) {
1308
- const fallbackAsset = this.configJson.assets[fallbackAssetId];
1309
- fallbackUrl = fallbackAsset.file?.url || '';
1310
- }
1311
- // 只使用 fallback URL,跳过 WASM 和 glue script
1312
- // PlayCanvas 会自动使用 fallback 当 wasmUrl 和 glueUrl 为空时
1313
- if (moduleData.moduleName && fallbackUrl) {
1314
- modules.push({
1315
- moduleName: moduleData.moduleName,
1316
- glueUrl: '', // 清空 - 不使用 WASM 胶水脚本
1317
- wasmUrl: '', // 清空 - 不使用 WASM 二进制
1318
- fallbackUrl: fallbackUrl, // 只使用纯 JS fallback
1319
- preload: true
1320
- });
1321
- }
1322
- }
1323
- }
1324
- return modules;
1325
- }
1326
- /**
1327
- * 输出 ZIP 文件
1328
- */
1329
- async outputZIP(outputDir) {
1330
- return new Promise(async (resolve, reject) => {
1331
- const zipPath = path.join(outputDir, 'playable.zip');
1332
- const { createWriteStream } = await import('fs');
1333
- const stream = createWriteStream(zipPath);
1334
- const archive = archiver('zip', { zlib: { level: 9 } });
1335
- archive.pipe(stream);
1336
- try {
1337
- // 先创建临时 HTML 文件
1338
- const tempHtmlPath = path.join(outputDir, 'temp-index.html');
1339
- const htmlTemplate = await this.loadHTMLTemplate();
1340
- const assets = this.converter.getAssets();
1341
- // 创建 URL 映射
1342
- const urlMap = new Map();
1343
- for (const asset of assets) {
1344
- const dataUrl = this.converter.getDataUrl(asset.path);
1345
- if (dataUrl) {
1346
- urlMap.set(asset.path, dataUrl);
1347
- urlMap.set(`/${asset.path}`, dataUrl);
1348
- }
1349
- }
1350
- let html = this.converter.replaceUrlsWithBase64(htmlTemplate, urlMap);
1351
- if (this.options.inlineGameScripts !== false) {
1352
- html = await this.converter.inlineScripts(html);
1353
- }
1354
- html = this.platformAdapter.modifyHTML(html, assets);
1355
- const platformScript = this.platformAdapter.getPlatformScript();
1356
- html = html.replace('</body>', `<script>${platformScript}</script></body>`);
1357
- await fs.writeFile(tempHtmlPath, html, 'utf-8');
1358
- archive.file(tempHtmlPath, { name: 'index.html' });
1359
- // 如果启用外部文件,添加资产文件
1360
- if (this.options.externFiles) {
1361
- const assets = this.converter.getAssets();
1362
- const folderName = this.options.externFiles?.folderName || 'assets';
1363
- for (const asset of assets) {
1364
- const fullPath = path.join(this.projectDir, asset.path);
1365
- try {
1366
- await fs.access(fullPath);
1367
- archive.file(fullPath, { name: `${folderName}/${path.basename(asset.path)}` });
1368
- }
1369
- catch (error) {
1370
- console.warn(`Warning: Failed to add asset to ZIP: ${asset.path}`);
1371
- }
1372
- }
1373
- }
1374
- await archive.finalize();
1375
- stream.on('close', async () => {
1376
- const { statSync } = await import('fs');
1377
- const stats = statSync(zipPath);
1378
- this.sizeReport.total = stats.size;
1379
- this.sizeReport.assets['playable.zip'] = stats.size;
1380
- // 清理临时文件
1381
- try {
1382
- await fs.unlink(tempHtmlPath);
1383
- }
1384
- catch (e) {
1385
- // 忽略清理错误
1386
- }
1387
- resolve(zipPath);
1388
- });
1389
- stream.on('error', reject);
1390
- archive.on('error', reject);
1391
- }
1392
- catch (error) {
1393
- reject(error);
1394
- }
1395
- });
1396
- }
1397
- /**
1398
- * 加载 HTML 模板
1399
- */
1400
- async loadHTMLTemplate() {
1401
- // 尝试多个可能的路径
1402
- const possiblePaths = [
1403
- // 开发环境:从源目录
1404
- path.join(__dirname, '../../templates/playable-ad.html'),
1405
- // 生产环境:从 dist 目录
1406
- path.join(__dirname, '../templates/playable-ad.html'),
1407
- // 从项目根目录
1408
- path.join(this.projectDir, 'templates/playable-ad.html'),
1409
- ];
1410
- for (const templatePath of possiblePaths) {
1411
- try {
1412
- return await fs.readFile(templatePath, 'utf-8');
1413
- }
1414
- catch (error) {
1415
- // 继续尝试下一个路径
1416
- }
1417
- }
1418
- // 如果所有路径都失败,返回默认模板
1419
- return this.getDefaultTemplate();
1420
- }
1421
- /**
1422
- * 获取默认 HTML 模板
1423
- */
1424
- getDefaultTemplate() {
1425
- return `<!DOCTYPE html>
1426
- <html lang="zh-CN">
1427
- <head>
1428
- <meta charset="UTF-8">
1429
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
1430
- <title>Playable Ad</title>
1431
- <style>
1432
- * {
1433
- margin: 0;
1434
- padding: 0;
1435
- box-sizing: border-box;
1436
- }
1437
- html, body {
1438
- width: 100%;
1439
- height: 100%;
1440
- overflow: hidden;
1441
- background: #000;
1442
- }
1443
- #application-canvas {
1444
- display: block;
1445
- width: 100%;
1446
- height: 100%;
1447
- }
1448
- </style>
1449
- </head>
1450
- <body>
1451
- <canvas id="application-canvas"></canvas>
1452
- <!-- PlayCanvas Engine, Config 和 Start Script 将在这里注入 -->
1453
- </body>
1454
- </html>`;
1455
- }
1456
- /**
1457
- * 获取大小报告
1458
- */
1459
- getSizeReport() {
1460
- return this.sizeReport;
1461
- }
1462
- }