/** System 接口:按 priority 排序,由 SystemRegistry 统一调度 tick(无业务依赖) */ export interface ISystem { /** 调度优先级(越小越先 tick) */ readonly priority: number; /** 是否启用(false 跳过 tick) */ enabled: boolean; /** 每帧更新 */ tick(dt: number): void; } /** System 构造器类型(不强制构造参数,由具体 system 自行声明依赖) */ export type ISystemCtor = new (...args: any[]) => T; /** System 注册与调度表 */ export class SystemRegistry { private readonly _systems: ISystem[] = []; private _sorted: ISystem[] | null = null; /** 注册 system */ register(system: T): T { this._systems.push(system); this._sorted = null; return system; } /** 按类型取已注册 system */ get(ctor: ISystemCtor): T | undefined { return this._systems.find((s) => s instanceof ctor) as T | undefined; } /** 按 priority 升序依次 tick(enabled=false 跳过)。单个 system 抛错不打断后续(含出怪) */ tick(dt: number): void { if (!this._sorted) { this._sorted = [...this._systems].sort((a, b) => a.priority - b.priority); } for (const s of this._sorted) { this._tickOne(s, dt); } } /** 按 slice 轮询 system:非当前 slice 的系统本帧不 tick,dt 按 slice 补偿 */ tickSlice(dt: number, sliceIndex: number, sliceCount: number): void { if (sliceCount <= 1) { this.tick(dt); return; } if (!this._sorted) { this._sorted = [...this._systems].sort((a, b) => a.priority - b.priority); } const compensated = dt * sliceCount; for (let i = 0; i < this._sorted.length; i++) { if (i % sliceCount !== sliceIndex) continue; this._tickOne(this._sorted[i], compensated); } } /** * 单系统 tick。异常只打日志,避免技能/Buff 抛错吞掉同帧后面的 WaveSpawner。 * @param system 系统 * @param dt 本拍步长(秒) */ private _tickOne(system: ISystem, dt: number): void { if (!system.enabled) return; try { system.tick(dt); } catch (err) { const name = system.constructor?.name ?? 'system'; console.error('[SystemRegistry] tick', name, err); } } }