feat: 添加ECS核心功能模块 - EntityManager实体管理器、EventBus事件总线、性能优化系统

This commit is contained in:
YHH
2025-06-09 13:24:24 +08:00
parent 6e2e7a4af5
commit e219fc47ba
6 changed files with 2296 additions and 0 deletions

View File

@@ -0,0 +1,261 @@
import { Entity } from '../Entity';
import { ComponentType } from './ComponentStorage';
/**
* 原型标识符
*/
export type ArchetypeId = string;
/**
* 原型数据结构
*/
export interface Archetype {
/** 原型唯一标识符 */
id: ArchetypeId;
/** 包含的组件类型 */
componentTypes: ComponentType[];
/** 属于该原型的实体列表 */
entities: Entity[];
/** 原型创建时间 */
createdAt: number;
/** 最后更新时间 */
updatedAt: number;
}
/**
* 原型查询结果
*/
export interface ArchetypeQueryResult {
/** 匹配的原型列表 */
archetypes: Archetype[];
/** 所有匹配实体的总数 */
totalEntities: number;
/** 查询执行时间(毫秒) */
executionTime: number;
/** 是否使用了缓存 */
fromCache: boolean;
}
/**
* Archetype系统
*
* 根据实体的组件组合将实体分组到不同的原型中,提供高效的查询性能。
*/
export class ArchetypeSystem {
/** 所有原型的映射表 */
private _archetypes = new Map<ArchetypeId, Archetype>();
/** 实体到原型的映射 */
private _entityToArchetype = new Map<Entity, Archetype>();
/** 组件类型到原型的映射 */
private _componentToArchetypes = new Map<ComponentType, Set<Archetype>>();
/** 查询缓存 */
private _queryCache = new Map<string, {
result: ArchetypeQueryResult;
timestamp: number;
}>();
private _cacheTimeout = 5000;
private _maxCacheSize = 100;
/**
* 添加实体到原型系统
*/
public addEntity(entity: Entity): void {
const componentTypes = this.getEntityComponentTypes(entity);
const archetypeId = this.generateArchetypeId(componentTypes);
let archetype = this._archetypes.get(archetypeId);
if (!archetype) {
archetype = this.createArchetype(componentTypes);
}
archetype.entities.push(entity);
archetype.updatedAt = Date.now();
this._entityToArchetype.set(entity, archetype);
this.updateComponentIndexes(archetype, componentTypes, true);
this.invalidateQueryCache();
}
/**
* 从原型系统中移除实体
*/
public removeEntity(entity: Entity): void {
const archetype = this._entityToArchetype.get(entity);
if (!archetype) return;
const index = archetype.entities.indexOf(entity);
if (index !== -1) {
archetype.entities.splice(index, 1);
archetype.updatedAt = Date.now();
}
this._entityToArchetype.delete(entity);
this.invalidateQueryCache();
}
/**
* 查询包含指定组件组合的原型
*/
public queryArchetypes(componentTypes: ComponentType[], operation: 'AND' | 'OR' = 'AND'): ArchetypeQueryResult {
const startTime = performance.now();
const cacheKey = `${operation}:${componentTypes.map(t => t.name).sort().join(',')}`;
// 检查缓存
const cached = this._queryCache.get(cacheKey);
if (cached && (Date.now() - cached.timestamp < this._cacheTimeout)) {
return {
...cached.result,
executionTime: performance.now() - startTime,
fromCache: true
};
}
const matchingArchetypes: Archetype[] = [];
let totalEntities = 0;
if (operation === 'AND') {
for (const archetype of this._archetypes.values()) {
if (this.archetypeContainsAllComponents(archetype, componentTypes)) {
matchingArchetypes.push(archetype);
totalEntities += archetype.entities.length;
}
}
} else {
const foundArchetypes = new Set<Archetype>();
for (const componentType of componentTypes) {
const archetypes = this._componentToArchetypes.get(componentType);
if (archetypes) {
for (const archetype of archetypes) {
foundArchetypes.add(archetype);
}
}
}
for (const archetype of foundArchetypes) {
matchingArchetypes.push(archetype);
totalEntities += archetype.entities.length;
}
}
const result: ArchetypeQueryResult = {
archetypes: matchingArchetypes,
totalEntities,
executionTime: performance.now() - startTime,
fromCache: false
};
// 缓存结果
this._queryCache.set(cacheKey, {
result,
timestamp: Date.now()
});
return result;
}
/**
* 获取实体所属的原型
*/
public getEntityArchetype(entity: Entity): Archetype | undefined {
return this._entityToArchetype.get(entity);
}
/**
* 获取所有原型
*/
public getAllArchetypes(): Archetype[] {
return Array.from(this._archetypes.values());
}
/**
* 清空所有数据
*/
public clear(): void {
this._archetypes.clear();
this._entityToArchetype.clear();
this._componentToArchetypes.clear();
this._queryCache.clear();
}
/**
* 获取实体的组件类型列表
*/
private getEntityComponentTypes(entity: Entity): ComponentType[] {
return entity.components.map(component => component.constructor as ComponentType);
}
/**
* 生成原型ID
*/
private generateArchetypeId(componentTypes: ComponentType[]): ArchetypeId {
return componentTypes
.map(type => type.name)
.sort()
.join('|');
}
/**
* 创建新原型
*/
private createArchetype(componentTypes: ComponentType[]): Archetype {
const id = this.generateArchetypeId(componentTypes);
const archetype: Archetype = {
id,
componentTypes: [...componentTypes],
entities: [],
createdAt: Date.now(),
updatedAt: Date.now()
};
this._archetypes.set(id, archetype);
return archetype;
}
/**
* 检查原型是否包含所有指定组件
*/
private archetypeContainsAllComponents(archetype: Archetype, componentTypes: ComponentType[]): boolean {
for (const componentType of componentTypes) {
if (!archetype.componentTypes.includes(componentType)) {
return false;
}
}
return true;
}
/**
* 更新组件索引
*/
private updateComponentIndexes(archetype: Archetype, componentTypes: ComponentType[], add: boolean): void {
for (const componentType of componentTypes) {
let archetypes = this._componentToArchetypes.get(componentType);
if (!archetypes) {
archetypes = new Set();
this._componentToArchetypes.set(componentType, archetypes);
}
if (add) {
archetypes.add(archetype);
} else {
archetypes.delete(archetype);
if (archetypes.size === 0) {
this._componentToArchetypes.delete(componentType);
}
}
}
}
/**
* 使查询缓存失效
*/
private invalidateQueryCache(): void {
this._queryCache.clear();
}
}

View File

@@ -0,0 +1,488 @@
import { Entity } from '../Entity';
import { Component } from '../Component';
import { ComponentType } from './ComponentStorage';
/**
* 组件索引类型
*/
export enum IndexType {
/** 哈希索引 - 最快查找 */
HASH = 'hash',
/** 位图索引 - 内存高效 */
BITMAP = 'bitmap',
/** 排序索引 - 支持范围查询 */
SORTED = 'sorted'
}
/**
* 索引统计信息
*/
export interface IndexStats {
/** 索引类型 */
type: IndexType;
/** 索引大小 */
size: number;
/** 内存使用量(字节) */
memoryUsage: number;
/** 查询次数 */
queryCount: number;
/** 平均查询时间(毫秒) */
avgQueryTime: number;
/** 最后更新时间 */
lastUpdated: number;
}
/**
* 组件索引接口
*/
export interface IComponentIndex {
/** 索引类型 */
readonly type: IndexType;
/** 添加实体到索引 */
addEntity(entity: Entity): void;
/** 从索引中移除实体 */
removeEntity(entity: Entity): void;
/** 查询包含指定组件的实体 */
query(componentType: ComponentType): Set<Entity>;
/** 批量查询多个组件 */
queryMultiple(componentTypes: ComponentType[], operation: 'AND' | 'OR'): Set<Entity>;
/** 清空索引 */
clear(): void;
/** 获取索引统计信息 */
getStats(): IndexStats;
}
/**
* 哈希索引实现
*
* 使用Map数据结构提供O(1)的查找性能。
* 适合大多数查询场景。
*/
export class HashComponentIndex implements IComponentIndex {
public readonly type = IndexType.HASH;
private _componentToEntities = new Map<ComponentType, Set<Entity>>();
private _entityToComponents = new Map<Entity, Set<ComponentType>>();
private _queryCount = 0;
private _totalQueryTime = 0;
private _lastUpdated = Date.now();
public addEntity(entity: Entity): void {
const components = entity.components;
const componentTypes = new Set<ComponentType>();
for (const component of components) {
const componentType = component.constructor as ComponentType;
componentTypes.add(componentType);
let entities = this._componentToEntities.get(componentType);
if (!entities) {
entities = new Set();
this._componentToEntities.set(componentType, entities);
}
entities.add(entity);
}
this._entityToComponents.set(entity, componentTypes);
this._lastUpdated = Date.now();
}
public removeEntity(entity: Entity): void {
const componentTypes = this._entityToComponents.get(entity);
if (!componentTypes) return;
for (const componentType of componentTypes) {
const entities = this._componentToEntities.get(componentType);
if (entities) {
entities.delete(entity);
if (entities.size === 0) {
this._componentToEntities.delete(componentType);
}
}
}
this._entityToComponents.delete(entity);
this._lastUpdated = Date.now();
}
public query(componentType: ComponentType): Set<Entity> {
const startTime = performance.now();
const result = new Set(this._componentToEntities.get(componentType) || []);
this._queryCount++;
this._totalQueryTime += performance.now() - startTime;
return result;
}
public queryMultiple(componentTypes: ComponentType[], operation: 'AND' | 'OR'): Set<Entity> {
const startTime = performance.now();
if (componentTypes.length === 0) {
return new Set();
}
if (componentTypes.length === 1) {
return this.query(componentTypes[0]);
}
let result: Set<Entity>;
if (operation === 'AND') {
let smallestSet: Set<Entity> | undefined;
let smallestSize = Infinity;
for (const componentType of componentTypes) {
const entities = this._componentToEntities.get(componentType);
if (!entities || entities.size === 0) {
this._queryCount++;
this._totalQueryTime += performance.now() - startTime;
return new Set();
}
if (entities.size < smallestSize) {
smallestSize = entities.size;
smallestSet = entities;
}
}
result = new Set();
if (smallestSet) {
for (const entity of smallestSet) {
let hasAll = true;
for (const componentType of componentTypes) {
const entities = this._componentToEntities.get(componentType);
if (!entities || !entities.has(entity)) {
hasAll = false;
break;
}
}
if (hasAll) {
result.add(entity);
}
}
}
} else {
result = new Set();
for (const componentType of componentTypes) {
const entities = this._componentToEntities.get(componentType);
if (entities) {
for (const entity of entities) {
result.add(entity);
}
}
}
}
this._queryCount++;
this._totalQueryTime += performance.now() - startTime;
return result;
}
public clear(): void {
this._componentToEntities.clear();
this._entityToComponents.clear();
this._lastUpdated = Date.now();
}
public getStats(): IndexStats {
let memoryUsage = 0;
memoryUsage += this._componentToEntities.size * 64;
memoryUsage += this._entityToComponents.size * 64;
for (const entities of this._componentToEntities.values()) {
memoryUsage += entities.size * 8;
}
for (const components of this._entityToComponents.values()) {
memoryUsage += components.size * 8;
}
return {
type: this.type,
size: this._componentToEntities.size,
memoryUsage,
queryCount: this._queryCount,
avgQueryTime: this._queryCount > 0 ? this._totalQueryTime / this._queryCount : 0,
lastUpdated: this._lastUpdated
};
}
}
/**
* 位图索引实现
*
* 使用位操作进行快速集合运算,内存效率高。
* 适合有限组件类型和大量实体的场景。
*/
export class BitmapComponentIndex implements IComponentIndex {
public readonly type = IndexType.BITMAP;
private _componentTypeToBit = new Map<ComponentType, number>();
private _entityToBitmap = new Map<Entity, number>();
private _bitToEntities = new Map<number, Set<Entity>>();
private _nextBit = 0;
private _queryCount = 0;
private _totalQueryTime = 0;
private _lastUpdated = Date.now();
public addEntity(entity: Entity): void {
let bitmap = 0;
for (const component of entity.components) {
const componentType = component.constructor as ComponentType;
let bit = this._componentTypeToBit.get(componentType);
if (bit === undefined) {
bit = this._nextBit++;
this._componentTypeToBit.set(componentType, bit);
}
bitmap |= (1 << bit);
let entities = this._bitToEntities.get(1 << bit);
if (!entities) {
entities = new Set();
this._bitToEntities.set(1 << bit, entities);
}
entities.add(entity);
}
this._entityToBitmap.set(entity, bitmap);
this._lastUpdated = Date.now();
}
public removeEntity(entity: Entity): void {
const bitmap = this._entityToBitmap.get(entity);
if (bitmap === undefined) return;
// 从所有相关的位集合中移除实体
for (const [bitMask, entities] of this._bitToEntities) {
if ((bitmap & bitMask) !== 0) {
entities.delete(entity);
if (entities.size === 0) {
this._bitToEntities.delete(bitMask);
}
}
}
this._entityToBitmap.delete(entity);
this._lastUpdated = Date.now();
}
public query(componentType: ComponentType): Set<Entity> {
const startTime = performance.now();
const bit = this._componentTypeToBit.get(componentType);
if (bit === undefined) {
this._queryCount++;
this._totalQueryTime += performance.now() - startTime;
return new Set();
}
const result = new Set(this._bitToEntities.get(1 << bit) || []);
this._queryCount++;
this._totalQueryTime += performance.now() - startTime;
return result;
}
public queryMultiple(componentTypes: ComponentType[], operation: 'AND' | 'OR'): Set<Entity> {
const startTime = performance.now();
if (componentTypes.length === 0) {
return new Set();
}
let targetBitmap = 0;
const validBits: number[] = [];
for (const componentType of componentTypes) {
const bit = this._componentTypeToBit.get(componentType);
if (bit !== undefined) {
targetBitmap |= (1 << bit);
validBits.push(1 << bit);
}
}
const result = new Set<Entity>();
if (operation === 'AND') {
for (const [entity, entityBitmap] of this._entityToBitmap) {
if ((entityBitmap & targetBitmap) === targetBitmap) {
result.add(entity);
}
}
} else {
for (const bitMask of validBits) {
const entities = this._bitToEntities.get(bitMask);
if (entities) {
for (const entity of entities) {
result.add(entity);
}
}
}
}
this._queryCount++;
this._totalQueryTime += performance.now() - startTime;
return result;
}
public clear(): void {
this._componentTypeToBit.clear();
this._entityToBitmap.clear();
this._bitToEntities.clear();
this._nextBit = 0;
this._lastUpdated = Date.now();
}
public getStats(): IndexStats {
let memoryUsage = 0;
memoryUsage += this._componentTypeToBit.size * 12;
memoryUsage += this._entityToBitmap.size * 12;
memoryUsage += this._bitToEntities.size * 64;
for (const entities of this._bitToEntities.values()) {
memoryUsage += entities.size * 8;
}
return {
type: this.type,
size: this._componentTypeToBit.size,
memoryUsage,
queryCount: this._queryCount,
avgQueryTime: this._queryCount > 0 ? this._totalQueryTime / this._queryCount : 0,
lastUpdated: this._lastUpdated
};
}
}
/**
* 智能组件索引管理器
*
* 根据使用模式自动选择最优的索引策略。
* 支持动态切换索引类型以获得最佳性能。
*/
export class ComponentIndexManager {
private _activeIndex: IComponentIndex;
private _indexHistory: Map<IndexType, IndexStats> = new Map();
private _autoOptimize = true;
private _optimizationThreshold = 1000;
constructor(initialType: IndexType = IndexType.HASH) {
this._activeIndex = this.createIndex(initialType);
}
/**
* 添加实体到索引
*/
public addEntity(entity: Entity): void {
this._activeIndex.addEntity(entity);
this.checkOptimization();
}
/**
* 从索引中移除实体
*/
public removeEntity(entity: Entity): void {
this._activeIndex.removeEntity(entity);
}
/**
* 查询包含指定组件的实体
*/
public query(componentType: ComponentType): Set<Entity> {
return this._activeIndex.query(componentType);
}
/**
* 批量查询多个组件
*/
public queryMultiple(componentTypes: ComponentType[], operation: 'AND' | 'OR'): Set<Entity> {
return this._activeIndex.queryMultiple(componentTypes, operation);
}
/**
* 手动切换索引类型
*/
public switchIndexType(type: IndexType): void {
if (type === this._activeIndex.type) return;
this._indexHistory.set(this._activeIndex.type, this._activeIndex.getStats());
const oldIndex = this._activeIndex;
this._activeIndex = this.createIndex(type);
oldIndex.clear();
}
/**
* 启用/禁用自动优化
*/
public setAutoOptimize(enabled: boolean): void {
this._autoOptimize = enabled;
}
/**
* 获取当前索引统计信息
*/
public getStats(): IndexStats {
return this._activeIndex.getStats();
}
/**
* 获取所有索引类型的历史统计信息
*/
public getAllStats(): Map<IndexType, IndexStats> {
const current = this._activeIndex.getStats();
return new Map([
...this._indexHistory,
[current.type, current]
]);
}
/**
* 清空索引
*/
public clear(): void {
this._activeIndex.clear();
}
/**
* 创建指定类型的索引
*/
private createIndex(type: IndexType): IComponentIndex {
switch (type) {
case IndexType.HASH:
return new HashComponentIndex();
case IndexType.BITMAP:
return new BitmapComponentIndex();
case IndexType.SORTED:
return new HashComponentIndex();
default:
return new HashComponentIndex();
}
}
/**
* 检查是否需要优化索引
*/
private checkOptimization(): void {
if (!this._autoOptimize) return;
const stats = this._activeIndex.getStats();
if (stats.queryCount < this._optimizationThreshold) return;
if (stats.avgQueryTime > 1.0 && stats.type !== IndexType.HASH) {
this.switchIndexType(IndexType.HASH);
} else if (stats.memoryUsage > 10 * 1024 * 1024 && stats.type !== IndexType.BITMAP) {
this.switchIndexType(IndexType.BITMAP);
}
}
}

View File

@@ -0,0 +1,375 @@
import { Entity } from '../Entity';
import { Component } from '../Component';
import { ComponentType } from './ComponentStorage';
/**
* 脏标记类型
*/
export enum DirtyFlag {
/** 组件数据已修改 */
COMPONENT_MODIFIED = 1 << 0,
/** 组件已添加 */
COMPONENT_ADDED = 1 << 1,
/** 组件已移除 */
COMPONENT_REMOVED = 1 << 2,
/** 实体位置已改变 */
TRANSFORM_CHANGED = 1 << 3,
/** 实体状态已改变 */
STATE_CHANGED = 1 << 4,
/** 自定义标记1 */
CUSTOM_1 = 1 << 8,
/** 自定义标记2 */
CUSTOM_2 = 1 << 9,
/** 自定义标记3 */
CUSTOM_3 = 1 << 10,
/** 所有标记 */
ALL = 0xFFFFFFFF
}
/**
* 脏标记数据
*/
export interface DirtyData {
/** 实体引用 */
entity: Entity;
/** 脏标记位 */
flags: number;
/** 修改的组件类型列表 */
modifiedComponents: Set<ComponentType>;
/** 标记时间戳 */
timestamp: number;
/** 帧编号 */
frameNumber: number;
}
/**
* 脏标记监听器
*/
export interface DirtyListener {
/** 感兴趣的标记类型 */
flags: number;
/** 回调函数 */
callback: (dirtyData: DirtyData) => void;
/** 监听器优先级(数字越小优先级越高) */
priority?: number;
}
/**
* 脏标记统计信息
*/
export interface DirtyStats {
/** 当前脏实体数量 */
dirtyEntityCount: number;
/** 总标记次数 */
totalMarkings: number;
/** 总清理次数 */
totalCleanups: number;
/** 监听器数量 */
listenerCount: number;
/** 平均每帧脏实体数量 */
avgDirtyPerFrame: number;
/** 内存使用量估算 */
estimatedMemoryUsage: number;
}
/**
* 脏标记追踪系统
*
* 提供高效的组件和实体变更追踪,避免不必要的计算和更新。
* 支持细粒度的脏标记和批量处理机制。
*
* @example
* ```typescript
* const dirtySystem = new DirtyTrackingSystem();
*
* // 标记实体的位置组件已修改
* dirtySystem.markDirty(entity, DirtyFlag.TRANSFORM_CHANGED, [PositionComponent]);
*
* // 监听位置变化
* dirtySystem.addListener({
* flags: DirtyFlag.TRANSFORM_CHANGED,
* callback: (data) => {
* console.log('Entity position changed:', data.entity.name);
* }
* });
*
* // 处理所有脏标记
* dirtySystem.processDirtyEntities();
* ```
*/
export class DirtyTrackingSystem {
/** 脏实体映射表 */
private _dirtyEntities = new Map<Entity, DirtyData>();
/** 脏标记监听器 */
private _listeners: DirtyListener[] = [];
/** 性能统计 */
private _stats = {
totalMarkings: 0,
totalCleanups: 0,
frameCount: 0,
totalDirtyPerFrame: 0
};
/** 当前帧编号 */
private _currentFrame = 0;
private _batchSize = 100;
private _maxProcessingTime = 16;
/** 延迟处理队列 */
private _processingQueue: DirtyData[] = [];
private _isProcessing = false;
/**
* 标记实体为脏状态
*
* @param entity 要标记的实体
* @param flags 脏标记位
* @param modifiedComponents 修改的组件类型列表
*/
public markDirty(entity: Entity, flags: DirtyFlag, modifiedComponents: ComponentType[] = []): void {
this._stats.totalMarkings++;
let dirtyData = this._dirtyEntities.get(entity);
if (!dirtyData) {
dirtyData = {
entity,
flags: 0,
modifiedComponents: new Set(),
timestamp: performance.now(),
frameNumber: this._currentFrame
};
this._dirtyEntities.set(entity, dirtyData);
}
dirtyData.flags |= flags;
dirtyData.timestamp = performance.now();
dirtyData.frameNumber = this._currentFrame;
for (const componentType of modifiedComponents) {
dirtyData.modifiedComponents.add(componentType);
}
this.notifyListeners(dirtyData, flags);
}
/**
* 检查实体是否有指定的脏标记
*
* @param entity 要检查的实体
* @param flags 要检查的标记位
* @returns 是否有指定的脏标记
*/
public isDirty(entity: Entity, flags: DirtyFlag = DirtyFlag.ALL): boolean {
const dirtyData = this._dirtyEntities.get(entity);
return dirtyData ? (dirtyData.flags & flags) !== 0 : false;
}
/**
* 清除实体的脏标记
*
* @param entity 要清除的实体
* @param flags 要清除的标记位,默认清除所有
*/
public clearDirty(entity: Entity, flags: DirtyFlag = DirtyFlag.ALL): void {
const dirtyData = this._dirtyEntities.get(entity);
if (!dirtyData) return;
if (flags === DirtyFlag.ALL) {
this._dirtyEntities.delete(entity);
} else {
dirtyData.flags &= ~flags;
if (dirtyData.flags === 0) {
this._dirtyEntities.delete(entity);
}
}
this._stats.totalCleanups++;
}
/**
* 获取所有脏实体
*
* @param flags 过滤标记位,只返回包含指定标记的实体
* @returns 脏实体数据数组
*/
public getDirtyEntities(flags: DirtyFlag = DirtyFlag.ALL): DirtyData[] {
const result: DirtyData[] = [];
for (const dirtyData of this._dirtyEntities.values()) {
if ((dirtyData.flags & flags) !== 0) {
result.push(dirtyData);
}
}
return result;
}
/**
* 批量处理脏实体
*
* 使用时间分片的方式处理脏实体,避免单帧卡顿
*/
public processDirtyEntities(): void {
if (this._isProcessing) return;
this._isProcessing = true;
const startTime = performance.now();
if (this._processingQueue.length === 0) {
this._processingQueue.push(...this._dirtyEntities.values());
}
let processed = 0;
while (this._processingQueue.length > 0 && processed < this._batchSize) {
const elapsed = performance.now() - startTime;
if (elapsed > this._maxProcessingTime) {
break;
}
const dirtyData = this._processingQueue.shift()!;
this.processEntity(dirtyData);
processed++;
}
if (this._processingQueue.length === 0) {
this._isProcessing = false;
this.onFrameEnd();
}
}
/**
* 添加脏标记监听器
*
* @param listener 监听器配置
*/
public addListener(listener: DirtyListener): void {
this._listeners.push(listener);
this._listeners.sort((a, b) => (a.priority || 100) - (b.priority || 100));
}
/**
* 移除脏标记监听器
*
* @param callback 要移除的回调函数
*/
public removeListener(callback: (dirtyData: DirtyData) => void): void {
const index = this._listeners.findIndex(l => l.callback === callback);
if (index !== -1) {
this._listeners.splice(index, 1);
}
}
/**
* 开始新的帧
*/
public beginFrame(): void {
this._currentFrame++;
}
/**
* 结束当前帧
*/
public endFrame(): void {
if (!this._isProcessing) {
this.processDirtyEntities();
}
}
/**
* 获取统计信息
*/
public getStats(): DirtyStats {
return {
dirtyEntityCount: this._dirtyEntities.size,
totalMarkings: this._stats.totalMarkings,
totalCleanups: this._stats.totalCleanups,
listenerCount: this._listeners.length,
avgDirtyPerFrame: this._stats.frameCount > 0 ?
this._stats.totalDirtyPerFrame / this._stats.frameCount : 0,
estimatedMemoryUsage: this.estimateMemoryUsage()
};
}
/**
* 清空所有脏标记和统计信息
*/
public clear(): void {
this._dirtyEntities.clear();
this._processingQueue.length = 0;
this._isProcessing = false;
this._stats = {
totalMarkings: 0,
totalCleanups: 0,
frameCount: 0,
totalDirtyPerFrame: 0
};
}
/**
* 配置批量处理参数
*
* @param batchSize 每次处理的最大实体数量
* @param maxProcessingTime 每帧最大处理时间(毫秒)
*/
public configureBatchProcessing(batchSize: number, maxProcessingTime: number): void {
this._batchSize = batchSize;
this._maxProcessingTime = maxProcessingTime;
}
/**
* 处理单个脏实体
*/
private processEntity(dirtyData: DirtyData): void {
for (const listener of this._listeners) {
if ((dirtyData.flags & listener.flags) !== 0) {
try {
listener.callback(dirtyData);
} catch (error) {
console.error('Dirty listener error:', error);
}
}
}
this.clearDirty(dirtyData.entity);
}
/**
* 通知监听器
*/
private notifyListeners(dirtyData: DirtyData, newFlags: DirtyFlag): void {
for (const listener of this._listeners) {
if ((newFlags & listener.flags) !== 0) {
try {
listener.callback(dirtyData);
} catch (error) {
console.error('Dirty listener notification error:', error);
}
}
}
}
/**
* 帧结束时的统计更新
*/
private onFrameEnd(): void {
this._stats.frameCount++;
this._stats.totalDirtyPerFrame += this._dirtyEntities.size;
}
/**
* 估算内存使用量
*/
private estimateMemoryUsage(): number {
let usage = 0;
usage += this._dirtyEntities.size * 100;
usage += this._listeners.length * 50;
usage += this._processingQueue.length * 8;
return usage;
}
}

View File

@@ -0,0 +1,674 @@
import { Entity } from '../Entity';
import { Component } from '../Component';
import { ComponentType } from './ComponentStorage';
import { IdentifierPool } from '../Utils/IdentifierPool';
import { ComponentIndexManager, IndexType } from './ComponentIndex';
import { ArchetypeSystem } from './ArchetypeSystem';
import { DirtyTrackingSystem, DirtyFlag } from './DirtyTrackingSystem';
import { EventBus } from './EventBus';
import { ECSEventType } from '../CoreEvents';
import { IEntityEventData, IComponentEventData } from '../../Types';
/**
* 实体查询构建器
*
* 提供流式API来构建复杂的实体查询条件。支持组件过滤、标签过滤、状态过滤和自定义条件。
*
* @example
* ```typescript
* const results = entityManager.query()
* .withAll(PositionComponent, HealthComponent)
* .without(VelocityComponent)
* .withTag(1)
* .active()
* .where(entity => entity.name.startsWith("Player"))
* .execute();
* ```
*/
export class EntityQueryBuilder {
/** 必须包含的组件类型 */
private _allComponents: ComponentType[] = [];
/** 至少包含一个的组件类型 */
private _anyComponents: ComponentType[] = [];
/** 不能包含的组件类型 */
private _withoutComponents: ComponentType[] = [];
/** 必须包含的标签 */
private _withTags: number[] = [];
/** 不能包含的标签 */
private _withoutTags: number[] = [];
/** 是否只查询激活状态的实体 */
private _activeOnly: boolean = false;
/** 是否只查询启用状态的实体 */
private _enabledOnly: boolean = false;
/** 自定义过滤条件 */
private _customPredicates: Array<(entity: Entity) => boolean> = [];
/**
* 创建查询构建器实例
* @param entityManager 实体管理器实例
*/
constructor(private entityManager: EntityManager) {}
/**
* 添加必须包含的组件条件
*
* 返回的实体必须包含所有指定的组件类型。
*
* @param componentTypes 组件类型列表
* @returns 查询构建器实例,支持链式调用
*/
public withAll(...componentTypes: ComponentType[]): EntityQueryBuilder {
this._allComponents.push(...componentTypes);
return this;
}
/**
* 添加至少包含一个的组件条件
*
* 返回的实体必须至少包含其中一个指定的组件类型。
*
* @param componentTypes 组件类型列表
* @returns 查询构建器实例,支持链式调用
*/
public withAny(...componentTypes: ComponentType[]): EntityQueryBuilder {
this._anyComponents.push(...componentTypes);
return this;
}
/**
* 添加不能包含的组件条件
*
* 返回的实体不能包含任何指定的组件类型。
*
* @param componentTypes 组件类型列表
* @returns 查询构建器实例,支持链式调用
*/
public without(...componentTypes: ComponentType[]): EntityQueryBuilder {
this._withoutComponents.push(...componentTypes);
return this;
}
/**
* 添加必须包含的标签条件
*
* 返回的实体必须具有指定的标签。
*
* @param tag 标签值
* @returns 查询构建器实例,支持链式调用
*/
public withTag(tag: number): EntityQueryBuilder {
this._withTags.push(tag);
return this;
}
/**
* 添加不能包含的标签条件
*
* 返回的实体不能具有指定的标签。
*
* @param tag 标签值
* @returns 查询构建器实例,支持链式调用
*/
public withoutTag(tag: number): EntityQueryBuilder {
this._withoutTags.push(tag);
return this;
}
/**
* 添加激活状态过滤条件
*
* 返回的实体必须处于激活状态active = true
*
* @returns 查询构建器实例,支持链式调用
*/
public active(): EntityQueryBuilder {
this._activeOnly = true;
return this;
}
/**
* 添加启用状态过滤条件
*
* 返回的实体必须处于启用状态enabled = true
*
* @returns 查询构建器实例,支持链式调用
*/
public enabled(): EntityQueryBuilder {
this._enabledOnly = true;
return this;
}
/**
* 添加自定义过滤条件
*
* 允许用户定义复杂的过滤逻辑。
*
* @param predicate 自定义过滤函数,接收实体作为参数,返回布尔值
* @returns 查询构建器实例,支持链式调用
*
* @example
* ```typescript
* .where(entity => entity.name.startsWith("Player"))
* .where(entity => entity.components.length > 5)
* ```
*/
public where(predicate: (entity: Entity) => boolean): EntityQueryBuilder {
this._customPredicates.push(predicate);
return this;
}
/**
* 执行查询并返回所有匹配的实体
*
* @returns 符合所有查询条件的实体数组
*/
public execute(): Entity[] {
let candidates: Entity[] = [];
if (this._allComponents.length > 0) {
const indexResult = this.entityManager.queryWithComponentIndex(this._allComponents, 'AND');
candidates = Array.from(indexResult);
} else if (this._anyComponents.length > 0) {
const indexResult = this.entityManager.queryWithComponentIndex(this._anyComponents, 'OR');
candidates = Array.from(indexResult);
} else {
candidates = this.entityManager.getAllEntities();
}
return candidates.filter(entity => this.matchesEntity(entity));
}
/**
* 执行查询并返回第一个匹配的实体
*
* @returns 第一个符合查询条件的实体如果没有找到则返回null
*/
public first(): Entity | null {
const entities = this.entityManager.getAllEntities();
return entities.find(entity => this.matchesEntity(entity)) || null;
}
/**
* 执行查询并返回匹配实体的数量
*
* @returns 符合查询条件的实体数量
*/
public count(): number {
const entities = this.entityManager.getAllEntities();
return entities.filter(entity => this.matchesEntity(entity)).length;
}
/**
* 对所有匹配的实体执行指定操作
*
* @param action 要执行的操作函数,接收匹配的实体作为参数
*/
public forEach(action: (entity: Entity) => void): void {
const entities = this.entityManager.getAllEntities();
entities.forEach(entity => {
if (this.matchesEntity(entity)) {
action(entity);
}
});
}
/**
* 检查实体是否匹配所有查询条件
*
* 按优先级顺序检查各种过滤条件一旦发现不匹配立即返回false。
*
* @param entity 要检查的实体
* @returns 实体是否匹配所有查询条件
*/
private matchesEntity(entity: Entity): boolean {
// 检查激活状态
if (this._activeOnly && !entity.active) {
return false;
}
// 检查启用状态
if (this._enabledOnly && !entity.enabled) {
return false;
}
// 检查必须包含的组件
if (this._allComponents.length > 0) {
for (const componentType of this._allComponents) {
if (!entity.hasComponent(componentType)) {
return false;
}
}
}
// 检查至少包含一个的组件
if (this._anyComponents.length > 0) {
let hasAny = false;
for (const componentType of this._anyComponents) {
if (entity.hasComponent(componentType)) {
hasAny = true;
break;
}
}
if (!hasAny) {
return false;
}
}
// 检查不能包含的组件
if (this._withoutComponents.length > 0) {
for (const componentType of this._withoutComponents) {
if (entity.hasComponent(componentType)) {
return false;
}
}
}
// 检查必须包含的标签
if (this._withTags.length > 0) {
if (!this._withTags.includes(entity.tag)) {
return false;
}
}
// 检查不能包含的标签
if (this._withoutTags.length > 0) {
if (this._withoutTags.includes(entity.tag)) {
return false;
}
}
// 检查自定义条件
if (this._customPredicates.length > 0) {
for (const predicate of this._customPredicates) {
if (!predicate(entity)) {
return false;
}
}
}
return true;
}
}
/**
* 实体管理器
*
* 提供统一的实体管理和查询机制,支持高效的实体操作。
* 包括实体的创建、销毁、查询和索引管理功能。
*
* @example
* ```typescript
* const entityManager = new EntityManager();
*
* // 创建实体
* const player = entityManager.createEntity("Player");
*
* // 查询实体
* const playerEntity = entityManager.getEntityByName("Player");
*
* // 复杂查询
* const results = entityManager.query()
* .withAll(HealthComponent, PositionComponent)
* .active()
* .execute();
* ```
*/
export class EntityManager {
/** 主要实体存储使用ID作为键 */
private _entities: Map<number, Entity> = new Map();
/** 按名称索引的实体映射 */
private _entitiesByName: Map<string, Entity[]> = new Map();
/** 按标签索引的实体映射 */
private _entitiesByTag: Map<number, Entity[]> = new Map();
/** 实体ID分配器 */
private _identifierPool: IdentifierPool;
/** 已销毁实体的ID集合 */
private _destroyedEntities: Set<number> = new Set();
/** 性能优化系统 */
private _componentIndexManager: ComponentIndexManager;
private _archetypeSystem: ArchetypeSystem;
private _dirtyTrackingSystem: DirtyTrackingSystem;
/** 事件总线 */
private _eventBus: EventBus;
/**
* 创建实体管理器实例
*
* 初始化内部数据结构和ID分配器。
*/
constructor() {
this._identifierPool = new IdentifierPool();
// 初始化性能优化系统
this._componentIndexManager = new ComponentIndexManager(IndexType.HASH);
this._archetypeSystem = new ArchetypeSystem();
this._dirtyTrackingSystem = new DirtyTrackingSystem();
this._eventBus = new EventBus(false);
// 设置Entity的静态事件总线引用
Entity.eventBus = this._eventBus;
}
/**
* 获取实体总数
*
* @returns 当前管理的实体总数量
*/
public get entityCount(): number {
return this._entities.size;
}
/**
* 获取激活状态的实体数量
*
* 只计算同时满足激活状态且未被销毁的实体。
*
* @returns 激活状态的实体数量
*/
public get activeEntityCount(): number {
let count = 0;
for (const entity of this._entities.values()) {
if (entity.active && !entity.isDestroyed) {
count++;
}
}
return count;
}
/**
* 创建新实体
*
* 分配唯一ID并将实体添加到管理系统中同时更新相关索引。
*
* @param name 实体名称,如果未指定则使用时间戳生成默认名称
* @returns 创建的实体实例
*
* @example
* ```typescript
* const player = entityManager.createEntity("Player");
* const enemy = entityManager.createEntity(); // 使用默认名称
* ```
*/
public createEntity(name: string = `Entity_${Date.now()}`): Entity {
const id = this._identifierPool.checkOut();
const entity = new Entity(name, id);
this._entities.set(id, entity);
this.updateNameIndex(entity, true);
this.updateTagIndex(entity, true);
this._componentIndexManager.addEntity(entity);
this._archetypeSystem.addEntity(entity);
this._dirtyTrackingSystem.markDirty(entity, DirtyFlag.COMPONENT_ADDED);
// 发射实体创建事件
this._eventBus.emitEntityCreated({
timestamp: Date.now(),
source: 'EntityManager',
entityId: entity.id,
entityName: entity.name,
entityTag: entity.tag?.toString()
});
return entity;
}
/**
* 销毁实体
*
* 支持通过实体对象、名称或ID来销毁实体。
* 会清理所有相关索引并回收ID。
*
* @param entityOrId 要销毁的实体可以是实体对象、名称字符串或ID数字
* @returns 是否成功销毁实体
*
* @example
* ```typescript
* // 通过实体对象销毁
* entityManager.destroyEntity(player);
*
* // 通过名称销毁
* entityManager.destroyEntity("Enemy_1");
*
* // 通过ID销毁
* entityManager.destroyEntity(123);
* ```
*/
public destroyEntity(entityOrId: Entity | string | number): boolean {
let entity: Entity | null = null;
if (typeof entityOrId === 'string') {
entity = this.getEntityByName(entityOrId);
} else if (typeof entityOrId === 'number') {
entity = this._entities.get(entityOrId) || null;
} else {
entity = this._entities.get(entityOrId.id) || null;
}
if (!entity) {
return false;
}
this._destroyedEntities.add(entity.id);
this.updateNameIndex(entity, false);
this.updateTagIndex(entity, false);
this._componentIndexManager.removeEntity(entity);
this._archetypeSystem.removeEntity(entity);
this._dirtyTrackingSystem.markDirty(entity, DirtyFlag.COMPONENT_REMOVED);
// 发射实体销毁事件
this._eventBus.emitEntityDestroyed({
timestamp: Date.now(),
source: 'EntityManager',
entityId: entity.id,
entityName: entity.name,
entityTag: entity.tag?.toString()
});
entity.destroy();
this._entities.delete(entity.id);
this._identifierPool.checkIn(entity.id);
return true;
}
/**
* 获取所有实体
*
* 返回当前管理的所有实体的副本数组。
*
* @returns 所有实体的数组
*/
public getAllEntities(): Entity[] {
return Array.from(this._entities.values());
}
/**
* 根据ID获取实体
*
* 支持字符串和数字类型的ID。
*
* @param id 实体ID可以是字符串或数字
* @returns 对应的实体如果不存在则返回null
*/
public getEntity(id: string | number): Entity | null {
const numId = typeof id === 'string' ? parseInt(id) : id;
return this._entities.get(numId) || null;
}
/**
* 根据名称获取实体
*
* 如果存在多个同名实体,返回第一个找到的实体。
*
* @param name 实体名称
* @returns 匹配的实体如果不存在则返回null
*/
public getEntityByName(name: string): Entity | null {
const entities = this._entitiesByName.get(name);
return entities && entities.length > 0 ? entities[0] : null;
}
/**
* 根据标签获取实体列表
*
* 返回所有具有指定标签的实体。
*
* @param tag 标签值
* @returns 具有指定标签的实体数组
*/
public getEntitiesByTag(tag: number): Entity[] {
return [...(this._entitiesByTag.get(tag) || [])];
}
/**
* 获取包含指定组件的所有实体
*
* 遍历所有实体,查找包含指定组件类型的实体。
*
* @param componentType 组件类型
* @returns 包含指定组件的实体数组
*
* @example
* ```typescript
* const entitiesWithHealth = entityManager.getEntitiesWithComponent(HealthComponent);
* ```
*/
public getEntitiesWithComponent<T extends Component>(componentType: ComponentType<T>): Entity[] {
const indexResult = this._componentIndexManager.query(componentType);
return Array.from(indexResult);
}
/**
* 创建查询构建器
*
* 返回一个新的查询构建器实例,用于构建复杂的实体查询。
*
* @returns 新的查询构建器实例
*
* @example
* ```typescript
* const results = entityManager.query()
* .withAll(PositionComponent, HealthComponent)
* .without(VelocityComponent)
* .active()
* .execute();
* ```
*/
public query(): EntityQueryBuilder {
return new EntityQueryBuilder(this);
}
/**
* 使用组件索引进行多组件查询
*
* @param componentTypes 组件类型数组
* @param operation 查询操作:'AND' 或 'OR'
* @returns 匹配的实体集合
*/
public queryWithComponentIndex(componentTypes: ComponentType[], operation: 'AND' | 'OR'): Set<Entity> {
return this._componentIndexManager.queryMultiple(componentTypes, operation);
}
/**
* 标记实体组件已修改
*
* @param entity 修改的实体
* @param componentTypes 修改的组件类型
*/
public markEntityDirty(entity: Entity, componentTypes: ComponentType[]): void {
this._dirtyTrackingSystem.markDirty(entity, DirtyFlag.COMPONENT_MODIFIED, componentTypes);
}
/**
* 获取性能优化统计信息
*/
public getOptimizationStats(): any {
return {
componentIndex: this._componentIndexManager.getStats(),
archetypeSystem: this._archetypeSystem.getAllArchetypes().map(a => ({
id: a.id,
componentTypes: a.componentTypes.map(t => t.name),
entityCount: a.entities.length
})),
dirtyTracking: this._dirtyTrackingSystem.getStats()
};
}
/**
* 获取事件总线实例
*
* 允许外部代码监听和发射ECS相关事件。
*
* @returns 事件总线实例
*/
public get eventBus(): EventBus {
return this._eventBus;
}
/**
* 更新名称索引
*
* 维护按名称查找实体的索引结构。支持添加和移除操作。
*
* @param entity 要更新索引的实体
* @param isAdd true表示添加到索引false表示从索引中移除
*/
private updateNameIndex(entity: Entity, isAdd: boolean): void {
if (!entity.name) {
return;
}
if (isAdd) {
let entities = this._entitiesByName.get(entity.name);
if (!entities) {
entities = [];
this._entitiesByName.set(entity.name, entities);
}
entities.push(entity);
} else {
const entities = this._entitiesByName.get(entity.name);
if (entities) {
const index = entities.indexOf(entity);
if (index !== -1) {
entities.splice(index, 1);
if (entities.length === 0) {
this._entitiesByName.delete(entity.name);
}
}
}
}
}
/**
* 更新标签索引
*
* 维护按标签查找实体的索引结构。支持添加和移除操作。
*
* @param entity 要更新索引的实体
* @param isAdd true表示添加到索引false表示从索引中移除
*/
private updateTagIndex(entity: Entity, isAdd: boolean): void {
if (isAdd) {
let entities = this._entitiesByTag.get(entity.tag);
if (!entities) {
entities = [];
this._entitiesByTag.set(entity.tag, entities);
}
entities.push(entity);
} else {
const entities = this._entitiesByTag.get(entity.tag);
if (entities) {
const index = entities.indexOf(entity);
if (index !== -1) {
entities.splice(index, 1);
if (entities.length === 0) {
this._entitiesByTag.delete(entity.tag);
}
}
}
}
}
}

View File

@@ -0,0 +1,497 @@
import {
IEventBus,
IEventListenerConfig,
IEventStats,
IEventData,
IEntityEventData,
IComponentEventData,
ISystemEventData,
ISceneEventData,
IPerformanceEventData
} from '../../Types';
import {
TypeSafeEventSystem,
EventListenerConfig,
EventStats
} from './EventSystem';
import {
ECSEventType,
EventPriority,
EVENT_TYPES,
EventTypeValidator
} from '../CoreEvents';
/**
* 增强的事件总线实现
* 基于TypeSafeEventSystem提供类型安全的事件发布订阅机制
*/
export class EventBus implements IEventBus {
private eventSystem: TypeSafeEventSystem;
private eventIdCounter = 0;
private isDebugMode = false;
constructor(debugMode: boolean = false) {
this.eventSystem = new TypeSafeEventSystem();
this.isDebugMode = debugMode;
}
/**
* 发射事件
* @param eventType 事件类型
* @param data 事件数据
*/
public emit<T>(eventType: string, data: T): void {
this.validateEventType(eventType);
// 增强事件数据
const enhancedData = this.enhanceEventData(eventType, data);
if (this.isDebugMode) {
console.log(`[EventBus] Emitting event: ${eventType}`, enhancedData);
}
this.eventSystem.emitSync(eventType, enhancedData);
}
/**
* 异步发射事件
* @param eventType 事件类型
* @param data 事件数据
*/
public async emitAsync<T>(eventType: string, data: T): Promise<void> {
this.validateEventType(eventType);
// 增强事件数据
const enhancedData = this.enhanceEventData(eventType, data);
if (this.isDebugMode) {
console.log(`[EventBus] Emitting async event: ${eventType}`, enhancedData);
}
await this.eventSystem.emit(eventType, enhancedData);
}
/**
* 监听事件
* @param eventType 事件类型
* @param handler 事件处理器
* @param config 监听器配置
* @returns 监听器ID
*/
public on<T>(
eventType: string,
handler: (data: T) => void,
config: IEventListenerConfig = {}
): string {
this.validateEventType(eventType);
const eventConfig: EventListenerConfig = {
once: config.once || false,
priority: config.priority || EventPriority.NORMAL,
async: config.async || false,
context: config.context
};
if (this.isDebugMode) {
console.log(`[EventBus] Adding listener for: ${eventType}`, eventConfig);
}
return this.eventSystem.on(eventType, handler, eventConfig);
}
/**
* 监听事件(一次性)
* @param eventType 事件类型
* @param handler 事件处理器
* @param config 监听器配置
* @returns 监听器ID
*/
public once<T>(
eventType: string,
handler: (data: T) => void,
config: IEventListenerConfig = {}
): string {
return this.on(eventType, handler, { ...config, once: true });
}
/**
* 异步监听事件
* @param eventType 事件类型
* @param handler 异步事件处理器
* @param config 监听器配置
* @returns 监听器ID
*/
public onAsync<T>(
eventType: string,
handler: (data: T) => Promise<void>,
config: IEventListenerConfig = {}
): string {
return this.on(eventType, handler as any, { ...config, async: true });
}
/**
* 移除事件监听器
* @param eventType 事件类型
* @param listenerId 监听器ID
*/
public off(eventType: string, listenerId: string): boolean {
if (this.isDebugMode) {
console.log(`[EventBus] Removing listener: ${listenerId} for event: ${eventType}`);
}
return this.eventSystem.off(eventType, listenerId);
}
/**
* 移除指定事件类型的所有监听器
* @param eventType 事件类型
*/
public offAll(eventType: string): void {
if (this.isDebugMode) {
console.log(`[EventBus] Removing all listeners for event: ${eventType}`);
}
this.eventSystem.offAll(eventType);
}
/**
* 检查是否有指定事件的监听器
* @param eventType 事件类型
*/
public hasListeners(eventType: string): boolean {
return this.eventSystem.hasListeners(eventType);
}
/**
* 获取事件统计信息
* @param eventType 事件类型(可选)
*/
public getStats(eventType?: string): IEventStats | Map<string, IEventStats> {
const stats = this.eventSystem.getStats(eventType);
if (stats instanceof Map) {
// 转换Map中的每个EventStats为IEventStats
const result = new Map<string, IEventStats>();
stats.forEach((stat, key) => {
result.set(key, this.convertEventStats(stat));
});
return result;
} else {
return this.convertEventStats(stats);
}
}
/**
* 清空所有监听器
*/
public clear(): void {
if (this.isDebugMode) {
console.log('[EventBus] Clearing all listeners');
}
this.eventSystem.clear();
}
/**
* 启用或禁用事件系统
* @param enabled 是否启用
*/
public setEnabled(enabled: boolean): void {
this.eventSystem.setEnabled(enabled);
}
/**
* 设置调试模式
* @param debug 是否启用调试
*/
public setDebugMode(debug: boolean): void {
this.isDebugMode = debug;
}
/**
* 设置最大监听器数量
* @param max 最大数量
*/
public setMaxListeners(max: number): void {
this.eventSystem.setMaxListeners(max);
}
/**
* 获取监听器数量
* @param eventType 事件类型
*/
public getListenerCount(eventType: string): number {
return this.eventSystem.getListenerCount(eventType);
}
/**
* 设置事件批处理配置
* @param eventType 事件类型
* @param batchSize 批处理大小
* @param delay 延迟时间(毫秒)
*/
public setBatchConfig(eventType: string, batchSize: number, delay: number): void {
this.eventSystem.setBatchConfig(eventType, {
batchSize,
delay,
enabled: true
});
}
/**
* 刷新指定事件的批处理队列
* @param eventType 事件类型
*/
public flushBatch(eventType: string): void {
this.eventSystem.flushBatch(eventType);
}
/**
* 重置事件统计
* @param eventType 事件类型(可选)
*/
public resetStats(eventType?: string): void {
this.eventSystem.resetStats(eventType);
}
// 便捷方法发射预定义的ECS事件
/**
* 发射实体创建事件
* @param entityData 实体事件数据
*/
public emitEntityCreated(entityData: IEntityEventData): void {
this.emit(ECSEventType.ENTITY_CREATED, entityData);
}
/**
* 发射实体销毁事件
* @param entityData 实体事件数据
*/
public emitEntityDestroyed(entityData: IEntityEventData): void {
this.emit(ECSEventType.ENTITY_DESTROYED, entityData);
}
/**
* 发射组件添加事件
* @param componentData 组件事件数据
*/
public emitComponentAdded(componentData: IComponentEventData): void {
this.emit(ECSEventType.COMPONENT_ADDED, componentData);
}
/**
* 发射组件移除事件
* @param componentData 组件事件数据
*/
public emitComponentRemoved(componentData: IComponentEventData): void {
this.emit(ECSEventType.COMPONENT_REMOVED, componentData);
}
/**
* 发射系统添加事件
* @param systemData 系统事件数据
*/
public emitSystemAdded(systemData: ISystemEventData): void {
this.emit(ECSEventType.SYSTEM_ADDED, systemData);
}
/**
* 发射系统移除事件
* @param systemData 系统事件数据
*/
public emitSystemRemoved(systemData: ISystemEventData): void {
this.emit(ECSEventType.SYSTEM_REMOVED, systemData);
}
/**
* 发射场景变化事件
* @param sceneData 场景事件数据
*/
public emitSceneChanged(sceneData: ISceneEventData): void {
this.emit(EVENT_TYPES.CORE.SCENE_CHANGED, sceneData);
}
/**
* 发射性能警告事件
* @param performanceData 性能事件数据
*/
public emitPerformanceWarning(performanceData: IPerformanceEventData): void {
this.emit(ECSEventType.PERFORMANCE_WARNING, performanceData);
}
// 便捷方法监听预定义的ECS事件
/**
* 监听实体创建事件
* @param handler 事件处理器
* @param config 监听器配置
*/
public onEntityCreated(
handler: (data: IEntityEventData) => void,
config?: IEventListenerConfig
): string {
return this.on(ECSEventType.ENTITY_CREATED, handler, config);
}
/**
* 监听组件添加事件
* @param handler 事件处理器
* @param config 监听器配置
*/
public onComponentAdded(
handler: (data: IComponentEventData) => void,
config?: IEventListenerConfig
): string {
return this.on(ECSEventType.COMPONENT_ADDED, handler, config);
}
/**
* 监听系统错误事件
* @param handler 事件处理器
* @param config 监听器配置
*/
public onSystemError(
handler: (data: ISystemEventData) => void,
config?: IEventListenerConfig
): string {
return this.on(ECSEventType.SYSTEM_ERROR, handler, config);
}
/**
* 监听性能警告事件
* @param handler 事件处理器
* @param config 监听器配置
*/
public onPerformanceWarning(
handler: (data: IPerformanceEventData) => void,
config?: IEventListenerConfig
): string {
return this.on(ECSEventType.PERFORMANCE_WARNING, handler, config);
}
// 私有方法
/**
* 验证事件类型
* @param eventType 事件类型
*/
private validateEventType(eventType: string): void {
if (!EventTypeValidator.isValid(eventType)) {
if (this.isDebugMode) {
console.warn(`[EventBus] Unknown event type: ${eventType}`);
}
// 在调试模式下添加自定义事件类型
if (this.isDebugMode) {
EventTypeValidator.addCustomType(eventType);
}
}
}
/**
* 增强事件数据
* @param eventType 事件类型
* @param data 原始数据
*/
private enhanceEventData<T>(eventType: string, data: T): T & IEventData {
const enhanced = data as T & IEventData;
// 如果数据还没有基础事件属性,添加它们
if (!enhanced.timestamp) {
enhanced.timestamp = Date.now();
}
if (!enhanced.eventId) {
enhanced.eventId = `${eventType}_${++this.eventIdCounter}`;
}
if (!enhanced.source) {
enhanced.source = 'EventBus';
}
return enhanced;
}
/**
* 转换EventStats为IEventStats
* @param stats EventStats实例
*/
private convertEventStats(stats: EventStats): IEventStats {
return {
eventType: stats.eventType,
listenerCount: stats.listenerCount,
triggerCount: stats.triggerCount,
totalExecutionTime: stats.totalExecutionTime,
averageExecutionTime: stats.averageExecutionTime,
lastTriggerTime: stats.lastTriggerTime
};
}
}
/**
* 全局事件总线实例
* 提供全局访问的事件总线
*/
export class GlobalEventBus {
private static instance: EventBus;
/**
* 获取全局事件总线实例
* @param debugMode 是否启用调试模式
*/
public static getInstance(debugMode: boolean = false): EventBus {
if (!this.instance) {
this.instance = new EventBus(debugMode);
}
return this.instance;
}
/**
* 重置全局事件总线实例
* @param debugMode 是否启用调试模式
*/
public static reset(debugMode: boolean = false): EventBus {
if (this.instance) {
this.instance.clear();
}
this.instance = new EventBus(debugMode);
return this.instance;
}
}
/**
* 事件装饰器工厂
* 用于自动注册事件监听器
*/
export function EventHandler(eventType: string, config: IEventListenerConfig = {}) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
// 在类实例化时自动注册监听器
const initMethod = target.constructor.prototype.initEventListeners || function() {};
target.constructor.prototype.initEventListeners = function() {
initMethod.call(this);
const eventBus = GlobalEventBus.getInstance();
eventBus.on(eventType, originalMethod.bind(this), config);
};
return descriptor;
};
}
/**
* 异步事件装饰器工厂
* 用于自动注册异步事件监听器
*/
export function AsyncEventHandler(eventType: string, config: IEventListenerConfig = {}) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
const initMethod = target.constructor.prototype.initEventListeners || function() {};
target.constructor.prototype.initEventListeners = function() {
initMethod.call(this);
const eventBus = GlobalEventBus.getInstance();
eventBus.onAsync(eventType, originalMethod.bind(this), config);
};
return descriptor;
};
}

View File

@@ -0,0 +1 @@