#!/bin/bash # Cocos Web 构建 → 001code-html 可用的 unity 静态资源 + CDN 上传清单 # # 001code-html 加载约定(scratch-gui/src/components/stage-unity/stage-unity.jsx): # 本地 loader: /unity/Build/mstest5.loader.js (不走 CDN,须放 static/unity/Build/) # CDN 资源: {unitycdndir}/Build/*.br # {unitycdndir}/StreamingAssets/aa/... # # 用法: # bash tools/deploy-to-001code.sh # bash tools/deploy-to-001code.sh --build build/web-desktop # bash tools/deploy-to-001code.sh --code-html /path/to/001code-html # bash tools/deploy-to-001code.sh --skip-pack # 仅用已有 build/mstest5 同步 set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" BUILD_DIR="$PROJECT_DIR/build/web-desktop" PACK_DIR="$PROJECT_DIR/build/mstest5" CODE_HTML="/Users/liuyufei/tfrh/001code/001code-html" UNITY_STATIC="" UNITY_REF="" CDN_BASE="" SKIP_PACK=0 DRY_RUN=0 CDN_UPLOAD_ONLY=0 CDN_PURE=0 while [[ $# -gt 0 ]]; do case "$1" in --build) BUILD_DIR="$2"; shift 2 ;; --pack) PACK_DIR="$2"; shift 2 ;; --code-html) CODE_HTML="$2"; shift 2 ;; --unity-static) UNITY_STATIC="$2"; shift 2 ;; --unity-ref) UNITY_REF="$2"; shift 2 ;; --cdn-base) CDN_BASE="$2"; shift 2 ;; --skip-pack) SKIP_PACK=1; shift ;; --cdn-upload-only) CDN_UPLOAD_ONLY=1; shift ;; --cdn-pure) CDN_PURE=1; shift ;; --dry-run) DRY_RUN=1; shift ;; -h|--help) cat <<'EOF' Usage: deploy-to-001code.sh [options] 将 Cocos 包部署到 001code-html/scratch-gui/static/unity/,并生成 CDN 上传清单。 选项: --build DIR Cocos Web Desktop 构建目录(默认 build/web-desktop) --pack DIR package-for-cdn 输出目录(默认 build/mstest5) --code-html DIR 001code-html 根目录 --unity-static DIR 覆盖 static/unity 目标(默认 scratch-gui/static/unity) --unity-ref DIR catalog 参考包(默认 static/unity,否则 竞赛/mstest5) --cdn-base URL 覆盖 CDN 根 URL(默认从 config.js 读取 unitycdndir) --skip-pack 跳过打包,直接同步已有 --pack 目录 --cdn-upload-only 只打包运行时包 + 清单,不同步 static/unity --cdn-pure 不同步/不解压到 static/unity(纯 CDN,loader 也走 OSS) --dry-run 只打印将执行的 rsync,不写入 步骤: 1. package-for-cdn(以 001code static/unity 的 catalog 为参考) 2. rsync Build/、StreamingAssets/ → scratch-gui/static/unity/ 3. 生成 build/deploy-001code-cdn-manifest.txt 部署后请在 001code-html/scratch-gui 执行 npm run build,或 npm start 本地验证。 EOF exit 0 ;; *) echo "Unknown option: $1"; exit 1 ;; esac done CODE_HTML="$(cd "$CODE_HTML" 2>/dev/null && pwd || true)" if [[ -z "$CODE_HTML" || ! -d "$CODE_HTML/scratch-gui" ]]; then echo "Error: 001code-html 不存在: $CODE_HTML" exit 1 fi if [[ -z "$UNITY_STATIC" ]]; then UNITY_STATIC="$CODE_HTML/scratch-gui/static/unity" fi UNITY_STATIC="$(cd "$UNITY_STATIC" 2>/dev/null && pwd || true)" if [[ -z "$UNITY_STATIC" ]]; then echo "Error: static/unity 不存在,请先创建: $CODE_HTML/scratch-gui/static/unity" exit 1 fi mkdir -p "$UNITY_STATIC/Build" "$UNITY_STATIC/StreamingAssets" # package-for-cdn 需要完整 Unity 参考包(index.html + TemplateData + catalog) # static/unity 是 Cocos 扁平运行包,仅有 catalog 时不能作为参考 DEFAULT_UNITY_REF="${UNITY_REF:-$HOME/tfrh/竞赛/mstest5}" UNITY_REF_DIR="$(cd "$DEFAULT_UNITY_REF" 2>/dev/null && pwd || true)" if [[ -z "$UNITY_REF" && -f "$UNITY_STATIC/index.html" && -f "$UNITY_STATIC/StreamingAssets/aa/catalog.json" ]]; then UNITY_REF_DIR="$UNITY_STATIC" echo ">>> catalog 参考: static/unity(完整 Unity 包)" elif [[ -f "$UNITY_REF_DIR/StreamingAssets/aa/catalog.json" ]]; then echo ">>> catalog 参考: $UNITY_REF_DIR" else echo "Error: 缺少 Unity 参考包(须含 index.html 与 StreamingAssets/aa/catalog.json)" >&2 echo " 默认路径: $DEFAULT_UNITY_REF" >&2 echo " 可指定: bash tools/deploy-cdn.sh 所在脚本加 --unity-ref /path/to/mstest5" >&2 exit 1 fi if [[ "$SKIP_PACK" -eq 0 ]]; then BUILD_DIR="$(cd "$BUILD_DIR" 2>/dev/null && pwd || true)" if [[ -z "$BUILD_DIR" || ! -f "$BUILD_DIR/index.html" ]]; then echo "Error: 请先 Cocos Creator 构建 Web Desktop: $BUILD_DIR" exit 1 fi if [[ ! -f "$UNITY_REF_DIR/StreamingAssets/aa/catalog.json" ]]; then echo "Error: 缺少参考 catalog: $UNITY_REF_DIR/StreamingAssets/aa/catalog.json" echo " 请指定 --unity-ref 指向含 StreamingAssets/aa/catalog.json 的 Unity 包" exit 1 fi echo ">>> [1/3] 打包 (unity-ref = $UNITY_REF_DIR)" node "$SCRIPT_DIR/package-for-cdn.js" "$BUILD_DIR" "$PACK_DIR" "$UNITY_REF_DIR" else PACK_DIR="$(cd "$PACK_DIR" 2>/dev/null && pwd || true)" if [[ -z "$PACK_DIR" || ! -f "$PACK_DIR/Build/mstest5.loader.js" ]]; then echo "Error: --skip-pack 但打包目录无效: $PACK_DIR" exit 1 fi echo ">>> [1/3] 跳过打包,使用: $PACK_DIR" fi PACK_DIR="$(cd "$PACK_DIR" && pwd)" if [[ -z "$CDN_BASE" ]]; then CONFIG_JS="$CODE_HTML/scratch-gui/src/playground/config.js" if [[ -f "$CONFIG_JS" ]]; then CDN_BASE="$(node -e " const fs=require('fs'); const t=fs.readFileSync(process.argv[1],'utf8'); const m=t.match(/unitycdndir:\s*['\"]([^'\"]+)['\"]/); if(!m){process.exit(1)} console.log(m[1]); " "$CONFIG_JS" 2>/dev/null || true)" fi fi CDN_BASE="${CDN_BASE:-https://oss.eanic.cn/001_code_unity_res_CHANGE_ME}" CDN_DEPLOY_DIR="$PROJECT_DIR/build/deploy" if [[ "$DRY_RUN" -eq 1 ]]; then echo ">>> [1b] [dry-run] 生成上传清单 → $CDN_DEPLOY_DIR" else echo ">>> [1b] 生成上传清单(运行时包不复制: $PACK_DIR)" MANIFEST_ARGS=("$PACK_DIR" --manifest-dir "$CDN_DEPLOY_DIR") [[ -n "$CDN_BASE" ]] && MANIFEST_ARGS+=(--cdn-base "$CDN_BASE") node "$SCRIPT_DIR/write-deploy-manifest.js" "${MANIFEST_ARGS[@]}" fi if [[ "$CDN_UPLOAD_ONLY" -eq 1 ]]; then echo "" echo "完成(仅运行时包 + 清单)。" echo " 运行时包: $PACK_DIR" echo " 清单: $CDN_DEPLOY_DIR/UPLOAD-MANIFEST.txt" exit 0 fi if [[ "$CDN_PURE" -eq 1 ]]; then echo ">>> [2/3] 跳过 static/unity 同步(--cdn-pure,仅 OSS)" else echo ">>> [2/3] 同步到 static/unity(与运行时包相同)" if [[ "$DRY_RUN" -eq 1 ]]; then DRY_RUN=1 bash "$SCRIPT_DIR/sync-unity-package-to-static.sh" "$PACK_DIR" "$UNITY_STATIC" else bash "$SCRIPT_DIR/sync-unity-package-to-static.sh" "$PACK_DIR" "$UNITY_STATIC" fi fi MANIFEST="$PROJECT_DIR/build/deploy-001code-cdn-manifest.txt" mkdir -p "$(dirname "$MANIFEST")" echo ">>> [3/3] 生成 CDN 上传清单: $MANIFEST" { echo "# 001code-html CDN 上传清单" echo "# 生成时间: $(date -u '+%Y-%m-%dT%H:%M:%SZ')" echo "# CDN 根目录 (unitycdndir): $CDN_BASE" echo "#" echo "# 上传规则: 将 build/mstest5/ 全部内容上传到 OSS unitycdndir" echo "" echo "## CDN: Build/(unitycdnbuilddir = unitycdndir + /Build,含 loader.js)" for f in "$PACK_DIR/Build"/*; do [[ -f "$f" ]] || continue base="$(basename "$f")" echo "local: Build/$base" echo "cdn: $CDN_BASE/Build/$base" echo "" done echo "## CDN: StreamingAssets/(unitycdndir + /StreamingAssets)" while IFS= read -r -d '' f; do rel="${f#$PACK_DIR/StreamingAssets/}" echo "local: StreamingAssets/$rel" echo "cdn: $CDN_BASE/StreamingAssets/$rel" echo "" done < <(find "$PACK_DIR/StreamingAssets" -type f ! -name '.DS_Store' -print0 | sort -z) for db in levels-database.json levels-database.json.br; do if [[ -f "$PACK_DIR/$db" ]]; then echo "local: $db" echo "cdn: $CDN_BASE/$db" echo "" fi done echo "## 001code config.js 当前配置" echo "unitycdndir: $CDN_BASE" echo "unitycdnbuilddir: $CDN_BASE/Build" echo "streamingAssetsUrl (CDN): $CDN_BASE/StreamingAssets" echo "loaderUrl (CDN): $CDN_BASE/Build/mstest5.loader.js" echo "" echo "## 验证(上传后)" echo "curl -I \"$CDN_BASE/Build/mstest5.loader.js\"" echo "curl -I \"$CDN_BASE/StreamingAssets/aa/catalog.json\"" python3 - <<'PY' "$PACK_DIR/StreamingAssets/aa/catalog.json" "$CDN_BASE" import json, sys catalog_path, cdn = sys.argv[1], sys.argv[2].rstrip('/') d = json.load(open(catalog_path)) names = sorted({x.split('/')[-1] for x in d.get('m_InternalIds', []) if '.bundle' in x}) for n in names: print(f'curl -I "{cdn}/StreamingAssets/aa/WebGL/{n}"') PY } > "$MANIFEST" echo "" echo "完成。" if [[ "$CDN_PURE" -eq 1 ]]; then echo " 模式: 纯 CDN(未写入 static/unity)" else echo " 本地 static: $UNITY_STATIC" fi echo " CDN 运行时包: $PACK_DIR" echo " CDN 清单: $CDN_DEPLOY_DIR/UPLOAD-MANIFEST.txt" echo "" echo "下一步:" echo " cd \"$CODE_HTML/scratch-gui\"" if [[ "$CDN_PURE" -eq 1 ]]; then echo " config.js: usecdn:true → npm run build → 部署 dist/(无需 static/unity 游戏资源)" else echo " npm start # usecdn:false 本地测 static/unity" echo " npm run build # usecdn:true 生产构建" fi echo "" echo "生产 CDN: 上传 $PACK_DIR 全部内容到 OSS(见 deploy/UPLOAD-MANIFEST.txt)"