feedback5: merge R5 — client split: ui/gameLogic/*, render/fx/*, render/app/* (prelude), screens/game/* (same exports)

# Conflicts:
#	.git-blame-ignore-revs
#	public/js/ui/gameLogic.js
This commit is contained in:
sganggs committed 2026-10-05 18:38:43 +08:00
commit 7d20695adf
51 files changed
+4655 -4335

No files matched your search

+2 -1
View File
@@ -293,7 +293,8 @@ test('user playtest #4 (DESIGN §18): picking by tile, timers, 机变 two taps,
// #1 the tile under the pointer; the dragged model held under the pointer (no touch lift, probe or body shapes)
assert.equal(ENEMY_REACH, 0.6);
const app = readFileSync(join(ROOT, 'public/js/render/app.js'), 'utf8');
assert.match(app, /export const DRAG_HOLD_TILES = 0\.45;/);
const tune = readFileSync(join(ROOT, 'public/js/render/app/tune.js'), 'utf8');
assert.match(tune, /export const DRAG_HOLD_TILES = 0\.45;/);
assert.ok(!/TOUCH_LIFT_TILES|drawnAt|pickShape|pieceDragOver/.test(app), 'no touch lift, pixel probe or body shapes (user playtest #4 item 1)');
assert.match(DESIGN, /`DRAG_HOLD_TILES` = 0\.45 tile/);
assert.match(DESIGN, /`ENEMY_REACH` 0\.6 tile/);
+2 -1
View File
@@ -234,7 +234,8 @@ test('a hidden-tab backlog still beyond HELD_MAX after compaction: the first fra
test('screens/game.js buffers the form fx with the state-bearing events it replays when a field is entered late', () => {
const src = readFileSync(path.join(ROOT, 'public/js/screens/game.js'), 'utf8');
assert.match(src, /const keepEarly = \(e\) => Array\.isArray\(e\) && \(STATE_EV\.has\(e\[0\]\) \|\| fxForm\(e\) !== undefined\);/);
const early = readFileSync(path.join(ROOT, 'public/js/screens/game/early.js'), 'utf8');
assert.match(early, /const keepEarly = \(e\) => Array\.isArray\(e\) && \(STATE_EV\.has\(e\[0\]\) \|\| fxForm\(e\) !== undefined\);/);
assert.match(src, /for \(const e of msg\.ev\) if \(keepEarly\(e\)\) buf\.push\(e\);/);
// a new m.field for the field on screen buffers its frames until the enter effect re-enters it (enterBattle resets)
assert.match(src, /if \(msg\.fieldId === lastFieldRef\.current\) reentryRef\.current = msg\.fieldId;/);
+3 -3
View File
@@ -1,9 +1,9 @@
// 点击 / 观战队友单位时详情卡显示装备(游玩记录 #2:「观战队友时看不到干员的装备」)。DESIGN §16
// 承诺 "a teammate's unit shows its owner's loadout in the detail card":服务器把 an ally operator 的
// 装备 id 放进战斗快照与侦察 meta 的 UnitInfo.items(server/sim/snapshot.js、Match.prepFieldMeta),
// detailPanel 的 unit 分支也从 `u.items` 取 `unitItems` —— 但 renderInfo(public/js/render/app.js)
// detailPanel 的 unit 分支也从 `u.items` 取 `unitItems` —— 但 renderInfo(public/js/render/app/info.js)
// 构建 info 白名单时把 items 丢了,队友单位点开的卡永远没有 装备 区,变形同构体的「同构」pairing
// chips 对队友单位同样失效。renderInfo 在 app.js 里(模块顶层有 canvas 副作用,node 无法 import),
// chips 对队友单位同样失效。renderInfo 在 app/info.js 里(app.js 模块顶层有 canvas 副作用,node 无法 import 整份视图),
// 按docs-consistency / feedback1d 的惯例对源码断言;消费端行为已由 morph-bonds.test.js 锁住,
// 这里再走一遍 unit → resolveDetail → ChessDetail 的完整用户可见结果。
import { test } from 'node:test';
@@ -22,7 +22,7 @@ const HAMMER = 'chess_item_1_01_e_a'; // 维式重锤 → 维多利亚
// ---- renderInfo: the snapshot UnitInfo reaches the client info object ---------------------------------------------
test('renderInfo passes UnitInfo.items through (the teammate-unit equipment into the detail card)', () => {
const app = readFileSync(path.join(ROOT, 'public/js/render/app.js'), 'utf8');
const app = readFileSync(path.join(ROOT, 'public/js/render/app/info.js'), 'utf8');
const start = app.indexOf('export function renderInfo(');
assert.ok(start > 0, 'renderInfo exists');
const body = app.slice(start, app.indexOf('\n}', start));
+1 -1
View File
@@ -171,6 +171,6 @@ describe('shop bar: the merge tag and the armed card', () => {
assert.match(src, /onArm=\$\{setArmedCard\}/, 'ShopBar reports the armed card');
assert.match(src, /mergeTarget\(priv, armedCard\.id, gd\.chess\)/, 'the target comes from gameLogic.mergeTarget');
assert.match(src, /view\.highlightTiles\(mergeAt \? \[\[mergeAt\.row, mergeAt\.col\]\] : \[\], MERGE_HL\)/, 'its own highlight group (cleared with [])');
assert.match(src, /const MERGE_HL = Object\.freeze\(\{ group: 'mergeTile'/);
assert.match(read('public/js/screens/game/marks.js'), /const MERGE_HL = Object\.freeze\(\{ group: 'mergeTile'/);
});
});