27 KiB
部署指南
目标:在一台家用 Windows 小主机上长期开服,让朋友通过局域网或公网来玩。macOS / Linux / Docker 放在后面。
所有命令都在项目根目录执行。遇到问题先运行 node tools/doctor.mjs(只读诊断)。
0. 资源需求
| 项目 | 说明 |
|---|---|
| 服务器 CPU | 战斗在各玩家浏览器里模拟(DESIGN §14),服务器只负责回合、经济和校验:每个房间每个作战回合约 1 ms CPU。AI 队友 / 掉线玩家的战场由服务器模拟:作战开始时 3 个 AI 战场在开发机上约 0.2–0.5 s CPU,小主机上可能要几秒(分成 8 ms 小片执行,不会卡住其他房间)。SP_VERIFY=all 会复算每个真人战场,CPU 明显增加,小主机建议保持 off 或 sample。 |
| 服务器内存 | 空闲约 100 MB,每个进行中的对局再增加几 MB。 |
| 网络 | 4 人对局中服务器每回合下行约 0.25 MB(DESIGN §14 实测)。首次进入游戏时浏览器要从主机下载所需的图片 / Spine 模型 / 音频(按需加载,之后走浏览器缓存),公网隧道带宽小时第一次会慢一些。 |
| 磁盘 | 素材约 440 MB(public/assets)+ 依赖约 125 MB(node_modules;整合包只带运行依赖,约 65 MB);可选的本地提取约 40 MB(.venv-extract)+ 70 MB 贴图(见第 6 节)。完整包解压后约 590 MB。 |
| 玩家设备 | 支持 WebGL 的现代浏览器(Chrome / Edge / Firefox / Safari 最新版),电脑或手机平板(横屏)。老旧设备可在设置里调低画质或访问 /?board=2d。 |
服务器无状态:房间和对局只存在内存里,没有数据库和存档,不需要备份。重启服务器会结束正在进行的对局(包括断线后本可在 24 小时内回来继续的独立模拟)。
1. Windows 小主机:一步步
1.1 安装与首次启动
- 安装 Node.js 22 LTS 和 Git(在 PowerShell 或「终端」里;用下面的整合包时不需要 Git):
装完关闭并重新打开终端,
winget install OpenJS.NodeJS.LTS winget install Git.Gitnode -v应显示 v22 或更高(winget 的 LTS 目前是 v24.x,同样可用)。没有 winget 时从 https://nodejs.org/zh-cn/download 和 https://git-scm.com/download/win 下载安装。 - 下载,三选一。建议放在一个固定、短、不在 OneDrive 同步范围内的目录,例如
C:\Stronghold-Protocol:- 完整包(推荐):在仓库的 Releases 页面下载最新版本的
Stronghold-Protocol-v<版本>.zip(约 400 MB,解压后约 590 MB;已含运行依赖、前端库和全部素材,包括官方 3D 棋盘等本地客户端素材),解压后把里面的Stronghold-Protocol文件夹放到上述位置。不需要 Git,首次启动也不用再下载素材。素材版权归上海鹰角网络 / Yostar,仅限非商业使用,见 NOTICE.md。 - 精简包:同一页面的
Stronghold-Protocol-v<版本>-lite.zip(约 21 MB)。代码、运行依赖和前端库与完整包相同,但不带素材:美术、Spine 模型、音频、字体、表情和「玩法说明」教程图在首次启动时由 setup 从公开镜像下载(约 440 MB,显示进度,可中断续传;镜像设置见下面的「国内镜像下载」)。官方 3D 棋盘等本地客户端素材需要用本机客户端提取,或从同一版本的完整包复制(第 6 节)。适合下载大文件不方便、或想先下一个小包的情况;放置方式同完整包。 - 源码:
git clone https://github.com/sganggs/Stronghold-Protocol.git C:\Stronghold-Protocol
- 完整包(推荐):在仓库的 Releases 页面下载最新版本的
- 双击
C:\Stronghold-Protocol\scripts\start-windows.bat。首次会:安装依赖(npm ci;整合包已含,跳过)→ 复制前端库(整合包已含,跳过)→ 下载约 440 MB 素材(完整包已含,跳过;精简包和源码在这一步下载,显示进度,中断后再次启动会续传)→ 若检测到本机的明日方舟客户端,询问是否提取官方贴图(可跳过)→ 启动服务器并打开浏览器。 - 窗口里会打印朋友可用的地址,例如
http://192.168.1.23:3000。用另一台设备打开它确认能进入。关闭窗口即停止服务器。
等价的手动命令:npm ci、node tools/setup.mjs、npm start。
国内镜像下载
Setup 默认使用「GitHub 原始源 → jsDelivr」,不查询公网 IP,也不请求 gh-proxy.com。GitHub 下载失败时会提示如何手动开启镜像;仅添加提示,不自动切换到第三方代理。
镜像方法是在完整 GitHub 链接前加 https://gh-proxy.com/,例如:
https://gh-proxy.com/https://raw.githubusercontent.com/OWNER/REPO/BRANCH/file.png
手动开启后顺序为「前缀镜像 → 原始源 → jsDelivr」。索引、图片、Spine、音频和字体都使用此规则(音频 voice 分支跳过 jsDelivr)。镜像是第三方代理;当前只校验格式和大小,没有内容哈希校验,请自行决定是否信任并启用。npm / pip 依赖不使用 GitHub 前缀。
node tools/setup.mjs --asset-source=mirror # 手动优先国内镜像
node tools/setup.mjs --asset-source=direct # 默认:仅原始源和 jsDelivr,不使用前缀代理
$env:SP_ASSET_SOURCE = 'mirror' # 也可用环境变量显式启用
node tools/fetch-assets.mjs 同样支持 --asset-source=direct|mirror。命令行优先于 SP_ASSET_SOURCE。默认镜像前缀为 https://gh-proxy.com/,可通过 SP_GITHUB_PROXY 指定其他 HTTPS 前缀;仅配置前缀不会启用镜像。将 SP_GITHUB_PROXY 设为空字符串(或全空格)可彻底禁用前缀代理,即使选择了 mirror 模式;未设置此变量与显式设空不同,前者使用默认前缀。Windows PowerShell 的某些版本会将空值视为删除变量,可设置 $env:SP_GITHUB_PROXY = ' ' 或使用 --asset-source=direct 来明确禁用。前缀只处理 GitHub 下载链接,不重复添加。
镜像请求每个 URL 只尝试一次,响应头超时 8 秒,响应体有独立的空闲超时,失败即尝试原始源。连续 3 次网络错误、HTTP 错误或无效内容会在本次运行中关闭镜像,后续索引、素材和字体共享该状态;正在进行的镜像请求也会中止并回退。成功会清零连续失败次数;404 / 410 是资源不存在,不触发熔断。再次运行脚本会重新尝试手动启用的镜像。原始源的重试、已有文件跳过和 0.1.1 的清单缩减保护保持不变。
从历史下载记录派生的 Spine 补充贴图也按本次设置重新选择来源,禁用后不会沿用旧代理地址。
1.2 防火墙
- 第一次启动时 Windows 会弹出「Windows 安全中心警报」:勾选专用网络并点「允许访问」。
- 没弹窗或点错了,用管理员 PowerShell 添加规则(下面的开机自启脚本也会自动添加):
netsh advfirewall firewall add rule name="Stronghold Protocol" dir=in action=allow protocol=TCP localport=3000 profile=private,domain - 家里的网络要是「公用网络」,Windows 会拦截入站连接。改成专用(管理员 PowerShell;网卡名用
Get-NetConnectionProfile查看):Set-NetConnectionProfile -InterfaceAlias "以太网" -NetworkCategory Private node tools/doctor.mjs会显示规则是否存在、每个网络的类型,以及朋友可用的地址。
1.3 固定局域网 IP(推荐)
主机 IP 变了,朋友收藏的地址就失效。推荐在路由器后台的「DHCP 静态分配 / 地址保留」里把小主机的 MAC 地址绑定到固定 IP(如 192.168.1.50)。也可以在 Windows「设置 → 网络和 Internet → 属性 → IP 分配 → 编辑」里手动设置(IP、子网掩码、网关、DNS 与路由器一致,且不要与别的设备冲突)。
1.4 开机自动在后台运行
先关闭 start-windows.bat 的窗口(否则端口冲突),然后在项目目录运行(会自动请求管理员权限):
powershell -ExecutionPolicy Bypass -File scripts\install-service-windows.ps1
它会:运行一次 tools/setup.mjs → 把设置写入 scripts\service.env.cmd(node.exe 路径、端口等)→ 注册计划任务 StrongholdProtocol(开机 20 秒后以 SYSTEM 身份运行 scripts\run-server.cmd,无需登录;服务器退出后 5 秒自动重启)→ 添加防火墙规则 → 立即启动并显示状态。日志在 logs\server.log(超过 10 MB 自动轮换)。
| 需求 | 命令(都加在 powershell -ExecutionPolicy Bypass -File scripts\install-service-windows.ps1 之后) |
|---|---|
| 换端口 / 其他设置 | -Port 8080、-Verify sample、-Combat server、-BindHost 127.0.0.1(只给反向代理用) |
| 公用网络也放行 | -AllowPublicNetwork(一般不需要;Tailscale 网卡被识别为公用网络时可能需要) |
| 查看状态和最近日志 | -Status |
| 重启(更新代码后) | -Restart |
| 停止 | -Stop(下次开机仍会自动启动) |
| 卸载 | -Uninstall(删除计划任务、防火墙规则和 service.env.cmd) |
建议同时关闭睡眠,否则小主机会在无人操作时休眠:powercfg /change standby-timeout-ac 0。
替代方案:用 NSSM 注册成真正的 Windows 服务
winget install NSSM.NSSM # 或从 https://nssm.cc 下载
nssm install StrongholdProtocol "C:\Program Files\nodejs\node.exe" server\index.js
nssm set StrongholdProtocol AppDirectory C:\Stronghold-Protocol
nssm set StrongholdProtocol AppEnvironmentExtra PORT=3000 HOST=0.0.0.0
nssm set StrongholdProtocol AppStdout C:\Stronghold-Protocol\logs\server.log
nssm set StrongholdProtocol AppStderr C:\Stronghold-Protocol\logs\server.log
nssm start StrongholdProtocol
防火墙规则仍需按 1.2 手动添加。两种方式只选一种。
1.5 更新
cd C:\Stronghold-Protocol
powershell -ExecutionPolicy Bypass -File scripts\install-service-windows.ps1 -Stop # 装了开机自启时
git checkout -- data/assets.json # 素材清单由 setup 重新生成,先还原以免 git pull 冲突
git pull
npm ci
node tools/setup.mjs # 补下载新增的素材(已有文件会跳过)
powershell -ExecutionPolicy Bypass -File scripts\install-service-windows.ps1 -Restart
没装开机自启的话,最后一步改成重新双击 start-windows.bat。用 Releases 整合包的:停止服务器,把新版本的整合包解压到新目录后从那里启动即可(完整包已含素材;装了开机自启的,在新目录重新运行一次 install-service-windows.ps1)。用精简包或 GitHub「Download ZIP」源码包的:解压新版本后,把旧目录里的 public\assets、public\fonts、.cache 和 data\local-assets.json(若有)复制过去,可避免重新下载(setup 只补下新增的素材)。
2. 让不在同一网络的朋友加入
2.1 Tailscale / ZeroTier(推荐给家用小主机)
组一个虚拟局域网:不需要公网 IP、不需要改路由器、不暴露到互联网。
- Tailscale:主机和朋友都安装 https://tailscale.com/download(Windows:
winget install Tailscale.Tailscale)并登录。朋友用自己的账号时,在 Tailscale 管理后台把这台主机「Share」给他们,或邀请他们加入你的 tailnet。朋友访问http://<主机的 100.x.y.z 地址>:3000(tailscale ip -4查看;开了 MagicDNS 也可以用http://<主机名>:3000)。 - ZeroTier:在 https://my.zerotier.com 创建网络,主机和朋友安装客户端并加入同一个 Network ID,在后台勾选授权成员;访问
http://<主机的 ZeroTier IP>:3000。 - 连不上时运行
node tools/doctor.mjs:看 VPN 网卡是否被 Windows 识别为「公用网络」,是的话按 1.2 改为专用,或安装自启时加-AllowPublicNetwork。
2.2 cloudflared 临时隧道(朋友什么都不用装)
winget install --id Cloudflare.cloudflared # macOS: brew install cloudflared
cloudflared tunnel --url http://localhost:3000
把输出的 https://xxxx.trycloudflare.com 发给朋友。页面是 https 时客户端自动改用 wss://,不需要任何配置;服务器会通过隧道转发的 CF-Connecting-IP 识别真实来源(TRUST_PROXY=auto)。临时隧道每次启动地址都不同,且没有可用性保证;需要固定地址请使用 Cloudflare 账号 + 自己域名的「命名隧道」。
2.3 路由器端口转发
仅当你有公网 IPv4(很多宽带是运营商级 NAT,没有公网 IP,此时请用 2.1 / 2.2):
- 先按 1.3 固定主机的局域网 IP。
- 路由器「虚拟服务器 / 端口转发」:外部端口 3000(或任意端口)→ 内部
主机IP:3000,TCP。 - 朋友访问
http://<你的公网 IP>:外部端口。
注意:游戏没有账号系统,知道地址的人都能进来。服务器对来自互联网的连接有按网络的数量限制(每个网络最多 64 个连接,房间 / 对局数量也有上限),但仍建议不玩时关掉转发,或优先用 Tailscale。
2.4 反向代理与 HTTPS(有域名时)
必须部署在域名根路径(客户端使用 /data/、/vendor/、/ws 等绝对路径,不支持挂在子路径下)。代理需要转发 WebSocket 升级(路径 /ws)。建议让服务器只监听本机:HOST=127.0.0.1(Windows 自启:-BindHost 127.0.0.1)。
Caddy(自动申请 HTTPS 证书,WebSocket 无需额外配置):
game.example.com {
reverse_proxy 127.0.0.1:3000
}
Nginx:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl http2; # 新版 Nginx(1.25.1 起)写成 listen 443 ssl; 加一行 http2 on;
server_name game.example.com;
ssl_certificate /etc/letsencrypt/live/game.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/game.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 1h; # WebSocket 长连接
}
}
HTTP/2:客户端由数百个小脚本模块组成(0.2.0 起进入对局时约 340 个),隔着公网时建议让代理以 HTTP/2 提供页面:所有模块走同一条连接,远距离玩家首次进入对局明显更快。Caddy 默认就是 HTTP/2;Nginx 见上面的 http2。服务器本身只说 HTTP/1.1,局域网或本机游玩不受影响。
https / wss 说明:页面通过 https 打开时客户端自动连接 wss://同一域名/ws;http 时用 ws://。服务器本身只提供 http,证书由代理 / 隧道负责。代理与服务器在同一台机器或内网时,TRUST_PROXY=auto 会信任它的 X-Forwarded-For / X-Real-IP;代理在公网另一台机器上时设 TRUST_PROXY=1(同时确保游戏端口只对代理开放)。
3. Docker
# A) 构建时下载素材(需要联网,约 440 MB)
docker build -t stronghold-protocol --build-arg FETCH_ASSETS=1 .
docker run -d --name stronghold -p 3000:3000 --restart unless-stopped stronghold-protocol
# B) 不把素材打进镜像:先在宿主机运行 node tools/setup.mjs,然后挂载
docker build -t stronghold-protocol .
docker run -d --name stronghold -p 3000:3000 --restart unless-stopped \
-v "$PWD/public/assets:/app/public/assets:ro" stronghold-protocol
镜像从源码(git clone)构建,Releases 的整合包不含 Dockerfile。镜像基于 node:22-alpine,多阶段构建,只含生产依赖;public/vendor 在构建时生成。.dockerignore 排除了 public/assets(不会把宿主机素材打进构建上下文);public/fonts、data/assets.json 和 data/local-assets.json 若存在会被复制进去。环境变量同 README(-e SP_VERIFY=sample 等)。健康检查:GET /healthz。
docker compose 示例:
services:
stronghold:
build:
context: .
args: { FETCH_ASSETS: "1" }
ports: ["3000:3000"]
restart: unless-stopped
environment:
SP_VERIFY: "off"
4. macOS / Linux 常驻
-
临时开服:
scripts/start.sh(或npm start),保持终端窗口打开。macOS 首次会询问是否允许 node 接受传入连接,选「允许」。 -
Linux systemd(
/etc/systemd/system/stronghold.service,路径与用户按实际修改):[Unit] Description=Stronghold Protocol game server After=network-online.target Wants=network-online.target [Service] WorkingDirectory=/opt/Stronghold-Protocol ExecStart=/usr/bin/node server/index.js Environment=PORT=3000 HOST=0.0.0.0 Restart=always RestartSec=5 User=stronghold [Install] WantedBy=multi-user.targetsudo systemctl daemon-reload && sudo systemctl enable --now stronghold;日志journalctl -u stronghold -f;防火墙sudo ufw allow 3000/tcp。
5. 排错
| 现象 | 处理 |
|---|---|
| 任何问题 | node tools/doctor.mjs:Node 版本、依赖、素材完整性、端口、局域网地址、防火墙、网络类型 |
端口已被占用 / EADDRINUSE |
已经有一个服务器在运行(自启任务?)或其他程序占用 3000:换端口 scripts\start-windows.bat --port 3001 |
| 朋友打不开页面 | 防火墙规则 / 网络类型(1.2);确认用的是 LAN 地址而不是 localhost;访客 Wi-Fi 常开启「AP 隔离」;不在同一网络请看第 2 节 |
| 画面是占位图、没有声音 | 素材没下完:重新运行 node tools/setup.mjs(会续传);缺失明细在 .cache/assets-report.json。默认仅原始源和 jsDelivr;可用 --asset-source=mirror 手动开启前缀镜像(见上文) |
| 素材下载很慢 / 失败 | 网络问题可随时中断,重新运行会跳过已完成的文件;node tools/fetch-assets.mjs --concurrency=4 降低并发。有文件没下载成功时,素材清单 data/assets.json 保持不变(脚本列出缺少的条目并以非零状态结束;游戏里缺的图片用占位图,缺的声音不播放),重新运行即可补齐 |
| 表情显示成默认图标、「玩法说明」只有文字要点 | 素材没下载完整:重新运行 node tools/setup.mjs(表情和教程图随其他素材一起从公开镜像下载,不需要客户端);缺失明细在 .cache/assets-report.json |
| 本地提取失败 | 游戏照常运行,只是第 6 节表格里的几样换成替代样式。确认客户端已下载全部资源;Python 版本太新导致依赖安装失败时,安装 Python 3.12 后删除 .venv-extract 再运行 node tools/setup.mjs --local |
| 3D 棋盘没出现 | 需要本地提取的棋盘贴图(node tools/doctor.mjs 会显示「3D 棋盘可用」),以及支持 WebGL2 的浏览器。没有客户端的服务器可以从同一版本的整合包复制本地素材(第 6 节) |
| 断线 | 同盟模拟 10 分钟内、独立模拟 24 小时内(config.constants.singleReconnectTime)用同一浏览器重新打开页面,自动回到原座位。同盟掉线期间按原阵容自动作战、到时自动准备(不会代为购买;想让 AI 代打请用「离开模拟 → 暂离(AI 托管)」);独立模拟不计时,等你回来 |
6. 本地客户端素材(可选)
public/assets/local/ 和 data/local-assets.json 是从本机安装的《明日方舟》客户端里提取的官方素材(tools/local-extract,DESIGN §13):node tools/setup.mjs 检测到客户端时会询问是否提取,之后可以用 node tools/setup.mjs --local 重新提取,或用 --game "<…/StreamingAssets/AB/Windows>" 指定客户端目录。setup 从公开镜像下载的素材不包含这部分,所以在没有客户端的电脑上(例如 Linux 服务器)用源码或精简包部署时不会有它;Releases 的完整包里已经带上了。
没有本地素材时游戏照常运行,只是下面几样换成替代样式:
| 内容 | 没有本地素材时 |
|---|---|
| 官方 3D 棋盘(贴图、模型、地图特效) | 2D 棋盘,地块由程序绘制 |
| 部分官方界面图标与底板:交流按钮和表情面板的边框、暂停面板、装备替换窗口、干员调配界面、队友状态与漏怪标记、模组类型图标等 | 样式相近的替代图形、图标或文字 |
| 灼热 / 炽焰源石虫的官方模型 | 染成橙色 / 红橙色的普通源石虫 |
| 39 个召唤物的官方模型(多数自选召唤物,以及凯瑟琳的爬行号·防护单元、凛御银灰的风雪之眼;公开镜像没有) | 召唤物头像(菱形底板) |
表情(6 套 × 6 个)和「玩法说明」的 19 页教程图公开镜像也有:node tools/setup.mjs 会和其他素材一起下载(约 21 MB),不需要客户端;有本地素材时优先显示本地的。
没有客户端的服务器想要上表中的官方素材:从同一版本的完整包(Releases)里,把 public/assets/local/ 文件夹和 data/local-assets.json 复制到服务器项目目录下的相同位置。服务器每次请求都会重新读取这两处,不必重启,玩家刷新页面即可。一定要用与服务器代码相同版本的完整包:各版本提取的内容和清单可能不同(例如灼热 / 炽焰源石虫的模型是 0.1.0 之后才加入的,召唤物模型是 0.2.0 加入的),混用其他版本的文件会缺图或用错图。复制后 node tools/doctor.mjs 会显示本地素材的条目数和「3D 棋盘可用」。
0.2.0 之前提取过的:召唤物模型是 0.2.0 新增的提取项,旧的提取结果里没有(node tools/setup.mjs 会提示「缺少新版的自选召唤物模型」)。有客户端的电脑运行 node tools/setup.mjs --local 重新提取即可,只想补这一项也可以在提取用的 Python 环境里运行 tools/local-extract/extract.py --only spine/token(新文件写入 public/assets/local/spine/token/,清单里其他条目保持不变)。
3D 棋盘贴图的下载量:每位玩家进入对局时都要从开服的电脑下载 3D 棋盘的 12 张贴图。提取时会给这 12 张各写一份 WebP(颜色贴图有损、质量 95,法线和数据贴图无损),清单里列的是 WebP,同名 PNG 留在旁边给裁切工具和 setup 用。这部分下载量从约 6.7 MB 降到约 2 MB,网速慢的远程联机最明显。只有 PNG 的本地素材(例如在这一改动之前提取的)可以用提取时的 Python 环境运行 tools/local-extract/extract.py --webp 就地补上,只需要 Pillow,不需要客户端。
7. 打包发布(维护者)
Releases 的两个 zip 由 tools/package.mjs 生成,在源码仓库里运行(整合包里没有这个工具):
npm run package -- --dry-run --list # 只检查:列出每个文件和大小,不写任何文件(精简包加 --lite)
npm run package -- --out <目录> # 完整包 Stronghold-Protocol-v<版本>.zip
npm run package:lite -- --out <目录> # 精简包 Stronghold-Protocol-v<版本>-lite.zip
- 打进去的:
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),再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)、其他文档、研究笔记和docs/img/、handoff/、.github/、types/、lint / 编辑器 / Docker 配置。和 0.1.x 的整树打包相比,完整包少了约 570 个文件、解压后小约 25 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保留打包用的目录供检查。