v0.1.7: 仙门之钥(门面化/能力注册表/数据包/开发者面板)

- GameFacade 统一门面:act(23 种动作白名单)/query(6 类只读快照)/subscribe(七大事件协议)/
  about(版本+模块清单+数据包指纹);UI store 接入门面(act 直达,散装调用收口)
- CapabilityRegistry:12 张能力卡(id/name/version/desc/hooks),world.systems 启停即拔插,
  时钟按能力开关过滤(禁修炼则无人精进…沙盒玩法);sysChanged 广播
- DataPackRegistry:默认包与静态数据同引用(金钟罩零漂移),override/reset/fingerprint,
  高频读口 6 处迁移 pack()——未来 MOD=注入数据包覆写
- 开发者面板:设置页系统仪表盘(清单+启停开关+警示文案)
- 测试 225→239(能力清单/拔插分殊四路/广播幂等/包覆盖物价/act 目录/query/协议退订/about/
  金钟罩复验零漂移)
This commit is contained in:
2026-08-23 09:32:21 +08:00
parent a7ee125866
commit 9e0b06e898
11 changed files with 543 additions and 29 deletions
+27 -2
View File
@@ -10,12 +10,14 @@ import {
} from '../types/domain'
import { Rng } from '../core/rng'
import { BUILDINGS } from '../data/buildings'
import { pack } from '../data/registry'
import { POSTS } from '../data/posts'
import { TECHNIQUES } from '../data/techniques'
import { aspirationById as aspirationOf } from '../data/aspirations'
import { computeLegacy, resolveLegacy, peakRealmIndex, grandTechniqueCount, LegacyArch } from '../core/legacy'
import { createWorldState, findInheritor } from './creation'
import { buildClock } from './clocks'
import { SYSTEM_DEFS, SystemDef } from './capabilities'
import { GameClock } from '../core/clock'
import { resolveBreakthrough } from './systems/cultivation'
import { applyEventChoice } from './systems/events'
@@ -30,6 +32,7 @@ export interface WorldEventBus {
onPendingEvent(id: string): void
onGameOver(reason: string, year: number): void
onYearPaper?(entry: YearlyReport): void
onSystemChange?(id: string, enabled: boolean): void
}
export function normalizeGameState(state: GameState): GameState {
@@ -65,6 +68,7 @@ export class World {
rng: Rng
out: WorldEventBus[]
clock: GameClock
systems: Record<string, { enabled: boolean }>
constructor(state: GameState, out: WorldEventBus[] = []) {
normalizeGameState(state)
@@ -72,6 +76,23 @@ export class World {
this.rng = new Rng(state.rng)
this.out = out
this.clock = buildClock()
this.systems = Object.fromEntries(SYSTEM_DEFS.map((d) => [d.id, { enabled: true }]))
}
sysEnabled(id: string): boolean {
return this.systems[id]?.enabled ?? true
}
toggleSystem(id: string): boolean {
const s = this.systems[id]
if (!s) return false
s.enabled = !s.enabled
this.out.forEach((o) => o.onSystemChange?.(id, s.enabled))
return s.enabled
}
systemList(): { id: string; name: string; version: string; desc: string; enabled: boolean }[] {
return SYSTEM_DEFS.map((d) => ({ id: d.id, name: d.name, version: d.version, desc: d.desc, enabled: this.sysEnabled(d.id) }))
}
seq(): Id {
@@ -115,6 +136,10 @@ export class World {
this.out.forEach((o) => o.onGameOver(reason, year))
}
gameOver___placeholder(): void {
void 0
}
memberById(id: Id): Character {
const c = this.state.members[id]
if (!c) throw new Error(`member not found ${id}`)
@@ -444,7 +469,7 @@ export class World {
if (fam.stones < 150) return false
fam.stones -= 150
fam.flag['sutraCD'] = this.state.year
const pool = TECHNIQUES.filter((t) => t.grade >= 2 && !fam.techniques.includes(t.id))
const pool = pack().techniques.filter((t) => t.grade >= 2 && !fam.techniques.includes(t.id))
if (pool.length === 0) {
this.log('info', '求经访道:天下典籍已入庶几,无可再得。')
this.chronicle('event', '求经台广搜天下,经卷已穷。', undefined, false)