v0.1.35b: 兼容层铲除——迁移链/版本戳/死表死代码/normalize 兼容批/死字段
【A+I】migrate.ts 迁移链(CURRENT_SCHEMA/MIGRATIONS/migrateIfNeeded/MigrationError)整链铲除→validateLoadedState 结构校验(seed/family/members 断言);信封统一 payload 单格式(去双格式兜底);APP_ID 保留 【F】schemaVersion 字段全删(domain/creation/save 8 处);SaveMeta.version 记游戏版本字符串 【C】chronicle 死表+saveChronicle 死方法(首行 return+unreachable legacy 僵尸)全删 【D/E】GameEngine __state globalThis 泄漏口+seed 三元(恒不可达)删除;engineFromSnapshot/noAutoCreate 保留(测试便利——非兼容机器) 【B/H】normalizeGameState 兼容批删:老档字段补(28行)/worldGen 重放(18行)/P0-2 占位 def(9行)/worldSim 字段批删;保留 npcs 重注册/headId 修复/d distress 防护;initSim 补 0.1.34 四键(唯一初始源) 【G】domain 收紧 5 兼容 optional(techniqueRank/Progress/tribBoost/worldGen 必填)+pcgen 必写 【测试】删 9 个兼容验证体(audit 0.1.0-era/全残缺矩阵/空 worldSim 兜底);5989 全绿——金钟罩零漂(新档结构全字段,删除不涉世界数值)
This commit is contained in:
@@ -78,90 +78,14 @@ export function normalizeGameState(state: GameState): GameState {
|
||||
registerNpcDef(n as never)
|
||||
}
|
||||
}
|
||||
// P0-2 双保险:npcFamilies 中缺 def 的 id → 占位 def(防极端旧档僵尸)
|
||||
for (const id of Object.keys(state.npcFamilies ?? {})) {
|
||||
if (!npcById(id)) {
|
||||
const n = state.npcFamilies[id]
|
||||
registerNpcDef({
|
||||
id, name: n.name, region: n.region, style: '遗族', desc: '世族遗脉,家道中落而名犹在册。',
|
||||
leaderRealm: 'foundation', initialPower: n.power, powerGrowth: [2, 6], sells: [], buys: ['lingcao']
|
||||
})
|
||||
}
|
||||
}
|
||||
if (!state.worldGen && state.seed) {
|
||||
const wg = generateWorld(state.seed)
|
||||
state.worldGen = {
|
||||
relations: wg.relations,
|
||||
eras: wg.eras,
|
||||
marketOffset: wg.marketOffset,
|
||||
regionFlavor: wg.regionFlavor,
|
||||
alliances: wg.alliances,
|
||||
feuds: wg.feuds,
|
||||
npcCount: wg.npcs.length,
|
||||
// P1-9 重放同步 npcs 摘要(与 creation 一致——该档自此自捕获,不再每次重放)
|
||||
npcs: wg.npcs.map((n) => ({
|
||||
id: n.id, name: n.name, region: n.region, style: n.style,
|
||||
desc: n.desc, leaderRealm: n.leaderRealm, initialPower: n.initialPower,
|
||||
powerGrowth: n.powerGrowth, sells: n.sells, buys: n.buys
|
||||
}))
|
||||
}
|
||||
}
|
||||
// 老版本存档(<0.1.1)缺少新增字段,加载时补齐,避免运行期 undefined 崩溃
|
||||
if (!state.finance) state.finance = { accum: 0 }
|
||||
if (!state.yearStats) state.yearStats = { births: 0, deaths: 0 }
|
||||
if (!state.yearlyReports) state.yearlyReports = []
|
||||
if (!state.stats) {
|
||||
state.stats = {
|
||||
repPeak: state.family?.reputation ?? 0,
|
||||
popPeak: Object.values(state.members).filter((c) => c.alive).length,
|
||||
maxRealmIdx: peakRealmIndex(state.members ?? {}),
|
||||
techniqueGrand: grandTechniqueCount(state.members ?? {}),
|
||||
tourneyHistory: [],
|
||||
feishengCount: 0
|
||||
}
|
||||
}
|
||||
if (typeof state.totalTicks !== 'number') state.totalTicks = 0
|
||||
if (typeof state.seq !== 'number') state.seq = 10
|
||||
if (!state.battles) state.battles = []
|
||||
if (!state.eventQueue) state.eventQueue = []
|
||||
if (!state.completedEvents) state.completedEvents = []
|
||||
if (!state.missions) state.missions = []
|
||||
if (!state.flags) state.flags = {}
|
||||
if (!state.npcFamilies) state.npcFamilies = {}
|
||||
if (!state.family.flag) state.family.flag = {}
|
||||
if (!state.family.inventory) state.family.inventory = {}
|
||||
if (!state.family.buildings) state.family.buildings = {}
|
||||
if (!state.family.techniques) state.family.techniques = []
|
||||
if (!state.family.missionIds) state.family.missionIds = []
|
||||
if (!state.stats.tourneyHistory) state.stats.tourneyHistory = []
|
||||
if (state.stats.tourneyBest === undefined) state.stats.tourneyBest = undefined
|
||||
if (state.worldSim) {
|
||||
state.worldSim.marketPool = state.worldSim.marketPool ?? {}
|
||||
state.worldSim.npcDyn = state.worldSim.npcDyn ?? {}
|
||||
state.worldSim.secretQi = state.worldSim.secretQi ?? {}
|
||||
state.worldSim.newsFeed = state.worldSim.newsFeed ?? []
|
||||
if (typeof state.worldSim.tide !== 'number') state.worldSim.tide = 0.5
|
||||
if (typeof state.worldSim.warFatigue !== 'number') state.worldSim.warFatigue = 0
|
||||
if (!state.worldSim.shortage) state.worldSim.shortage = {}
|
||||
if (!state.worldSim.shortageWarned) state.worldSim.shortageWarned = {}
|
||||
if (!state.worldSim.wonders) state.worldSim.wonders = {}
|
||||
if (typeof state.worldSim.tideTicks !== 'number') state.worldSim.tideTicks = 0
|
||||
if (typeof state.worldSim.npcSuccessions !== 'number') state.worldSim.npcSuccessions = 0
|
||||
if (typeof state.worldSim.calamityLeft !== 'number') state.worldSim.calamityLeft = 0
|
||||
// 0.1.35 收敛:初始字段职责归 initSim(WorldSim.ts),此处仅防脏(异常落盘/测试注入)
|
||||
// 防护一:era 非法值兜底(语义防护——主产物 initSim 造)
|
||||
if (state.worldSim.era !== 'shengshi' && state.worldSim.era !== 'pingshi' && state.worldSim.era !== 'luanshi' && state.worldSim.era !== 'mofa') {
|
||||
state.worldSim.era = 'pingshi'
|
||||
state.worldSim.eraStartYear = 1
|
||||
} else if (typeof state.worldSim.eraStartYear !== 'number') {
|
||||
state.worldSim.eraStartYear = state.year ?? 1
|
||||
}
|
||||
if (typeof state.worldSim.overfluxYear !== 'number') state.worldSim.overfluxYear = -99
|
||||
if (!Array.isArray(state.worldSim.worldAnnals)) state.worldSim.worldAnnals = []
|
||||
if (state.worldSim.distress && typeof state.worldSim.distress !== 'object') state.worldSim.distress = undefined
|
||||
for (const dyn of Object.values(state.worldSim.npcDyn)) {
|
||||
if (dyn && typeof (dyn as { prosperity?: unknown }).prosperity !== 'number') {
|
||||
(dyn as { prosperity: number }).prosperity = 50
|
||||
}
|
||||
}
|
||||
}
|
||||
if (state.family.headId && !state.members[state.family.headId]) {
|
||||
const firstAlive = Object.values(state.members).find((c) => c.alive)
|
||||
|
||||
Reference in New Issue
Block a user