引入游玩呈现壳与旁观维护槽,完善结算合并、十分制自评与技能产物 UI。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-12 02:03:29 +08:00
co-authored by Cursor
parent 94f67fa744
commit 120d67ee82
46 changed files with 2513 additions and 236 deletions
+38
View File
@@ -2,6 +2,10 @@
* 主世界层 → 叙事转述的裁决包(settlement / direction packet)。
* 存黑板 tag:运行.本轮.裁决
*/
import {
createTableFromValues,
type TableDoc,
} from "../blackboard/table-cells.js";
import { extractJsonObjectText } from "./worker-set-parse.js";
export const SETTLEMENT_SCHEMA = "settlement.v1" as const;
@@ -229,3 +233,37 @@ export function isSettlementLikeObject(doc: unknown): boolean {
for (const k of keys) if (k in row) hits += 1;
return hits >= 2;
}
/**
* 将 variable_changes 编成 TableDoc patch,供合并进「变量.当前」。
* - 有 `to` → 写绝对值
* - 仅有 `delta` → 在现有数值上加减(无现值则从 0)
*/
export function settlementChangesToTablePatch(
changes: SettlementVariableChange[],
current: TableDoc | null,
): TableDoc | null {
if (!changes.length) return null;
const byKey = new Map((current?.rows ?? []).map((r) => [r.key, r]));
const values: Record<string, unknown> = {};
const meta: Record<string, { note?: string }> = {};
for (const c of changes) {
const key = c.key.trim();
if (!key) continue;
const existing = byKey.get(key);
if (c.to !== undefined) {
values[key] = c.to;
} else if (c.delta != null) {
const cur = existing?.value;
const n = typeof cur === "number" ? cur : Number(cur);
values[key] = Number.isFinite(n) ? (n as number) + c.delta : c.delta;
} else {
continue;
}
if (c.note) meta[key] = { note: c.note };
}
if (!Object.keys(values).length) return null;
return createTableFromValues(values, "system", meta);
}