mirror of
https://github.com/Shu-Ying/noname-shuying.git
synced 2026-10-24 16:50:01 +08:00
Merge origin/main: preserve relic system and diagnostics updates
This commit is contained in:
@@ -6,6 +6,7 @@ import { recordNormalBattleVictory } from "../progression/encounter-progress.js"
|
||||
import { stripBattleProgress } from "../progression/map-checkpoint.js";
|
||||
import { grantGold } from "../relics/progression.js";
|
||||
import { heldRelics } from "../relics/definitions.js";
|
||||
import { getDiagnostics } from "../../diagnostics/index.js";
|
||||
import { prepareRewardPackage, applyRewardPackage }
|
||||
from "../progression/reward-package.js";
|
||||
|
||||
@@ -16,6 +17,11 @@ export function createBattleSettlement({
|
||||
enterNextAct, createRun, now = Date.now, logRewardPackage = () => {}, resolveRelicChoices = async () => {},
|
||||
}) {
|
||||
let item = null, committed = null, commitPromise = null, choicePromise = null, choiceSignature = null;
|
||||
const diagnostics = getDiagnostics().scope("mengsan.settlement", () => ({
|
||||
settlementId: item?.id, runId: item?.base.runId,
|
||||
nodeId: item?.nodeId, pendingState: item?.state,
|
||||
route: item?.route, commitReceipt: !!committed,
|
||||
}));
|
||||
const readRun = () => store.read()[config.saveKey];
|
||||
function current(storage, runId) {
|
||||
const run = storage[config.saveKey];
|
||||
@@ -29,6 +35,11 @@ export function createBattleSettlement({
|
||||
function validateCheckpoint(run, snapshot, nodeId) {
|
||||
if (run.actIndex !== snapshot.actIndex || run.revision !== snapshot.revision ||
|
||||
run.map?.nodes.find(node => node.id === nodeId)?.completed !== false) {
|
||||
diagnostics.warn("checkpoint.mismatch", {
|
||||
expectedRevision: snapshot.revision, actualRevision: run.revision,
|
||||
expectedAct: snapshot.actIndex, actualAct: run.actIndex,
|
||||
nodeId, completed: run.map?.nodes.find(node => node.id === nodeId)?.completed,
|
||||
});
|
||||
throw new Error("Stale node or revision");
|
||||
}
|
||||
}
|
||||
@@ -78,6 +89,10 @@ export function createBattleSettlement({
|
||||
getRandomRewardChoices) : null;
|
||||
item = {id, state:"awaitingChoice", nodeId:node.id, base, choices:copy(choices), fixedRewards:copy(fixedRewards), victoryDialogue:copy(encounter.victoryDialogue || []), boss:!!encounter.boss, elite, outcome, relicRecovery, bondGrowth};
|
||||
item.rewardPackage = copy(rewardPackage);
|
||||
diagnostics.info("prepared", {
|
||||
outcome, choices: choices.map(choice => choice.id), fixedRewards,
|
||||
expectedRevision: snapshot.revision, actualRevision: run.revision,
|
||||
});
|
||||
if (outcome === "victory" && !rewardPackage) {
|
||||
item.rewardMode = "one-or-skip";
|
||||
}
|
||||
@@ -152,6 +167,7 @@ export function createBattleSettlement({
|
||||
// 在内存锁定最终结果(包括随机牌实例),只在 commit 写入地图进度。
|
||||
item.state = "chosen"; item.choiceId = copy(choiceId); item.result = stripBattleProgress(result);
|
||||
item.route = route; item.completedAt = now();
|
||||
diagnostics.info("choice.applied", { choiceId, route });
|
||||
if (item.rewardPackage && item.outcome === "victory") {
|
||||
logRewardPackage(item.rewardPackage, choiceId);
|
||||
}
|
||||
@@ -160,8 +176,11 @@ export function createBattleSettlement({
|
||||
async commit(runId, id) {
|
||||
const item = pending(runId, id);
|
||||
if (item.state !== "chosen") throw new Error("Player choice required before saving");
|
||||
if (committed) return {...copy(committed), duplicate:true};
|
||||
if (commitPromise) return commitPromise;
|
||||
if (committed) {
|
||||
diagnostics.info("commit.duplicate");
|
||||
return {...copy(committed), duplicate:true};
|
||||
}
|
||||
if (commitPromise) { diagnostics.info("commit.inflight"); return commitPromise; }
|
||||
commitPromise = store.update(storage => {
|
||||
const saved = storage[config.saveKey];
|
||||
const prior = storage[config.profileKey]?.completedRuns?.find(r => r.runId === runId && r.settlementId === id);
|
||||
@@ -191,8 +210,9 @@ export function createBattleSettlement({
|
||||
else delete storage[config.saveKey]; // Same transaction as profile; never a second clear write.
|
||||
}
|
||||
return {route:item.route, run:item.route === "new" ? copy(item.nextRun) : result, duplicate:false};
|
||||
}).then(result => {
|
||||
}, { runId, settlementId: id, nodeId: item.nodeId }).then(result => {
|
||||
committed = copy(result);
|
||||
diagnostics.info("commit.receipt", { duplicate: result.duplicate, route: result.route });
|
||||
return copy(committed);
|
||||
}).finally(() => { commitPromise = null; });
|
||||
return commitPromise;
|
||||
|
||||
Reference in New Issue
Block a user