v0.1.28: 稳石——第三轮全量审计歼灭(2008 全绿 + 指纹补盲)

【P0 批(7 项,实证驱动)】
- P0-1 世界词库池无回滚(真实漂移实证)→ WorldGenPools 来源追踪 + removePool 精确回滚
  + MOD uninstall 自动摘除(池/灾因/配方/数值四类全局注册——P2-3 一并根治)
- P0-2 新贵 def 不落档(僵尸实证:power 恒 120 零演化)→ 生成即写 worldGen.npcs
  + normalize 占位 def 双保险 + 新贵 id 掺 seed 指纹(P1-10 防跨档碰撞)
- P0-3 校验死代码化 → installModText 装前 modPreflight(冲突拒+警告 toast)
- P0-4 MOD 读档静默消失 → state.pluginsMissing 收集提示(与 MOD_GUIDE 承诺对齐)
- P0-5 救济按钮乌龙(哈希序首个+直改 state)→ World.reliefCalamity(景气最低+双检)
- P0-6 天下快讯永久冻结(memo 依赖恒 120 length)→ 去 memo 每次 reverse
- P0-7 MOD 导出单行道 → modParse 识别 {app:'cotymod',bundle} 逐包递归(roundtrip 闭环)

【P1 批】
- P1-8 指纹补盲(worldGen/sagaAnnals/distress/declineYears 入 hash——0.1.27 成果真实锁定)+ 双基线重算
- P1-9 重放同步 worldGen.npcs(自捕获);P1-11 worldNum 字段接线(install/uninstall 复位)
- P1-13 落盘兜底(beforeunload/visibilitychange 突发 save,堵 12-tick 节流窗口)
- P1-14 onGameOver 停 timer + IPC mods 路径白名单(扩展名正则防穿越)
- P1-15 DataPack 摘除 npcs(覆写死路删除,与五口宣言对齐);P1-4 techniques 双源统一(techniquePrice 读包)

【P2 扫尾】tauntCD 清理/sagaAnnals 上限 40/worldGenMods 落空写入/validateMod 深度校验随 P0-3 提交

【测试】69 套件 2008 全绿(audit-0.1.28 八例:池回滚/僵尸/preflight/bundle/freeze/指纹敏感/worldNum/救济);
金钟罩 0.1.28 基线重算(指纹补盲+受控时序变更);build 通过
This commit is contained in:
2026-08-23 18:07:31 +08:00
parent d8d34fcb74
commit da4fb9f635
24 changed files with 304 additions and 43 deletions
@@ -20,6 +20,8 @@ export interface ModPackData {
}
/** 灾因扩展(0.1.26:进入世界灾签循环) */
calamities?: Array<{ name: string; family?: Record<string, number>; effect?: Record<string, number> }>
/** 世界数值白名单覆写(0.1.27 声明口径,0.1.28 接线;卸载复位) */
worldNum?: Record<string, number>
/** 丹方/铸器配方 */
pills?: Array<{ output: string; name: string; danfangLevel: number; stones: number; lingcao: number; beastcore: number; desc: string }>
forges?: Array<{ output: string; name: string; stones: number; lingkuang: number; beastcore: number; desc: string }>
@@ -51,6 +53,16 @@ export function modParse(text: string): ModParseResult {
} catch {
return { ok: false, error: 'MOD 文件不是合法 JSON。' }
}
// P0-7 bundle 分支:游戏内导出的合并包({app:'cotymod',bundle:[...]})→ 逐包递归(首包解析失败即报)
const asRec = raw as { app?: string; bundle?: unknown[] }
if (asRec?.app === 'cotymod' && Array.isArray(asRec.bundle)) {
if (asRec.bundle.length === 0) return { ok: false, error: 'bundle 为空。' }
for (const b of asRec.bundle) {
const r = modParse(JSON.stringify(b))
if (!r.ok) return { ok: false, error: `bundle 内包非法:${r.error}` }
}
return modParse(JSON.stringify(asRec.bundle[0]))
}
if (!raw || typeof raw !== 'object') return { ok: false, error: 'MOD 内容为空。' }
const p = raw as Record<string, unknown>
if (typeof p.id !== 'string' || !ID_RE.test(p.id)) return { ok: false, error: '缺失/非法的 MOD id。' }