0.1.39 P3: worldsim tick 入口双闸守卫 + 关停冻结测试(4 例全绿)

This commit is contained in:
2026-09-13 12:55:59 +08:00
parent 62da87a4e4
commit e2070c8fcb
2 changed files with 111 additions and 0 deletions
+4
View File
@@ -25,6 +25,10 @@ export class WorldSim {
} }
tick(): void { tick(): void {
// 0.1.39 根治双闸:clocks.ts 外部守卫 + 此处入口二次守卫。
// 与 tournament/apprentice 等系统卡同模式(sysEnabled ?? true 兜底,
// 注册后默认开、关停后 false)。防止未来新增直接调 tick() 的路径绕过守卫。
if (!this.w.sysEnabled('worldsim')) return
const s = this.s() const s = this.s()
const rng = this.w.rng const rng = this.w.rng
// ---- C. 灵气潮汐(大周期) ---- // ---- C. 灵气潮汐(大周期) ----
+107
View File
@@ -0,0 +1,107 @@
/**
* 0.1.39 P3worldsim 能力卡关停根治测试
* 验证关停后世界自主演进完全冻结——潮汐、NPC 动力学、时代弧、快讯不再推进。
* 注意:玩家行为(修炼耗草→tradeSettle 回写池、买卖交易回写池)不受 worldsim
* 能力卡关停影响——这是玩家与世界的交互而非世界自主演进。
*/
import { describe, expect, it } from 'vitest'
import { World } from '../src/renderer/game/engine/runtime/World'
import { WorldSim } from '../src/renderer/game/engine/sim/WorldSim'
import { resetSaveBus, attachLogSink } from './world.helpers'
import type { WorldSimState } from '../src/renderer/game/engine/sim/worldsim-data'
function baseWorld(seed: string): World {
const w = World.create({ seed, surname: '封', familyName: '封家', motto: 'm', difficulty: 'normal' })
resetSaveBus()
attachLogSink(w)
return w
}
describe('0.1.39 worldsim 关停根治', () => {
it('sysEnabled("worldsim") 默认开 → toggleSystem 后关', () => {
const w = baseWorld('ws-toggle-1')
expect(w.sysEnabled('worldsim')).toBe(true)
const after = w.toggleSystem('worldsim')
expect(after).toBe(false)
expect(w.sysEnabled('worldsim')).toBe(false)
})
it('关停后 tick() 直接 return(入口双闸守卫)', () => {
const w = baseWorld('ws-freeze-1')
// 推进 12 月让 worldSim 有初始状态
for (let i = 0; i < 12; i++) w.advanceMonth()
const ws = w.state.worldSim as WorldSimState
expect(ws).toBeDefined()
// 快照关键字段
const tideBefore = ws.tide
const tideTicksBefore = ws.tideTicks
const poolBefore = { ...ws.marketPool }
// 关停 worldsim
w.toggleSystem('worldsim')
expect(w.sysEnabled('worldsim')).toBe(false)
// 直接调 tick() 应被入口守卫拦截
new WorldSim(w).tick()
// 状态完全冻结(tick 内所有逻辑未执行)
expect(ws.tide).toBe(tideBefore)
expect(ws.tideTicks).toBe(tideTicksBefore)
expect(ws.marketPool).toEqual(poolBefore)
})
it('关停后 advanceMonth 不再自主演进世界(潮汐/NPC/时代弧/快讯冻结)', () => {
const w = baseWorld('ws-freeze-2')
// 推进 24 月让世界有实质演化
for (let i = 0; i < 24; i++) w.advanceMonth()
const ws = w.state.worldSim as WorldSimState
expect(ws).toBeDefined()
// 快照世界自主演进指标
const tideTicksBefore = ws.tideTicks
const npcDynBefore = JSON.stringify(ws.npcDyn)
const secretQiBefore = JSON.stringify(ws.secretQi)
const eraBefore = ws.era
const newsLenBefore = ws.newsFeed.length
const calamityBefore = ws.calamity
const warFatigueBefore = ws.warFatigue
// 关停
w.toggleSystem('worldsim')
// 推进 36 月——世界自主演进应纹丝不动
for (let i = 0; i < 36; i++) w.advanceMonth()
// tick 内逻辑全部冻结
expect(ws.tideTicks).toBe(tideTicksBefore) // 潮汐不推进
expect(JSON.stringify(ws.npcDyn)).toBe(npcDynBefore) // NPC 动力学不变
expect(JSON.stringify(ws.secretQi)).toBe(secretQiBefore) // 秘境灵气不自恢复
expect(ws.era).toBe(eraBefore) // 时代弧不变
expect(ws.newsFeed.length).toBe(newsLenBefore) // 无新快讯
expect(ws.calamity).toBe(calamityBefore) // 灾年状态不变
expect(ws.warFatigue).toBe(warFatigueBefore) // 战争疲劳不变
})
it('重新开启后世界恢复演进(可逆性)', () => {
const w = baseWorld('ws-resume-1')
for (let i = 0; i < 12; i++) w.advanceMonth()
const ws = w.state.worldSim as WorldSimState
// 关停 12 月
w.toggleSystem('worldsim')
const tideFrozen = ws.tide
const ticksFrozen = ws.tideTicks
for (let i = 0; i < 12; i++) w.advanceMonth()
expect(ws.tide).toBe(tideFrozen)
expect(ws.tideTicks).toBe(ticksFrozen)
// 重新开启
w.toggleSystem('worldsim')
expect(w.sysEnabled('worldsim')).toBe(true)
for (let i = 0; i < 12; i++) w.advanceMonth()
// 世界恢复演进——tideTicks 必须增长
expect(ws.tideTicks).toBeGreaterThan(ticksFrozen)
})
})