feedback7 G-SMALL: settings can copy local diagnostics for a bug report (PR #321 by @Cloudnyco)
Applied 设置 → 问题反馈. The report stays in the browser: the in-memory error log, device info, and the battle on screen only while 「附上本场战斗」 is on. Nothing is uploaded. Redaction no longer treats a long name as a bare substring. Prose replaces each secret only as a whole token, so a name does not cut a longer word or a chess id. The attached JSON replaces a string only when it equals the secret, so chess_char_1013_chen2 and a note like "charge the char" stay, while an exact "char" value becomes the placeholder. The token boundary is a consumed prefix plus a lookahead, because a lookbehind is a SyntaxError in Safari before 16.4. PLAYING section 12 stays; the other section-12 proposal is not in this batch. Tests: node --test test/diag.test.js — 10 pass. node --test test/client-static.test.js — 315 pass. node --test test/match/runner-pending.test.js test/match/watch-bonds.test.js test/ui/playtest6-unite.test.js test/ui/spectate-effects.test.js test/ui/feedback5-hotkeys.test.js test/i18n-server.test.js test/ui/bosshit-ticker.test.js test/ui/playtest3.test.js test/docs-consistency.test.js test/docs-paths.test.js test/version.test.js test/package.test.js — 138 pass. npm run -s lint — 0 errors. npm run -s typecheck and npm run -s check:imports passed. node tools/i18n.mjs check --all --strict — 1041/1041 in en, ja, ko and zh-TW, 0 errors.
This commit is contained in:
1 parent
073507eca3
commit
3f8844129b
12 files changed
+599
-7
No files matched your search
@@ -72,6 +72,7 @@ import { net as appNet } from '../net.js';
|
||||
import { store as appStore } from '../store.js';
|
||||
import { unitStatsEntry, fxForm } from '../../../shared/protocol.js';
|
||||
import { spectateEffects } from './observe.js';
|
||||
import { recordError, setBattleSource } from '../diag.js';
|
||||
|
||||
const TICK = 1 / 30;
|
||||
/** Fast-forward budget per frame (ticks) when far behind. */
|
||||
@@ -156,9 +157,12 @@ export async function loadBrowserSim({ base = '/sim/', dataBase = '/data/', fetc
|
||||
return { spec, ds: new simdata.DataSource(raw, null) };
|
||||
}
|
||||
|
||||
/** Battle logger: content errors are isolated by the sim; report them as warnings (the server logs its own). */
|
||||
/**
|
||||
* Battle logger: content errors are isolated by the sim; report them as warnings (the server logs its own) and keep
|
||||
* them for the diagnostics a player copies (diag.js).
|
||||
*/
|
||||
const SIM_LOGGER = Object.freeze({
|
||||
error: (...a) => console.warn('[sim]', ...a),
|
||||
error: (...a) => { console.warn('[sim]', ...a); recordError('sim', a.length === 1 ? a[0] : a.map(String).join(' ')); },
|
||||
warn: (...a) => console.warn('[sim]', ...a),
|
||||
info() {},
|
||||
debug() {},
|
||||
@@ -351,6 +355,7 @@ export function createBattleRunner(deps) {
|
||||
} catch (err) {
|
||||
stats.errors++;
|
||||
console.warn('[runner] battle step failed', err);
|
||||
recordError('runner', err, 'battle step failed');
|
||||
try { b.forceEnd('timeout'); } catch { /* ignore */ }
|
||||
}
|
||||
const dt = now() - t;
|
||||
@@ -393,7 +398,7 @@ export function createBattleRunner(deps) {
|
||||
const list = catchingUp ? s.ev.filter(keepsState) : s.ev;
|
||||
if (list.length) emit('ev', { t: 'b.ev', fieldId: e.fieldId, gt: s.gt, ev: list });
|
||||
}
|
||||
try { emit('snap', frameOf(e)); } catch (err) { console.warn('[runner] snapshot failed', err); }
|
||||
try { emit('snap', frameOf(e)); } catch (err) { console.warn('[runner] snapshot failed', err); recordError('runner', err, 'snapshot failed'); }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -457,7 +462,7 @@ export function createBattleRunner(deps) {
|
||||
result = e.sim.spec.compactResult(e.battle.result());
|
||||
// an oversized frame would close the socket at the very end of the battle (64 KB inbound limit)
|
||||
if (typeof e.sim.spec.fitResult === 'function') result = e.sim.spec.fitResult(result, { bossLike: bossLike(e), battleId: e.battleId });
|
||||
} catch (err) { console.warn('[runner] result failed', err); }
|
||||
} catch (err) { console.warn('[runner] result failed', err); recordError('runner', err, 'result failed'); }
|
||||
if (result) {
|
||||
e.result = result;
|
||||
// the view answers with the settlement voice of this battle (screens/game.js → audio.voice result*): the
|
||||
@@ -491,6 +496,7 @@ export function createBattleRunner(deps) {
|
||||
} else {
|
||||
e.delivery = 'delivered';
|
||||
console.warn('[runner] b.result refused', code);
|
||||
recordError('runner', code, 'b.result refused');
|
||||
}
|
||||
return null;
|
||||
});
|
||||
@@ -670,6 +676,7 @@ export function createBattleRunner(deps) {
|
||||
let sim;
|
||||
try { sim = await ensureSim(); } catch (err) {
|
||||
console.warn('[runner] simulation unavailable', err);
|
||||
recordError('runner', err, 'simulation unavailable');
|
||||
return;
|
||||
}
|
||||
if (!wanted()) return;
|
||||
@@ -678,6 +685,7 @@ export function createBattleRunner(deps) {
|
||||
battle = sim.spec.createBattleFromSpec(e.spec, sim.ds, { logger });
|
||||
} catch (err) {
|
||||
console.warn('[runner] battle construction failed', err);
|
||||
recordError('runner', err, 'battle construction failed');
|
||||
return;
|
||||
}
|
||||
stats.battles++;
|
||||
@@ -806,6 +814,16 @@ export function createBattleRunner(deps) {
|
||||
return () => listeners.get(type)?.delete(fn);
|
||||
},
|
||||
state,
|
||||
/**
|
||||
* The battle on screen as a report attaches it (diag.js): its b.start fields and its game time; null without one.
|
||||
* @returns {{ battleId: string, fieldId: string, kind: string, spec: object, time: number|null }|null}
|
||||
*/
|
||||
currentBattle() {
|
||||
const e = cur;
|
||||
if (!e || !e.spec) return null;
|
||||
const time = e.battle && Number.isFinite(e.battle.time) ? e.battle.time : null;
|
||||
return { battleId: e.battleId, fieldId: e.fieldId, kind: e.kind, spec: e.spec, time };
|
||||
},
|
||||
stats() {
|
||||
return { ...stats, avgTickMs: stats.ticks ? stats.stepMs / stats.ticks : 0, entries: entries.size, loadingSim: !!simP };
|
||||
},
|
||||
@@ -869,3 +887,4 @@ export const battleRunner = typeof window !== 'undefined' && typeof document !==
|
||||
? createBattleRunner({ net: appNet, store: appStore })
|
||||
: null;
|
||||
if (battleRunner) globalThis.__SP_RUNNER__ = battleRunner; // dev / E2E introspection
|
||||
if (battleRunner) setBattleSource(() => battleRunner.currentBattle());
|
||||
Reference in new issue
Block a user