diff --git a/README.md b/README.md index 832df396..75b77d84 100644 --- a/README.md +++ b/README.md @@ -245,7 +245,7 @@ GOLDEN_FULL=1 node --test test/golden.test.js # 黄金结果:固定 An **unofficial, non-commercial fan remake** of Arknights' seasonal auto-chess tower-defense mode *Stronghold Protocol: Alliance*, played in the browser: solo, or 1–4 player co-op (AI teammates can fill seats). Combat is simulated in each player's browser, so a low-power PC can host. -- **Run:** download the full bundle `Stronghold-Protocol-v.zip` (~430 MB, all the art inside) from [Releases](../../releases/latest) — or the lite one, `…-lite.zip` (~22 MB), which downloads the art (~460 MB) on its first start — install Node.js 22 or 24, then double-click `scripts\start-windows.bat` (Windows) or run `./scripts/start.sh` (macOS / Linux) and open . From source: `npm install && npm run setup && npm start` (setup downloads ~460 MB of art from public mirrors, the emotes and the how-to-play pages included; the official 3D board, some official HUD icons and two enemy models are extracted from a local Arknights client — without one the game uses the 2D board and look-alike stand-ins, and a server can copy `public/assets/local/` and `data/local-assets.json` from the full bundle of the same version). +- **Run:** download the full bundle `Stronghold-Protocol-v.zip` (~430 MB, all the art inside) from [Releases](../../releases/latest) — or the lite one, `…-lite.zip` (~22 MB), which downloads the art (~460 MB) on its first start — install Node.js 22 or 24, then double-click `scripts\start-windows.bat` (Windows) or run `./scripts/start.sh` (macOS / Linux) and open . From source: `npm install && npm run setup && npm start` (setup downloads ~460 MB of art from public mirrors, the emotes and the how-to-play pages included; the official 3D board, some official HUD icons, two enemy models and 39 summon models are extracted from a local Arknights client — without one the game uses the 2D board and look-alike stand-ins (the summons show their avatars), and a server can copy `public/assets/local/` and `data/local-assets.json` from the full bundle of the same version). - **Play with friends:** create a co-op room and share the 4-letter key or the `?room=KEY` link. On a LAN, use the address printed at start; otherwise use a virtual-LAN tool, a tunnel or a VPS — see [docs/DEPLOY.md](docs/DEPLOY.md). - **Disclaimer:** not affiliated with or endorsed by Hypergryph or Yostar. All Arknights names, art, audio, text and data are © their respective owners and are **not** covered by this project's GPL licence. For study and personal non-commercial use only — no selling, paid distribution, paid servers or monetisation of any kind. Content will be removed on request of the rights holders. Provided "as is", without warranty. - **License:** code GPL-3.0-or-later ([LICENSE](LICENSE)); game assets excluded. diff --git a/docs/DEPLOY.md b/docs/DEPLOY.md index 2d91bd0b..05109002 100644 --- a/docs/DEPLOY.md +++ b/docs/DEPLOY.md @@ -301,6 +301,6 @@ npm run package:lite -- --out <目录> # 精简包 Stronghold-Protocol-v<版 ``` - **打进去的**:`git ls-files` 里的 `server/`、`shared/`、`data/`、`public/`(不含 `public/dev/`)、`packs/`(随仓库提交的内容包;只在本机安装、没提交的不打进去)、启动脚本、玩家会运行的工具(setup、vendor、fetch-assets 与 `tools/assets/`、doctor,以及 setup 调用的 `tools/local-extract/` 和 `crop-board-atlas.mjs`)、服务器和 fetch-assets 读取的 4 张研究数据表(`docs/research/` 的 `03-operators`、`05-enemies`、`05-maps`、`07-assets` 四个 JSON)、`package.json` / `package-lock.json`、许可证与说明(`LICENSE`、`NOTICE.md`、`THIRD-PARTY-NOTICES.md`、`README.md`、`CHANGELOG.md`)、`docs/PLAYING.md` 和本文;然后在临时目录里生成 `packs/index.json`(打进去的语言包和内容包的列表,供纯静态托管使用;服务器自己会实时列出,见 [PACKS.md](PACKS.md)),再 `npm ci --omit=dev` 装上运行依赖和 `public/vendor`。完整包再加上 `data/assets.json` 列出的素材、`public/fonts`,以及本地提取的 `public/assets/local/` 和 `data/local-assets.json`。磁盘上有、清单却没列出的文件不打进去(例如 0.2.0 移出自选的焰狐龙梓兰的旧素材)。 -- **不打进去的**:`test/`、维护用的工具(数据构建、golden、botbench、i18n、导入检查、本工具等)、`scripts/make-windows-bundle.mjs`(Windows 便携包,见 [WINDOWS.md](WINDOWS.md))、其他文档、研究笔记和 `docs/img/`、`handoff/`、`.github/`、`types/`、lint / 编辑器 / Docker 配置。和 0.1.x 的整树打包相比,完整包少了约 570 个文件、解压后小约 25 MB,zip 小约 8 MB。 +- **不打进去的**:`test/`、维护用的工具(数据构建、golden、botbench、i18n、导入检查、本工具等)、`scripts/make-windows-bundle.mjs`(Windows 便携包,见 [WINDOWS.md](WINDOWS.md))、其他文档、研究笔记和 `docs/img/`、`handoff/`、`.github/`、`types/`、lint / 编辑器 / Docker 配置。和 0.1.x 的整树打包(全部跟踪文件加上 `public/assets` 的全部内容)相比,0.2.0 的完整包少了约 640 个文件、解压后小约 26 MB,zip 小约 8 MB。 - **打包前的检查**(`--dry-run` 也全部做一遍):拒绝名单(`pv`、`review`、`.cache`、`.claude`、`.git`、`logs`、`.env`、`scripts/service.env.cmd`、`handoff`、`test` 等);每个打进去的模块的相对导入、玩家用的 npm 脚本(start / setup / doctor / launch / postinstall / vendor / assets)都指向包里的文件;完整包里 `data/assets.json` 和 `data/local-assets.json` 列出的文件都在(缺了先运行 `node tools/fetch-assets.mjs`);没有只差大小写的两个路径;包里的文件(二进制素材也查)不含个人目录路径(`/Users/…`、`C:\Users\…`、`/home/…`)或本机的账户名(运行时从系统读取;`SP_PACKAGE_SCAN_NAMES=a,b` 可以再加名字);打进去的已跟踪文件没有未提交的改动(重新生成的 `data/assets.json` 要先提交)。有任何问题都会列出原因、以非零状态结束,不写 zip;正式打包时还会核对临时目录里的文件和计划完全一致。 - **需要**:已下载素材的仓库(完整包)——打包前先联网运行一次 `node tools/fetch-assets.mjs`,补齐清单计划但本机还没有的素材(清单只列出磁盘上有的文件,打包工具看不出缺了哪些;`data/assets.json` 有变化就先提交);能访问 npm 的网络(`npm ci`);`zip`(或 bsdtar 的 `tar`,Windows 10 起自带)。`--out` 默认是系统临时目录下的 `stronghold-protocol-release`,不能在仓库里面;`--force` 覆盖已有的 zip,`--keep-stage` 保留打包用的目录供检查。 diff --git a/tools/setup.mjs b/tools/setup.mjs index 5f325131..067d49a1 100755 --- a/tools/setup.mjs +++ b/tools/setup.mjs @@ -8,7 +8,7 @@ // 2. Dependencies: `npm ci` (falls back to `npm install`) when node_modules is missing or incomplete. // 3. Client libraries in public/vendor (tools/vendor.mjs) when any is missing. // 4. Game data (data/*.json, committed) present and parseable. -// 5. Art/audio (tools/fetch-assets.mjs, ~270 MB into public/assets, resumable, mirror fallback) when public/assets +// 5. Art/audio (tools/fetch-assets.mjs, ~460 MB into public/assets, resumable, mirror fallback) when public/assets // is missing or data/assets.json lists files that are not on disk. A failure is a warning: the game still runs // with fallback visuals and the next run resumes. // 6. Optional: official board/UI art from a locally installed Arknights client (Windows native install, CrossOver @@ -76,6 +76,9 @@ export const nodeMajor = () => Number(process.versions.node.split('.')[0]); const exists = (p) => { try { fs.accessSync(p); return true; } catch { return false; } }; const readJson = (p) => { try { return JSON.parse(fs.readFileSync(p, 'utf8')); } catch { return null; } }; const mb = (n) => `${(n / 1048576).toFixed(0)} MB`; +/** The art download when data/assets.json gives no size (missing, unreadable or without stats.bytes): the 0.2.0 + * manifest's stats.bytes, 463 MB, as README and docs/DEPLOY.md quote it. */ +const ART_DOWNLOAD_FALLBACK = '460 MB'; /** Terminal display width (CJK / full-width characters take two columns). */ export const displayWidth = (s) => [...String(s)].reduce((n, ch) => n + (ch.codePointAt(0) >= 0x2e80 ? 2 : 1), 0); export const padDisplay = (s, w) => s + ' '.repeat(Math.max(0, w - displayWidth(s))); @@ -429,7 +432,7 @@ async function main() { let assets = checkAssets(); if (!opts.assets) add(assets.ok ? 'ok' : 'skip', '美术/音频 public/assets', assets.ok ? `${assets.total} 个文件` : '已跳过(--no-assets)'); else if (!assets.ok && deps.ok && !opts.check) { - const what = !assets.present ? `首次下载约 ${assets.bytes ? mb(assets.bytes) : '270 MB'},可随时中断,重新运行会续传` + const what = !assets.present ? `首次下载约 ${assets.bytes ? mb(assets.bytes) : ART_DOWNLOAD_FALLBACK},可随时中断,重新运行会续传` : `补全缺失的 ${assets.missing} 个文件`; log(`\n${c.cyan('▶')} 下载美术与音频素材(${what})…`); const r = run(process.execPath, [path.join(ROOT, 'tools', 'fetch-assets.mjs'), `--asset-source=${opts.source}`]);