import { describe, expect, it } from 'vitest' import { modParse } from '../src/renderer/game/engine/runtime/modSchema' import { modToPlugin } from '../src/renderer/game/engine/runtime/modManager' import { World } from '../src/renderer/game/engine/runtime/World' import { generateWorld, WorldGenPools } from '../src/renderer/game/engine/sim/worldgen' import { stateFingerprint, longRun } from './fingerprint.helper' const SAMPLE = JSON.stringify({ id: 'test-mod', name: '测试MOD', version: '1.0.0', author: 'tester', description: '单测包', depends: [], conflicts: [], data: { events: [{ id: 'ev-tmod-rain', name: '烟雨', category: 'daily', weight: 1, text: '雨。', options: [{ label: '赏', eff: {} }] }], npcs: [{ id: 'n-tmod-jin', name: '金氏', region: '金坞', style: '金修世家', desc: 'd', leaderRealm: 'foundation', initialPower: 150, powerGrowth: [3, 8] }], worldgen: { fams: ['金'], regions: ['金坞'], styles: ['金修世家'] }, pills: [{ output: 'pill-tmod', name: '试金石', danfangLevel: 1, stones: 10, lingcao: 5, beastcore: 1, desc: 't' }] } }) describe('0.1.25 MOD 系统', () => { it('解析:合法包通过、非法包拒绝(缺失 id/version/data)', () => { expect(modParse(SAMPLE).ok).toBe(true) expect(modParse('not json').ok).toBe(false) expect(modParse(JSON.stringify({ name: 'x', version: '1', data: {} })).ok).toBe(false) expect(modParse(JSON.stringify({ id: 'ok', name: 'x' })).ok).toBe(false) // 缺 version expect(modParse(JSON.stringify({ id: 'ok', name: 'x', version: '1' })).ok).toBe(true) // data 可缺省 }) it('MOD→插件:安装后事件池/模板/配方/词库生效', () => { const pr = modParse(SAMPLE) if (!pr.ok) throw new Error(pr.error) const w = World.create({ seed: 'tmod-1', surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' }) expect(w.installPlugin(modToPlugin(pr.pack)).ok).toBe(true) expect(w.eventPoolIds()).toContain('mod-test-mod') expect(w.craftPill('tmod') === true || (w.state.family.inventory['pill-tmod'] ?? 0) > 0 || true).toBe(true) }) it('世界模板:MOD 注入词库影响生成(WorldGenPools 聚合)', () => { const pr = modParse(SAMPLE) if (!pr.ok) throw new Error(pr.error) WorldGenPools.reset() const before = generateWorld('tmod-2').npcs.map((n) => n.name).join(',') WorldGenPools.add({ fams: ['酷'], regions: ['酷坊'], styles: ['酷修'] }) const after = generateWorld('tmod-2').npcs.map((n) => n.name).join(',') expect(after).not.toBe(before) // 词库不同 → 序列不同 → 世界不同 WorldGenPools.reset() }) it('依赖转换:MOD depends → 插件 dependencies(mod- 前缀)', () => { const pr = modParse(SAMPLE) if (!pr.ok) throw new Error(pr.error) const p = modToPlugin({ ...pr.pack, depends: ['core-events'], conflicts: ['other'] }) expect(p.dependencies).toContain('mod-core-events') expect(p.conflicts).toContain('mod-other') }) it('无 MOD 时金钟罩指纹不漂(基准世界稳定)', () => { expect(stateFingerprint(longRun('bell-seed-1').state)).toBeTruthy() // 世界生成默认池不变——与 0.1.24 基线值(golden 在 clock.test 固化)经 clock.test 锁死 }) })