Ported by hand: - public/js/ui/gameLogic.js is a re-export shim on feedback5: #185's TERRAIN_TIPS / terrainInfo went into the new public/js/ui/gameLogic/terrain.js (the barrel gains one re-export line); closesOnFieldPress 'terrain' into ui/gameLogic/shortcuts.js. - i18n (docs/I18N.md): every new user-visible string goes through t() with an English entry in public/i18n/en.json (42, after the 补位 strings): the terrain names / tags / fact table are N_() and translated where terrainInfo hands them out, the mechanism lines are msgids with their numbers as params (a line with an optional half is two whole msgids, the list joins use an array param), the card's 地形机制 / 这一格 titles in ui/detailPanel.js. Official EN terms where the EN client has them (stage_table tileInfo: Active Originium, Mire, Exhaust Grille, Deep Water Zone, Incursion Point, Protection Objective, Tunnel Entry / Exit, High Ground; Camouflage). The Chinese output is byte-identical to feedback4's terrainInfo on all 5187 tiles of the 13 stages and on synthetic stages. - public/js/screens/game.js (MatchScreen still lives there): the import keeps feedback5's names plus terrainInfo / fieldTile; the terrain stage is the one view.setStage gets, so it includes feedback5's fieldStage — a 联防 field is played on its own map (GitHub #41), and a tap there explains that map's tile, not the round stage's. The tileClick handler and render/app.js emitTileClick / ui/fallbackField.js auto-merged in place. terrainInfo reads the stage only, so a 补位 / 自选 board explains its tiles the same way (their pieces only change a piece's art and name). - public/js/ui/detailPanel.js: the terrain branch of resolveDetail before feedback5's stand-in / 自选 helpers. - public/js/screens/title.js (#183): feedback5's LangToggle / t() imports plus GIcon / SettingsModal; the gear button's aria-label / title are t('设置') (en.json already has "Settings"). - tools/fetch-assets.mjs / tools/assets/downloader.mjs: --add-only (keepExisting, the font skip) beside #24's --asset-source / SP_ASSET_SOURCE and the shared MirrorPolicy; feedback5's extraOperators / moduleTypes and the voice plan unchanged. - data/assets.json: feedback5's manifest plus #134's audio.sfx.battle.leak (after heal, the plan order); stats files 6993 → 6994 and bytes +23 240 as measured on feedback4; the hash recomputed with the generator's contentHash (c01aa739a2d3 → 6a547fc5c937). A field-wise JSON diff against feedback5 shows only those four fields. - docs: DESIGN §24 intro and §24.5 / §24.6 as on feedback4 (the rest of DESIGN.md is feedback5's); ASSETS.md, DEPLOY.md, PLAYING.md auto-merged. - Auto-merged and checked: audio.js (the sim still emits ['leak', id], server/sim/battle/deploy.js), render/style.js, textures.js, tiles.js, board3d/materials.js, boardArt.js, tools/assets/*, tools/setup.mjs, extract.py, the tests. Checks: the PRs' unit tests (audio 22, gameLogic 44, terrain-detail 1, originium-art 4, boardart 15, board3d-extract 9, asset-network 21, fetch-assets-shrink 4), i18n 9 / i18n-data 8 / i18n-server 4, client-static 313, docs-consistency 24, kits_layout 6 pass; lint 0 errors (no new warnings), check:imports, typecheck; golden: all 283 scenarios match, nothing regenerated.
288 lines
21 KiB
Markdown
288 lines
21 KiB
Markdown
# 部署指南
|
||
|
||
目标:在一台家用 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 模型 / 音频(按需加载,之后走浏览器缓存),公网隧道带宽小时第一次会慢一些。 |
|
||
| 磁盘 | 素材约 270 MB(`public/assets`)+ 依赖约 125 MB(`node_modules`);可选的本地提取约 40 MB(`.venv-extract`)+ 70 MB 贴图(见第 6 节)。 |
|
||
| 玩家设备 | 支持 WebGL 的现代浏览器(Chrome / Edge / Firefox / Safari 最新版),电脑或手机平板(横屏)。老旧设备可在设置里调低画质或访问 `/?board=2d`。 |
|
||
|
||
服务器**无状态**:房间和对局只存在内存里,没有数据库和存档,**不需要备份**。重启服务器会结束正在进行的对局(包括断线后本可在 24 小时内回来继续的独立模拟)。
|
||
|
||
## 1. Windows 小主机:一步步
|
||
|
||
### 1.1 安装与首次启动
|
||
|
||
1. 安装 Node.js 22 LTS 和 Git(在 PowerShell 或「终端」里;用下面的完整包时不需要 Git):
|
||
```powershell
|
||
winget install OpenJS.NodeJS.LTS
|
||
winget install Git.Git
|
||
```
|
||
装完**关闭并重新打开**终端,`node -v` 应显示 v22 或更高(winget 的 LTS 目前是 v24.x,同样可用)。没有 winget 时从 <https://nodejs.org/zh-cn/download> 和 <https://git-scm.com/download/win> 下载安装。
|
||
2. 下载,二选一。建议放在一个固定、短、**不在 OneDrive 同步范围内**的目录,例如 `C:\Stronghold-Protocol`:
|
||
- **完整包(推荐)**:在仓库的 [Releases](https://github.com/sganggs/Stronghold-Protocol/releases) 页面下载最新版本(当前为 v0.1.3)的完整包 zip(已含依赖、前端库和全部素材,包括官方 3D 棋盘),解压后把里面的 `Stronghold-Protocol` 文件夹放到上述位置。不需要 Git,首次启动也不用再下载素材。素材版权归上海鹰角网络 / Yostar,仅限非商业使用,见 [NOTICE.md](../NOTICE.md)。
|
||
- **源码**:
|
||
```powershell
|
||
git clone https://github.com/sganggs/Stronghold-Protocol.git C:\Stronghold-Protocol
|
||
```
|
||
3. 双击 `C:\Stronghold-Protocol\scripts\start-windows.bat`。首次会:安装依赖(`npm ci`;完整包已含,跳过)→ 复制前端库 → 下载约 270 MB 素材(完整包已含,跳过;显示进度,中断后再次启动会续传)→ 若检测到本机的明日方舟客户端,询问是否提取官方贴图(可跳过)→ 启动服务器并打开浏览器。
|
||
4. 窗口里会打印朋友可用的地址,例如 `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/`,例如:
|
||
|
||
```text
|
||
https://gh-proxy.com/https://raw.githubusercontent.com/OWNER/REPO/BRANCH/file.png
|
||
```
|
||
|
||
手动开启后顺序为「前缀镜像 → 原始源 → jsDelivr」。索引、图片、Spine、音频和字体都使用此规则(音频 voice 分支跳过 jsDelivr)。镜像是第三方代理;当前只校验格式和大小,没有内容哈希校验,请自行决定是否信任并启用。npm / pip 依赖不使用 GitHub 前缀。
|
||
|
||
```powershell
|
||
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 添加规则(下面的开机自启脚本也会自动添加):
|
||
```powershell
|
||
netsh advfirewall firewall add rule name="Stronghold Protocol" dir=in action=allow protocol=TCP localport=3000 profile=private,domain
|
||
```
|
||
- 家里的网络要是「公用网络」,Windows 会拦截入站连接。改成专用(管理员 PowerShell;网卡名用 `Get-NetConnectionProfile` 查看):
|
||
```powershell
|
||
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
|
||
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`。
|
||
|
||
<details>
|
||
<summary>替代方案:用 NSSM 注册成真正的 Windows 服务</summary>
|
||
|
||
```powershell
|
||
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 手动添加。两种方式只选一种。
|
||
</details>
|
||
|
||
### 1.5 更新
|
||
|
||
```powershell
|
||
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`(若有)复制过去,可避免重新下载。
|
||
|
||
## 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 临时隧道(朋友什么都不用装)
|
||
|
||
```powershell
|
||
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. 先按 1.3 固定主机的局域网 IP。
|
||
2. 路由器「虚拟服务器 / 端口转发」:外部端口 3000(或任意端口)→ 内部 `主机IP:3000`,TCP。
|
||
3. 朋友访问 `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 无需额外配置):
|
||
|
||
```caddy
|
||
game.example.com {
|
||
reverse_proxy 127.0.0.1:3000
|
||
}
|
||
```
|
||
|
||
**Nginx**:
|
||
|
||
```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
|
||
|
||
```bash
|
||
# A) 构建时下载素材(需要联网,约 250 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
|
||
```
|
||
|
||
镜像基于 `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 示例:
|
||
|
||
```yaml
|
||
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`,路径与用户按实际修改):
|
||
|
||
```ini
|
||
[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.target
|
||
```
|
||
|
||
`sudo 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 棋盘,地块由程序绘制 |
|
||
| 部分官方界面图标与底板:交流按钮和表情面板的边框、暂停面板、装备替换窗口、干员调配界面、队友状态与漏怪标记、模组类型图标等 | 样式相近的替代图形、图标或文字 |
|
||
| 灼热 / 炽焰源石虫的官方模型 | 染成橙色 / 红橙色的普通源石虫 |
|
||
|
||
表情(6 套 × 6 个)和「玩法说明」的 19 页教程图公开镜像也有:`node tools/setup.mjs` 会和其他素材一起下载(约 21 MB),不需要客户端;有本地素材时优先显示本地的。
|
||
|
||
**没有客户端的服务器**想要上表中的官方素材:从**同一版本**的完整包([Releases](https://github.com/sganggs/Stronghold-Protocol/releases))里,把 `public/assets/local/` 文件夹和 `data/local-assets.json` 复制到服务器项目目录下的相同位置。服务器每次请求都会重新读取这两处,不必重启,玩家刷新页面即可。一定要用与服务器代码相同版本的完整包:各版本提取的内容和清单可能不同(例如灼热 / 炽焰源石虫的模型是 0.1.0 之后才加入的),混用其他版本的文件会缺图或用错图。复制后 `node tools/doctor.mjs` 会显示本地素材的条目数和「3D 棋盘可用」。
|
||
|
||
**3D 棋盘贴图的下载量**:每位玩家进入对局时都要从开服的电脑下载 3D 棋盘的 12 张贴图。提取时会给这 12 张各写一份 WebP(颜色贴图有损、质量 95,法线和数据贴图无损),清单里列的是 WebP,同名 PNG 留在旁边给裁切工具和 setup 用。这部分下载量从约 6.7 MB 降到约 2 MB,网速慢的远程联机最明显。只有 PNG 的本地素材(例如在这一改动之前提取的)可以用提取时的 Python 环境运行 `tools/local-extract/extract.py --webp` 就地补上,只需要 Pillow,不需要客户端。
|