feat # 新增日志功能

This commit is contained in:
2026-10-08 14:40:58 +08:00
parent 3a3d547ccd
commit cba7b5fbcc
19 changed files with 978 additions and 48 deletions
+39 -7
View File
@@ -94,6 +94,7 @@ import { mountGMManager } from "./ui/gm-manager.js";
import { createPlayerTeardown } from "./battle/skill-teardown.js";
import { createBattleResources } from "./battle/battle-resources.js";
import { createModeStorage } from "./progression/mode-storage.js";
import { getDiagnostics } from "../diagnostics/index.js";
import { createBattleSession } from "./battle/battle-session.js";
import { observeFreshEvent } from "./battle/engine-session.js";
import { runPhaseLoop, stopBattleTurn } from "./battle/battle-loop.js";
@@ -141,7 +142,26 @@ const clearRun = modeStorage.clearRun;
const showMap = run => renderMap(run, { saveRun });
let battleSequence = 0;
let activeBattle = null;
const reportFlowError = error => { console.error("梦三流程暂停,未自动清档:", error); };
const diagnosticService = getDiagnostics();
const diagnostics = diagnosticService.scope("mengsan.mode");
diagnosticService.registerContext("mengsan", () => {
const run = _status.mengsanRun_shuying;
const manager = _status.eventManager;
return {
runId: run?.runId, revision: run?.revision, actIndex: run?.actIndex,
character: run?.player?.character, hp: run?.player?.hp,
sessionId: activeBattle?.session.id,
flowState: activeBattle?.flow.state, pendingTasks: activeBattle?.session.pendingCount,
save: modeStorage.lastWrite,
engine: { paused: _status.paused, paused2: _status.paused2,
tempEvent: manager?.tempEvent?.name,
eventStack: manager?.eventStack?.slice(-8).map(event => ({ name: event?.name })) },
};
});
const reportFlowError = error => {
diagnostics.error("journey.failed", error);
console.error("梦三流程暂停,未自动清档:", error);
};
const chooseRun = async savedRun => {
const available = savedRun?.status === "running";
@@ -718,8 +738,9 @@ const registerPlayers = (session, players) => {
});
}
};
const makeFlow = (releaseSkills = async () => {}) => createBattleFlow({
const makeFlow = (releaseSkills = async () => {}, releaseBattle = () => {}) => createBattleFlow({
releaseSkills,
releaseBattle,
presentVictory: pending => {
if (pending.bondGrowth) {
const growth = pending.bondGrowth;
@@ -764,7 +785,10 @@ const requestBattleFinish = outcome => {
const current = activeBattle;
if (!current) return false;
// Complete the original card and all queued replays before snapshotting a victory.
if(outcome==="victory" && current.sharedPendingUses?.size){current.sharedDeferredVictory=true;return false;}
if(outcome==="victory" && current.sharedPendingUses?.size){
diagnostics.info("victory.deferred", { pendingUses: current.sharedPendingUses.size });
current.sharedDeferredVictory=true;return false;
}
for (const player of game.dead) {
recordBondDeath(player, _status.mengsanRun_shuying,
message => game.log(message));
@@ -787,10 +811,12 @@ const awaitSettlement = async (flow, initial = flow.wait()) => {
try { return await operation; }
catch (error) {
if (flow.state !== "retryable") throw error;
diagnostics.error("settlement.prompt", error, { flowState: flow.state });
const action = await chooseButtons("结算未完成", [
{id:"retry",name:"重试保存与结算"},
{id:"exit",name:"保留已保存进度并返回模式选择"},
], "已提交的奖励不会重发。技能释放失败时请返回模式选择,避免重复调用释放回调。");
diagnostics.info("settlement.prompt.action", { action });
if (action === "exit") { await openModeSelection(); throw error; }
operation = flow.retry();
}
@@ -801,14 +827,20 @@ const playBattle = async (run, node, encounter) => {
if (lib.onfree) await new Promise(resolve => lib.onfree.push(resolve));
await quiesceEngine(_status);
const session = createBattleSession(`${run.runId}:${++battleSequence}`);
const resources = createBattleResources(session, {game,ui,_status});
let current;
const flow = makeFlow(() => current.releaseSkills?.());
let resources = createBattleResources(session, {game,ui,_status});
let current, root;
const flow = makeFlow(() => current.releaseSkills?.(), () => {
if (activeBattle === current) activeBattle = null;
for (const key of Object.keys(current)) {
if (key !== "session" && key !== "flow") delete current[key];
}
root = null; resources = null;
});
let finished;
const signal = new Promise(resolve => { finished = resolve; });
current = {session, flow, finished, resources, players: new Set(), monsterPiles: new Map(), energyUI: new Map(), intentUI: new Map()};
activeBattle = current;
const root = new lib.element.GameEvent("mengsanBattle", false, _status.eventManager);
root = new lib.element.GameEvent("mengsanBattle", false, _status.eventManager);
current.root = root;
const previousRoot = _status.eventManager.rootEvent;
session.ownResource({}, () => {