Complete Cocos Creator port with level bundles, themes, and tooling.

Adds level prefabs, theme assets, audio, extensions, and deployment scripts for the Unity WebGL migration.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-16 15:30:58 +08:00
parent cba5105908
commit d393302388
6248 changed files with 17322729 additions and 11036 deletions

View File

@@ -0,0 +1,111 @@
#!/usr/bin/env node
/**
* 为运行时包生成 OSS 上传清单(不复制文件 — 本地与 CDN 共用同一目录)。
*
* node tools/write-deploy-manifest.js [packDir] [--cdn-base URL] [--manifest-dir DIR] [--zip]
*
* 运行时包: build/mstest5/ ← 上传此目录全部内容到 unitycdndir
* 清单输出: build/deploy/UPLOAD-MANIFEST.txt不进 OSS
*/
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const { dirSize, formatBytes } = require('./package-optimize');
const { listRuntimeFiles, bundleNamesFromCatalog } = require('./runtime-pack');
const argv = process.argv.slice(2);
const flags = new Set(argv.filter((a) => a.startsWith('--')));
const positional = argv.filter((a) => !a.startsWith('--'));
const PROJECT = path.resolve(__dirname, '..');
const packDir = path.resolve(positional[0] || path.join(PROJECT, 'build/mstest5'));
const manifestDir = (() => {
const i = argv.indexOf('--manifest-dir');
return path.resolve(i >= 0 ? argv[i + 1] : path.join(PROJECT, 'build/deploy'));
})();
const cdnBase = (() => {
const i = argv.indexOf('--cdn-base');
return i >= 0 ? argv[i + 1] : '';
})();
const makeZip = flags.has('--zip');
if (!fs.existsSync(path.join(packDir, 'Build/mstest5.loader.js'))) {
console.error('错误: 无效运行时包,请先 bash tools/package-for-project.sh');
console.error(' 期望:', packDir);
process.exit(1);
}
const files = listRuntimeFiles(packDir);
const catalogPath = path.join(packDir, 'StreamingAssets/aa/catalog.json');
const bundleNames = bundleNamesFromCatalog(catalogPath);
const base = (cdnBase || 'https://YOUR_CDN/unitycdndir').replace(/\/$/, '');
fs.mkdirSync(manifestDir, { recursive: true });
const manifestPath = path.join(manifestDir, 'UPLOAD-MANIFEST.txt');
const readmePath = path.join(manifestDir, 'README.txt');
const lines = [
'# OSS 上传清单(自动生成)',
`# 生成时间: ${new Date().toISOString()}`,
`# 运行时包目录: ${packDir}`,
`# OSS 根路径 (unitycdndir): ${base}`,
'#',
'# 上传方式: 将「运行时包目录」内全部内容原样上传到 OSS',
'# 本地 static/unity 与 OSS 文件完全一致,前端仅 config.js usecdn 切换根 URL',
'#',
`# ossutil cp -r "${packDir}/" oss://BUCKET/PATH/`,
'',
'## 运行时包文件(本地 = CDN',
...files.map((f) => `- ${f.rel}`),
'',
'## OSS 目标路径',
...files.map((f) => `${base}/${f.rel}`),
'',
'## 上传后验证',
`curl -I "${base}/Build/mstest5.loader.js"`,
`curl -I "${base}/StreamingAssets/aa/catalog.json"`,
`curl -I "${base}/levels-database.json"`,
...bundleNames.map((n) => `curl -I "${base}/StreamingAssets/aa/WebGL/${n}"`),
];
fs.writeFileSync(manifestPath, lines.join('\n'), 'utf8');
const readme = [
'部署说明',
'========',
'',
`生成: ${new Date().toLocaleString('zh-CN')}`,
'',
'运行时包(本地与 OSS 相同):',
` ${packDir}/`,
' ├── Build/',
' ├── StreamingAssets/',
' └── levels-database.json(.br)',
'',
'本地: import-to-unity.sh → scratch-gui/static/unity/(同上结构)',
'CDN: 上传运行时包全部内容 → config.js unitycdndir + usecdn:true',
'',
`包体积: ${formatBytes(dirSize(packDir))}`,
`详细路径: ${manifestPath}`,
'',
'独立调试页(不进 OSS / static:',
` ${path.join(path.dirname(packDir), 'standalone-player')}/index.html`,
].join('\n');
fs.writeFileSync(readmePath, readme, 'utf8');
let zipPath = '';
if (makeZip) {
zipPath = path.join(path.dirname(packDir), 'mstest5-runtime.zip');
if (fs.existsSync(zipPath)) fs.unlinkSync(zipPath);
const items = ['Build', 'StreamingAssets'];
if (fs.existsSync(path.join(packDir, 'levels-database.json'))) items.push('levels-database.json');
if (fs.existsSync(path.join(packDir, 'levels-database.json.br'))) items.push('levels-database.json.br');
execSync(`cd "${packDir}" && zip -0 -q -r "${zipPath}" ${items.join(' ')}`, { stdio: 'pipe' });
}
console.log('>>> 运行时包:', packDir);
console.log(`>>> 文件数: ${files.length}, 体积: ${formatBytes(dirSize(packDir))}`);
console.log('>>> 上传清单:', manifestPath);
if (zipPath) {
console.log(`>>> ZIP: ${zipPath} (${formatBytes(fs.statSync(zipPath).size)})`);
}