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:
@@ -54,6 +54,8 @@ export function buyTechnique(w: World, techId: string, price: number): boolean {
|
||||
}
|
||||
|
||||
export function techniquePrice(techId: string): number {
|
||||
const t = pack().techniques.find((x) => x.id === techId)
|
||||
if (t) return TECHNIQUE_GRADE_PRICE[t.grade] ?? 300
|
||||
return TECH_GRADE_BASE[techId] ?? 200
|
||||
}
|
||||
|
||||
|
||||
@@ -153,6 +153,7 @@ export class WorldSim {
|
||||
};当世最强为 ${topNowName}(${topNow})。`
|
||||
if (!s.sagaAnnals) s.sagaAnnals = []
|
||||
s.sagaAnnals.push({ year: y, kind, text })
|
||||
if (s.sagaAnnals.length > 40) s.sagaAnnals.splice(0, s.sagaAnnals.length - 40)
|
||||
this.w.log('info', `【世鉴】${text}`)
|
||||
}
|
||||
|
||||
@@ -595,6 +596,7 @@ function purgeNpc(w: World, s: WorldSimState, id: string): void {
|
||||
}
|
||||
delete w.state.family.flag[`raidCD-${id}`]
|
||||
delete w.state.family.flag[`auction-${id}`]
|
||||
delete w.state.family.flag[`tauntCD-${id}`]
|
||||
w.state.eventQueue = (w.state.eventQueue ?? []).filter((e) => !e.startsWith('ev-raid-') || !e.endsWith(id))
|
||||
if (s.distress?.id === id) s.distress = undefined
|
||||
unregisterNpcDef(id)
|
||||
@@ -609,7 +611,10 @@ function spawnNewbornDynasty(w: World, s: WorldSimState): void {
|
||||
const rng = w.rng
|
||||
const style = rng.pick([...NEWBORN_STYLES])
|
||||
const region = rng.pick([...NEWBORN_REGIONS])
|
||||
const id = `n-new-${rng.int(1, 9999)}`
|
||||
// P1-10 id 掺 seed 指纹(防跨档碰撞)
|
||||
let seedHash = 0
|
||||
for (let i = 0; i < w.state.seed.length; i++) seedHash = (seedHash * 31 + w.state.seed.charCodeAt(i)) >>> 0
|
||||
const id = `n-new-${(seedHash % 4096).toString(36)}-${rng.int(1, 9999)}`
|
||||
const name = `${region.slice(0, 2)}${NEWBORN_NAME_SUFFIX[rng.int(0, NEWBORN_NAME_SUFFIX.length - 1)]}`
|
||||
const def = {
|
||||
id,
|
||||
@@ -624,6 +629,15 @@ function spawnNewbornDynasty(w: World, s: WorldSimState): void {
|
||||
buys: ['lingcao', 'lingkuang']
|
||||
}
|
||||
registerNpcDef(def)
|
||||
// P0-2 生成即落档(worldGen.npcs 追加——读档幂等重注册,防御新贵僵尸)
|
||||
if (w.state.worldGen) {
|
||||
if (!w.state.worldGen.npcs) w.state.worldGen.npcs = []
|
||||
w.state.worldGen.npcs.push({
|
||||
id: def.id, name: def.name, region: def.region, style: def.style,
|
||||
desc: def.desc, leaderRealm: def.leaderRealm, initialPower: def.initialPower,
|
||||
powerGrowth: def.powerGrowth, sells: def.sells, buys: def.buys
|
||||
})
|
||||
}
|
||||
w.state.npcFamilies[id] = {
|
||||
id, name, region,
|
||||
power: def.initialPower,
|
||||
|
||||
@@ -22,23 +22,52 @@ const DEFAULT_GEN_REGIONS = ['北岳玄影峰', '西川药谷', '南都连港',
|
||||
const DEFAULT_GEN_SUFFIX = ['氏', '氏', '宗', '寨', '门']
|
||||
const DEFAULT_GEN_FAM = ['玄', '墨', '楚', '白', '萧', '洛', '燕', '秦', '顾', '周', '华', '苏']
|
||||
|
||||
/** 聚合词库池(MOD/插件注入端;读取端 worldgen 消费) */
|
||||
/** 聚合词库池(MOD/插件注入端;读取端 worldgen 消费)
|
||||
* 0.1.28 追踪回滚:add 记录来源(source key),removePool 精确退——卸 MOD 后同 seed 重放零漂移。 */
|
||||
type PoolPart = { styles?: string[]; regions?: string[]; suffixes?: string[]; fams?: string[] }
|
||||
const TRACKER = new Map<string, PoolPart>()
|
||||
|
||||
export const WorldGenPools = {
|
||||
styles: [...DEFAULT_GEN_STYLES],
|
||||
regions: [...DEFAULT_GEN_REGIONS],
|
||||
suffixes: [...DEFAULT_GEN_SUFFIX],
|
||||
fams: [...DEFAULT_GEN_FAM],
|
||||
add(part: { styles?: string[]; regions?: string[]; suffixes?: string[]; fams?: string[] }): void {
|
||||
add(part: PoolPart, source = 'unnamed'): void {
|
||||
TRACKER.set(source, part)
|
||||
if (part.styles) for (const s of part.styles) if (!this.styles.includes(s)) this.styles.push(s)
|
||||
if (part.regions) for (const r of part.regions) if (!this.regions.includes(r)) this.regions.push(r)
|
||||
if (part.suffixes) for (const s of part.suffixes) if (!this.suffixes.includes(s)) this.suffixes.push(s)
|
||||
if (part.fams) for (const f of part.fams) if (!this.fams.includes(f)) this.fams.push(f)
|
||||
},
|
||||
/** 精确回滚:移除某来源注入的词条(其他来源仍拥有的保留) */
|
||||
removePool(source: string): void {
|
||||
const part = TRACKER.get(source)
|
||||
if (!part) return
|
||||
TRACKER.delete(source)
|
||||
const ownedByOthers = new Set(
|
||||
[...TRACKER.values()].flatMap((p) => [
|
||||
...(p.styles ?? []), ...(p.regions ?? []), ...(p.suffixes ?? []), ...(p.fams ?? [])
|
||||
])
|
||||
)
|
||||
const removeIfUnshared = (arr: string[], items?: string[]) => {
|
||||
if (!items) return
|
||||
for (const s of items) {
|
||||
if (ownedByOthers.has(s)) continue
|
||||
const idx = arr.indexOf(s)
|
||||
if (idx >= 0) arr.splice(idx, 1)
|
||||
}
|
||||
}
|
||||
removeIfUnshared(this.styles, part.styles)
|
||||
removeIfUnshared(this.regions, part.regions)
|
||||
removeIfUnshared(this.suffixes, part.suffixes)
|
||||
removeIfUnshared(this.fams, part.fams)
|
||||
},
|
||||
reset(): void {
|
||||
this.styles = [...DEFAULT_GEN_STYLES]
|
||||
this.regions = [...DEFAULT_GEN_REGIONS]
|
||||
this.suffixes = [...DEFAULT_GEN_SUFFIX]
|
||||
this.fams = [...DEFAULT_GEN_FAM]
|
||||
TRACKER.clear()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -218,6 +218,13 @@ export function addCalamity(
|
||||
return true
|
||||
}
|
||||
|
||||
export function removeCalamityByName(name: string): void {
|
||||
const idx = EXTENDED_CALAMITIES.indexOf(name)
|
||||
if (idx >= 0) EXTENDED_CALAMITIES.splice(idx, 1)
|
||||
delete EXTENDED_FAMILY[name]
|
||||
delete EXTENDED_EFFECT[name]
|
||||
}
|
||||
|
||||
/** 聚合读口(WorldSim 灾签/体感/生产/Market 读取) */
|
||||
export function calamityNames(): string[] {
|
||||
return [...DEFAULT_CALAMITIES, ...EXTENDED_CALAMITIES]
|
||||
|
||||
Reference in New Issue
Block a user