feedback2 WE: review wording — ASSETS.md and DESIGN §13 say the HUD sprites are not downloaded (most are on the mirror), §22.5 says the mirror copies match the local sizes and that #38 stays open; setup's no-client row only points to DEPLOY §6 (doctor keeps the copy hint); stale test messages
This commit is contained in:
1 parent
7f7df66977
commit
fadeed2dc6
6 files changed
+16
-11
No files matched your search
+1
-1
@@ -271,7 +271,7 @@ Other renderer rules from research 07 §5.4–5.5:
|
||||
|
||||
### Other fallbacks
|
||||
|
||||
- **Emotes and 玩法说明 pages** (`public/js/data.js artUrls / nextArtUrl`): the local-client picture (`data/local-assets.json`) first, then the mirror copy (`ui['emoticon/…']`, `ui['guide/…']`), each tried in turn when one fails to load; with neither, the neutral emote glyph and the official tips text (`config.tips`). The rest of the local-client art (the 3D board, most official HUD sprites, module type icons, the two enemy models above) has no web copy: docs/DEPLOY.md §6 lists what falls back without it.
|
||||
- **Emotes and 玩法说明 pages** (`public/js/data.js artUrls / nextArtUrl`, `ui/guide.js guideStage`): the local-client picture (`data/local-assets.json`) first, then the mirror copy (`ui['emoticon/…']`, `ui['guide/…']`), each tried in turn when one fails to load; when none is left — none listed, or every copy failed (for example data/assets.json lists the downloaded pages but the files are not on disk yet: a `git pull` and restart without setup) — the neutral emote glyph, and for a page the official tips text (`config.tips`). The rest of the local-client art (the 3D board, the official HUD sprites, module type icons, the two enemy models above) is not downloaded: the client looks it up in `data/local-assets.json` only (most of the HUD sprites are on the mirror too, DESIGN §22.5); docs/DEPLOY.md §6 lists what falls back without it.
|
||||
- **Tokens:**
|
||||
- Without an avatar, use `chars[owner].avatar` with a 召唤物 badge, or `prof.battlecard.token`.
|
||||
- Without a Spine, draw the avatar sprite with a bob tween.
|
||||
|
||||
+6
-6
@@ -516,7 +516,7 @@ Audio: autochess BGM per phase, UI SFX (buy/sell/refresh/level/merge/ready/timer
|
||||
|
||||
## 13. Local-client art (optional, host-side)
|
||||
|
||||
`tools/local-extract/extract.py` (Python: UnityPy + lz4 + Pillow; decodes Arknights' custom **LZ4AK** bundle compression via `aklz4.py`) extracts art that no web source has from a locally installed client (CrossOver Windows build or PlayCover iOS build) into `public/assets/local/**` and writes `data/local-assets.json` (`{ groups: { '<subdir>': { name: { path, w, h, kind } } } }`). Everything here is **optional**: clients must render correctly when the file or any entry is missing (fall back to the web assets / procedural art). The emotes and the guide pages below are on the public mirror too (§22.5): fetch-assets downloads them (data/assets.json `ui['emoticon/<dir>/<picId>']`, `ui['guide/<key>']`) and the client shows the local copy first, then that one (`data.js artUrls`); docs/DEPLOY.md §6 lists what still needs the client.
|
||||
`tools/local-extract/extract.py` (Python: UnityPy + lz4 + Pillow; decodes Arknights' custom **LZ4AK** bundle compression via `aklz4.py`) extracts the art the web download does not include (some of it, most official HUD sprites among it, is on the public mirror too — §22.5) from a locally installed client (CrossOver Windows build or PlayCover iOS build) into `public/assets/local/**` and writes `data/local-assets.json` (`{ groups: { '<subdir>': { name: { path, w, h, kind } } } }`). Everything here is **optional**: clients must render correctly when the file or any entry is missing (fall back to the web assets / procedural art). The emotes and the guide pages below are on the public mirror too (§22.5): fetch-assets downloads them (data/assets.json `ui['emoticon/<dir>/<picId>']`, `ui['guide/<key>']`) and the client shows the local copy first, then that one (`data.js artUrls`); docs/DEPLOY.md §6 lists what still needs the client.
|
||||
- `map/autochess/TX_autochessi_*` — the real autochess board atlas (`_D` diffuse 2048² with floor tiles, gold-framed high-ground plates, REINFORCEMENTS bench pads, EQUIPMENTS pads, crates, gates; `_N/_M/_E` normal/mask/emission; `common_D` device icons; `BG` backdrop). `map/autochesssand/*` — the sand-theme variant.
|
||||
- `ui/{common,battle,outer}/*` — every sprite of the three official autochess UI bundles (tier chips I–VI, bond disc rings, frames, banners, HUD pieces, badges, backgrounds, mode art).
|
||||
- `emoticon/<dir>/<picId>.png` — the 36 official battle emotes, 6 themes (`shared/constants.js → EMOTE_THEMES / EMOTES`, `emoteArtPath`; data/emotes.json); also downloaded from the mirror (§22.5).
|
||||
@@ -1485,14 +1485,14 @@ TBD-22.4
|
||||
### 22.5 Emotes and guide pages without a local client; deployment docs (#42); the English title (#38) — `tools/assets/plan.mjs UI_EXTRAS / GUIDE_PAGES`, data/assets.json `ui['emoticon/<dir>/<picId>']` / `ui['guide/<key>']`, `data.js artUrls / nextArtUrl`, `ui/emotes.js emoteArtUrls / EmoteArt`, `ui/guide.js guidePages / GuideHost`, `tools/setup.mjs LOCAL_ART_FALLBACK / LOCAL_ART_COPY_HINT`, `tools/doctor.mjs`, README, docs/DEPLOY.md §6, `server/index.js` banner, package.json `name`
|
||||
|
||||
- **#42 seen**: "游玩时左下角的六页表情全部显示为默认图标" — a Linux server deployed from source (git clone, setup with the asset download, Node 22); copying `public/assets/local/` and `data/local-assets.json` from the release bundle fixed it. **Real**: both are extracted from a locally installed client (§13; setup extracts only when it finds one), and the emote art and the 玩法说明 pages came from there only, so a source deploy without the client drew the neutral glyph for all 36 emotes and the official tips text instead of the 19 pages. README, DEPLOY.md, setup and doctor said the local art did not matter ("不影响游戏", "其他功能不受影响") — wrong: the 3D board, part of the official HUD art and two enemy models fall back too.
|
||||
- **Source**: the mirror the pipeline already uses (ArknightsAssets2 `cn`, assets/dyn) has all 55 files — the six theme bundles' `ui/emoticon/theme/[uc]<themeId>/icon/<picId>.png` (the 36 battle sprites, keyed by display_meta_table picId) and `arts/guidebookpages/[pack]autochess/autochess_{home 1–9, shop 1–6, handbook 1–4}.png`. Checked 2026-10-03: every URL answers 200 on raw.githubusercontent.com and on the jsDelivr fallback; the same pictures at the same sizes as the local extraction (emotes 120×120 / ≈113×115, pages 1024² squashed — still shown at 16:9), pixel differences only from the platforms' texture compression.
|
||||
- **Now**: the asset plan downloads them like any other UI sprite (UI_EXTRAS, built from shared/constants.js EMOTE_CATALOG and GUIDE_PAGES — a test keeps GUIDE_PAGES equal to guide.js GUIDE_CHAPTERS), keyed by the data/local-assets.json group and name: `ui['emoticon/<dir>/<picId>']` → `/assets/ui/emoticon/<dir>/<picId>.png`, `ui['guide/<key>']` → `/assets/ui/guide/<key>.png` (55 files, 21.3 MiB; the download ≈ 270 MB, was ≈ 250 MB). The committed data/assets.json lists them (regenerated by a real fetch-assets run: only these 55 entries, `hash` and `stats` changed), so `npm run setup` — which the start scripts run on every start — on an install made before them finds 55 files missing and runs fetch-assets; §21.25's conventions hold: ledger, retries, the jsDelivr fallback, and a run where they fail keeps the committed manifest (shrink guard), so the next setup tries again. The client looks both manifests up by the same names (`data.js artUrls`): the local-client picture first, then the mirror copy; `EmoteArt` and the guide viewer move to the next URL when an image fails to load (`nextArtUrl`: a copied data/local-assets.json without its files falls through to the mirror copy), and with neither keep today's fallback (the glyph; the tips text). `localAsset` stays local-only.
|
||||
- **Docs now**: README, docs/DEPLOY.md (new §6 本地客户端素材, the 排错 rows), docs/PLAYING.md, docs/ASSETS.md and the setup / doctor messages say what still needs the client — the official 3D board (→ the 2D board with procedural tiles), part of the official HUD art (the emote button and panel frames, the pause plate, the equip-replace dialog, the loadout screen, the team status and miss tags, module type icons … → CSS look-alikes, icons or text) and 灼热 / 炽焰源石虫's models (→ the tinted web alias, §21.14) — and that a server without the client can copy `public/assets/local/` and `data/local-assets.json` from the release bundle of the **same version** (both are read per request: no restart). The Docker parts are unchanged (deferred by the owner).
|
||||
- **Source**: the mirror the pipeline already uses (ArknightsAssets2 `cn`, assets/dyn) has all 55 files — the six theme bundles' `ui/emoticon/theme/[uc]<themeId>/icon/<picId>.png` (the 36 battle sprites, keyed by display_meta_table picId) and `arts/guidebookpages/[pack]autochess/autochess_{home 1–9, shop 1–6, handbook 1–4}.png`. Checked 2026-10-03: every URL answers 200 on raw.githubusercontent.com and on the jsDelivr fallback; the same pictures as the local extraction, each at the size of its local copy (all 55 compared; the pages 1024² squashed — still shown at 16:9), pixel differences only from the platforms' texture compression.
|
||||
- **Now**: the asset plan downloads them like any other UI sprite (UI_EXTRAS, built from shared/constants.js EMOTE_CATALOG and GUIDE_PAGES — a test keeps GUIDE_PAGES equal to guide.js GUIDE_CHAPTERS), keyed by the data/local-assets.json group and name: `ui['emoticon/<dir>/<picId>']` → `/assets/ui/emoticon/<dir>/<picId>.png`, `ui['guide/<key>']` → `/assets/ui/guide/<key>.png` (55 files, 21.3 MiB; the download ≈ 270 MB, was ≈ 250 MB). The committed data/assets.json lists them (regenerated by a real fetch-assets run: only these 55 entries, `hash` and `stats` changed), so `npm run setup` — which the start scripts run on every start — on an install made before them finds 55 files missing and runs fetch-assets; §21.25's conventions hold: ledger, retries, the jsDelivr fallback, and a run where they fail keeps the committed manifest (shrink guard), so the next setup tries again. The client looks both manifests up by the same names (`data.js artUrls`): the local-client picture first, then the mirror copy; `EmoteArt` and the guide viewer move to the next URL when an image fails to load (`nextArtUrl`: a copied data/local-assets.json without its files falls through to the mirror copy); when none is left they keep 0.1.1's fallback — the glyph, and for a 玩法说明 page the official tips text (`guideStage`), also when data/assets.json lists the downloaded pages but the files are not on disk (a `git pull` and restart without setup, an older asset folder, a failed download the shrink guard kept); the chapter tabs, dots and keys still reach the other pages. `localAsset` stays local-only.
|
||||
- **Docs now**: README, docs/DEPLOY.md (new §6 本地客户端素材, the 排错 rows), docs/PLAYING.md, docs/ASSETS.md and the setup / doctor messages say what still needs the client — the official 3D board (→ the 2D board with procedural tiles), part of the official HUD art (the emote button and panel frames, the pause plate, the equip-replace dialog, the loadout screen, the team status and miss tags, module type icons … → CSS look-alikes, icons or text) and 灼热 / 炽焰源石虫's models (→ the tinted web alias, §21.14) — and README, DEPLOY §6 and doctor that a server without the client can copy `public/assets/local/` and `data/local-assets.json` from the release bundle of the **same version** (both are read per request: no restart); setup's row, which the launcher prints on every start, only points to DEPLOY §6. The Docker parts are unchanged (deferred by the owner).
|
||||
- **Not done here**: the mirror also has most sprites of the three autochess UI bundles that the local `ui/battle` / `ui/common` / `ui/outer` groups hold (by name 377 / 389, 137 / 160 and 659 / 659 under `ui/autochess/[uc]autochess{battle,common,outer}/**`; the emote panel frames, `matte_pause` and `bg_miss_enemy` checked at the local sizes), so the HUD row of DEPLOY §6 could shrink in a follow-up.
|
||||
- **#38, the English title** — **official**: EN client data, activity_table `basicInfo.act2autochess.name` = "Stronghold Protocol: Alliance" (CN 卫戍协议:盟约; ArknightsAssets/ArknightsGamedata `en/gamedata/excel/activity_table.json`, 2026-09-29 — Kengxxiao/ArknightsGameData_YoStar stops at EN client 31.5.80, 2025-11-13, before this season, with act1vautochess "Stronghold Protocol" only). **Now**: the README title and English summary, the server start-up banner and the package name (`stronghold-protocol-alliance`, package.json and the lockfile) say Alliance instead of "Covenant"; the Chinese title 卫戍协议:盟约 and the repository name stay. "Covenant" remains only in 新约能天使's official appellation ("Exusiai the New Covenant") and its buff key `angel2:covenant`.
|
||||
- **#38, the English title** — **official**: EN client data, activity_table `basicInfo.act2autochess.name` = "Stronghold Protocol: Alliance" (CN 卫戍协议:盟约; ArknightsAssets/ArknightsGamedata `en/gamedata/excel/activity_table.json`, 2026-09-29 — Kengxxiao/ArknightsGameData_YoStar stops at EN client 31.5.80, 2025-11-13, before this season, with act1vautochess "Stronghold Protocol" only). **Now**: the README title and English summary, the server start-up banner and the package name (`stronghold-protocol-alliance`, package.json and the lockfile) say Alliance instead of "Covenant"; the Chinese title 卫戍协议:盟约 and the repository name stay. "Covenant" remains only in 新约能天使's official appellation ("Exusiai the New Covenant") and its buff key `angel2:covenant`. Only the title is settled here: #38 itself (a full English UI) stays open.
|
||||
- **PR #27 follow-up**: tools/doctor.mjs's comment now says directly that tun0 / tap0 are matched first by VPN_IF (substring `tun\d` / `tap`) and classed as vpn — it spoke of no longer listing `^tun\d`, which master's VIRTUAL_IF never had; comment only.
|
||||
- [ASSUMED]: none.
|
||||
- Tests: `test/assets.test.js` (the 55 plan entries and URLs, a rebuilt manifest, the committed manifest lists them), `test/ui/localArt.test.js` (the lookup order, a server without the client, GUIDE_PAGES = GUIDE_CHAPTERS), `test/fetch-assets-shrink.test.js` (a failed mirror run keeps the manifest), `test/static-local-art.test.js` (the docs and messages), `test/version.test.js` (the English title), `test/doctor.test.js`.
|
||||
- Tests: `test/assets.test.js` (the 55 plan entries and URLs, a rebuilt manifest, the committed manifest lists them), `test/ui/localArt.test.js` (the lookup order, a server without the client, `guideStage`, GUIDE_PAGES = GUIDE_CHAPTERS), `test/fetch-assets-shrink.test.js` (a failed mirror run keeps the manifest), `test/static-local-art.test.js` (the docs and messages), `test/version.test.js` (the English title), `test/doctor.test.js`.
|
||||
|
||||
|
||||
### 22.6 钩索师 and 推击手 on 高台 (#32 item 4)
|
||||
|
||||
@@ -80,6 +80,10 @@ test('docs and messages say what falls back without the local art and how a serv
|
||||
for (const re of [/3D 棋盘/, /界面图标/, /源石虫/]) assert.match(LOCAL_ART_FALLBACK, re);
|
||||
assert.ok(!/表情|玩法说明/.test(LOCAL_ART_FALLBACK), 'the emotes and the 玩法说明 pages are downloaded, not local-only');
|
||||
assert.match(LOCAL_ART_COPY_HINT, /同一版本的整合包/);
|
||||
// setup's row is printed on every start (scripts/launch.mjs): it names the fallbacks and points to DEPLOY §6; doctor adds the hint
|
||||
const noClientRow = read('tools/setup.mjs').split('\n').find((l) => l.includes("'未检测到本机明日方舟客户端'"));
|
||||
assert.ok(noClientRow && noClientRow.includes('LOCAL_ART_FALLBACK') && noClientRow.includes('DEPLOY.md 第 6 节') && !noClientRow.includes('LOCAL_ART_COPY_HINT'), noClientRow);
|
||||
assert.match(read('tools/doctor.mjs'), /未提取:\$\{LOCAL_ART_FALLBACK\}(\$\{LOCAL_ART_COPY_HINT\})/);
|
||||
const deploy = read('docs/DEPLOY.md');
|
||||
const s6 = deploy.slice(deploy.indexOf('## 6. 本地客户端素材'));
|
||||
assert.ok(deploy.includes('## 6. 本地客户端素材') && s6.length > 200, 'DEPLOY §6');
|
||||
|
||||
@@ -248,7 +248,7 @@ describe('public/js/ui/emotes.js helpers', () => {
|
||||
} };
|
||||
const realFetch = globalThis.fetch;
|
||||
|
||||
test('art URLs come from the manifest only (keyed by picId); unknown / unlisted → null', async () => {
|
||||
test('art URLs come only from what the manifests list (here the local one, keyed by picId; data/assets.json absent); unknown / unlisted → null', async () => {
|
||||
globalThis.fetch = async (url) => (String(url).endsWith('/local-assets.json')
|
||||
? { ok: true, status: 200, json: async () => manifest } : { ok: false, status: 404, json: async () => ({}) });
|
||||
try {
|
||||
|
||||
@@ -41,7 +41,7 @@ test('the release version is what players see', () => {
|
||||
assert.match(server, /app: APP_VERSION/, '/healthz');
|
||||
});
|
||||
|
||||
test('the English title is the official one: Stronghold Protocol: Alliance (GitHub issues #38 / #42)', () => {
|
||||
test('the English title is the official one: Stronghold Protocol: Alliance (as in the reply to GitHub issue #38, which stays open)', () => {
|
||||
// EN client data, activity_table basicInfo.act2autochess.name = "Stronghold Protocol: Alliance" (CN 卫戍协议:盟约);
|
||||
// the project used to call it "Covenant". The Chinese title stays 卫戍协议:盟约; the repository keeps its name.
|
||||
const readme = read('README.md');
|
||||
|
||||
+3
-2
@@ -195,7 +195,8 @@ export function checkAssets() {
|
||||
* issue #42). Shown by setup and doctor.
|
||||
*/
|
||||
export const LOCAL_ART_FALLBACK = '3D 棋盘改用 2D,部分官方界面图标和灼热/炽焰源石虫模型用替代样式';
|
||||
/** Where a machine without the client gets the local art (docs/DEPLOY.md §6「本地客户端素材」). */
|
||||
/** Where a machine without the client gets the local art (docs/DEPLOY.md §6「本地客户端素材」); shown by doctor (setup's row,
|
||||
* printed on every start by scripts/launch.mjs, only points to that section). */
|
||||
export const LOCAL_ART_COPY_HINT = '没有客户端的服务器可以从同一版本的整合包复制 public/assets/local 和 data/local-assets.json';
|
||||
|
||||
/**
|
||||
@@ -432,7 +433,7 @@ async function main() {
|
||||
if (!client) {
|
||||
if (already && local.board3d && !local.tiles && !opts.check) cropBoardTiles(log);
|
||||
add(already ? 'ok' : 'skip', '本地客户端美术(可选)', already ? `已提取 ${local.count} 项`
|
||||
: `${opts.game ? `找不到 ${opts.game}` : '未检测到本机明日方舟客户端'}:${LOCAL_ART_FALLBACK}(${LOCAL_ART_COPY_HINT},见 docs/DEPLOY.md 第 6 节)`);
|
||||
: `${opts.game ? `找不到 ${opts.game}` : '未检测到本机明日方舟客户端'}:${LOCAL_ART_FALLBACK}(见 docs/DEPLOY.md 第 6 节)`);
|
||||
} else if (!client.autochess) {
|
||||
add(already ? 'ok' : 'warn', '本地客户端美术(可选)', `${client.kind} 客户端缺少卫戍协议资源(请在游戏内下载全部资源):${client.path}`);
|
||||
} else if (already && opts.local !== 'force') {
|
||||
|
||||
Reference in new issue
Block a user