You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

71 lines
2.4 KiB

/** System 接口:按 priority 排序,由 SystemRegistry 统一调度 tick(无业务依赖) */
export interface ISystem {
/** 调度优先级(越小越先 tick) */
readonly priority: number;
/** 是否启用(false 跳过 tick) */
enabled: boolean;
/** 每帧更新 */
tick(dt: number): void;
}
/** System 构造器类型(不强制构造参数,由具体 system 自行声明依赖) */
export type ISystemCtor<T extends ISystem> = new (...args: any[]) => T;
/** System 注册与调度表 */
export class SystemRegistry {
private readonly _systems: ISystem[] = [];
private _sorted: ISystem[] | null = null;
/** 注册 system */
register<T extends ISystem>(system: T): T {
this._systems.push(system);
this._sorted = null;
return system;
}
/** 按类型取已注册 system */
get<T extends ISystem>(ctor: ISystemCtor<T>): 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);
}
}
}