diff --git a/source/src/ECS/Component.ts b/source/src/ECS/Component.ts index f247d2cd..690c4f1a 100644 --- a/source/src/ECS/Component.ts +++ b/source/src/ECS/Component.ts @@ -1,3 +1,5 @@ +import type { IComponent } from '../Types'; + /** * 游戏组件基类 * @@ -18,7 +20,7 @@ * } * ``` */ -export abstract class Component { +export abstract class Component implements IComponent { /** * 组件ID生成器 * diff --git a/source/src/ECS/Core/QuerySystem.ts b/source/src/ECS/Core/QuerySystem.ts index 9e2e20f6..0ecfb220 100644 --- a/source/src/ECS/Core/QuerySystem.ts +++ b/source/src/ECS/Core/QuerySystem.ts @@ -5,6 +5,9 @@ import { ecsCore } from '../../Utils/WasmCore'; import { ComponentPoolManager } from './ComponentPool'; import { BitMaskOptimizer } from './BitMaskOptimizer'; import { IndexUpdateBatcher } from './IndexUpdateBatcher'; +import { ComponentIndexManager, IndexType } from './ComponentIndex'; +import { ArchetypeSystem, Archetype, ArchetypeQueryResult } from './ArchetypeSystem'; +import { DirtyTrackingSystem, DirtyFlag } from './DirtyTrackingSystem'; /** * 查询条件类型 @@ -84,23 +87,30 @@ export class QuerySystem { private wasmAvailable = false; private entityIndex: EntityIndex; private indexDirty = true; - + // 查询缓存系统 private queryCache = new Map(); private cacheMaxSize = 1000; private cacheTimeout = 5000; // 5秒缓存过期 - + // 优化组件 private componentPoolManager: ComponentPoolManager; private bitMaskOptimizer: BitMaskOptimizer; private indexUpdateBatcher: IndexUpdateBatcher; - + + // 新增性能优化系统 + private componentIndexManager: ComponentIndexManager; + private archetypeSystem: ArchetypeSystem; + private dirtyTrackingSystem: DirtyTrackingSystem; + // 性能统计 private queryStats = { totalQueries: 0, cacheHits: 0, indexHits: 0, - linearScans: 0 + linearScans: 0, + archetypeHits: 0, + dirtyChecks: 0 }; constructor() { @@ -110,32 +120,37 @@ export class QuerySystem { byTag: new Map(), byName: new Map() }; - + // 初始化优化组件 this.componentPoolManager = ComponentPoolManager.getInstance(); this.bitMaskOptimizer = BitMaskOptimizer.getInstance(); this.indexUpdateBatcher = new IndexUpdateBatcher(); - + + // 初始化新的性能优化系统 + this.componentIndexManager = new ComponentIndexManager(IndexType.HASH); + this.archetypeSystem = new ArchetypeSystem(); + this.dirtyTrackingSystem = new DirtyTrackingSystem(); + // 设置索引更新批处理器的回调 this.indexUpdateBatcher.onBatchAdd = (entities) => { for (const entity of entities) { this.addEntityToIndexes(entity); } }; - + this.indexUpdateBatcher.onBatchRemove = (entities) => { for (const entity of entities) { this.removeEntityFromIndexes(entity); } }; - + this.indexUpdateBatcher.onBatchUpdate = (updates) => { for (const update of updates) { this.removeEntityFromIndexes(update.entity); this.addEntityToIndexes(update.entity); } }; - + this.initializeWasm(); } @@ -149,7 +164,7 @@ export class QuerySystem { try { const wasmLoaded = await ecsCore.initialize(); this.wasmAvailable = wasmLoaded && ecsCore.isUsingWasm(); - + if (this.wasmAvailable) { console.log('QuerySystem: WebAssembly计算加速已启用'); } else { @@ -188,7 +203,11 @@ export class QuerySystem { if (!this.entities.includes(entity)) { this.entities.push(entity); this.addEntityToIndexes(entity); - + + this.componentIndexManager.addEntity(entity); + this.archetypeSystem.addEntity(entity); + this.dirtyTrackingSystem.markDirty(entity, DirtyFlag.COMPONENT_ADDED); + // 只有在非延迟模式下才立即清理缓存 if (!deferCacheClear) { this.clearQueryCache(); @@ -206,11 +225,11 @@ export class QuerySystem { */ public addEntities(entities: Entity[]): void { if (entities.length === 0) return; - + // 使用Set来快速检查重复 const existingIds = new Set(this.entities.map(e => e.id)); let addedCount = 0; - + for (const entity of entities) { if (!existingIds.has(entity.id)) { this.entities.push(entity); @@ -219,7 +238,7 @@ export class QuerySystem { addedCount++; } } - + // 只在有实体被添加时才清理缓存 if (addedCount > 0) { this.clearQueryCache(); @@ -236,17 +255,17 @@ export class QuerySystem { */ public addEntitiesUnchecked(entities: Entity[]): void { if (entities.length === 0) return; - + // 避免调用栈溢出,分批添加 for (const entity of entities) { this.entities.push(entity); } - + // 批量更新索引 for (const entity of entities) { this.addEntityToIndexes(entity); } - + // 清理缓存 this.clearQueryCache(); } @@ -263,6 +282,11 @@ export class QuerySystem { if (index !== -1) { this.entities.splice(index, 1); this.removeEntityFromIndexes(entity); + + this.componentIndexManager.removeEntity(entity); + this.archetypeSystem.removeEntity(entity); + this.dirtyTrackingSystem.markDirty(entity, DirtyFlag.COMPONENT_REMOVED); + this.clearQueryCache(); } } @@ -272,7 +296,7 @@ export class QuerySystem { */ private addEntityToIndexes(entity: Entity): void { const mask = entity.componentMask; - + // 组件掩码索引 - 优化Map操作 let maskSet = this.entityIndex.byMask.get(mask); if (!maskSet) { @@ -280,7 +304,7 @@ export class QuerySystem { this.entityIndex.byMask.set(mask, maskSet); } maskSet.add(entity); - + // 组件类型索引 - 批量处理 const components = entity.components; for (let i = 0; i < components.length; i++) { @@ -292,7 +316,7 @@ export class QuerySystem { } typeSet.add(entity); } - + // 标签索引 - 只在有标签时处理 const tag = entity.tag; if (tag !== undefined) { @@ -303,7 +327,7 @@ export class QuerySystem { } tagSet.add(entity); } - + // 名称索引 - 只在有名称时处理 const name = entity.name; if (name) { @@ -321,7 +345,7 @@ export class QuerySystem { */ private removeEntityFromIndexes(entity: Entity): void { const mask = entity.componentMask; - + // 从组件掩码索引移除 const maskSet = this.entityIndex.byMask.get(mask); if (maskSet) { @@ -330,7 +354,7 @@ export class QuerySystem { this.entityIndex.byMask.delete(mask); } } - + // 从组件类型索引移除 for (const component of entity.components) { const componentType = component.constructor as ComponentType; @@ -342,7 +366,7 @@ export class QuerySystem { } } } - + // 从标签索引移除 if (entity.tag !== undefined) { const tagSet = this.entityIndex.byTag.get(entity.tag); @@ -353,7 +377,7 @@ export class QuerySystem { } } } - + // 从名称索引移除 if (entity.name) { const nameSet = this.entityIndex.byName.get(entity.name); @@ -377,11 +401,11 @@ export class QuerySystem { this.entityIndex.byComponentType.clear(); this.entityIndex.byTag.clear(); this.entityIndex.byName.clear(); - + for (const entity of this.entities) { this.addEntityToIndexes(entity); } - + this.indexDirty = false; } @@ -404,10 +428,10 @@ export class QuerySystem { public queryAll(...componentTypes: ComponentType[]): QueryResult { const startTime = performance.now(); this.queryStats.totalQueries++; - + // 生成缓存键 const cacheKey = `all:${componentTypes.map(t => t.name).sort().join(',')}`; - + // 检查缓存 const cached = this.getFromCache(cacheKey); if (cached) { @@ -419,21 +443,28 @@ export class QuerySystem { fromCache: true }; } - + let entities: Entity[]; - - // 单组件查询:直接使用索引 - if (componentTypes.length === 1) { + + const archetypeResult = this.archetypeSystem.queryArchetypes(componentTypes, 'AND'); + if (archetypeResult.archetypes.length > 0) { + this.queryStats.archetypeHits++; + entities = []; + for (const archetype of archetypeResult.archetypes) { + entities.push(...archetype.entities); + } + } else if (componentTypes.length === 1) { this.queryStats.indexHits++; - entities = Array.from(this.entityIndex.byComponentType.get(componentTypes[0]) || []); + const indexResult = this.componentIndexManager.query(componentTypes[0]); + entities = Array.from(indexResult); } else { - // 多组件查询:使用高效算法 - entities = this.queryMultipleComponents(componentTypes); + const indexResult = this.componentIndexManager.queryMultiple(componentTypes, 'AND'); + entities = Array.from(indexResult); } - + // 缓存结果 this.addToCache(cacheKey, entities); - + return { entities, count: entities.length, @@ -455,7 +486,7 @@ export class QuerySystem { // 找到最小的组件集合作为起点 let smallestSet: Set | null = null; let smallestSize = Infinity; - + for (const componentType of componentTypes) { const set = this.entityIndex.byComponentType.get(componentType); if (!set || set.size === 0) { @@ -466,22 +497,22 @@ export class QuerySystem { smallestSet = set; } } - + if (!smallestSet) { this.queryStats.linearScans++; return this.queryByLinearScan(componentTypes); } - + // 从最小集合开始,逐步过滤 const mask = this.createComponentMask(componentTypes); const result: Entity[] = []; - + for (const entity of smallestSet) { if ((entity.componentMask & mask) === mask) { result.push(entity); } } - + return result; } @@ -496,7 +527,7 @@ export class QuerySystem { */ private queryByLinearScan(componentTypes: ComponentType[]): Entity[] { const mask = this.createComponentMask(componentTypes); - return this.entities.filter(entity => + return this.entities.filter(entity => (entity.componentMask & mask) === mask ); } @@ -520,9 +551,9 @@ export class QuerySystem { public queryAny(...componentTypes: ComponentType[]): QueryResult { const startTime = performance.now(); this.queryStats.totalQueries++; - + const cacheKey = `any:${componentTypes.map(t => t.name).sort().join(',')}`; - + // 检查缓存 const cached = this.getFromCache(cacheKey); if (cached) { @@ -534,21 +565,22 @@ export class QuerySystem { fromCache: true }; } - - // 使用集合合并 - const entitySet = new Set(); - for (const componentType of componentTypes) { - const typeEntities = this.entityIndex.byComponentType.get(componentType); - if (typeEntities) { - for (const entity of typeEntities) { - entitySet.add(entity); - } + + const archetypeResult = this.archetypeSystem.queryArchetypes(componentTypes, 'OR'); + let entities: Entity[]; + + if (archetypeResult.archetypes.length > 0) { + this.queryStats.archetypeHits++; + entities = []; + for (const archetype of archetypeResult.archetypes) { + entities.push(...archetype.entities); } + } else { + const indexResult = this.componentIndexManager.queryMultiple(componentTypes, 'OR'); + entities = Array.from(indexResult); } - - const entities = Array.from(entitySet); this.addToCache(cacheKey, entities); - + return { entities, count: entities.length, @@ -576,9 +608,9 @@ export class QuerySystem { public queryNone(...componentTypes: ComponentType[]): QueryResult { const startTime = performance.now(); this.queryStats.totalQueries++; - + const cacheKey = `none:${componentTypes.map(t => t.name).sort().join(',')}`; - + // 检查缓存 const cached = this.getFromCache(cacheKey); if (cached) { @@ -590,14 +622,14 @@ export class QuerySystem { fromCache: true }; } - + const mask = this.createComponentMask(componentTypes); - const entities = this.entities.filter(entity => + const entities = this.entities.filter(entity => (entity.componentMask & mask) === BigInt(0) ); - + this.addToCache(cacheKey, entities); - + return { entities, count: entities.length, @@ -624,9 +656,9 @@ export class QuerySystem { public queryByTag(tag: number): QueryResult { const startTime = performance.now(); this.queryStats.totalQueries++; - + const cacheKey = `tag:${tag}`; - + // 检查缓存 const cached = this.getFromCache(cacheKey); if (cached) { @@ -638,14 +670,14 @@ export class QuerySystem { fromCache: true }; } - + // 使用索引查询 this.queryStats.indexHits++; const entities = Array.from(this.entityIndex.byTag.get(tag) || []); - + // 缓存结果 this.addToCache(cacheKey, entities); - + return { entities, count: entities.length, @@ -672,9 +704,9 @@ export class QuerySystem { public queryByName(name: string): QueryResult { const startTime = performance.now(); this.queryStats.totalQueries++; - + const cacheKey = `name:${name}`; - + // 检查缓存 const cached = this.getFromCache(cacheKey); if (cached) { @@ -686,14 +718,14 @@ export class QuerySystem { fromCache: true }; } - + // 使用索引查询 this.queryStats.indexHits++; const entities = Array.from(this.entityIndex.byName.get(name) || []); - + // 缓存结果 this.addToCache(cacheKey, entities); - + return { entities, count: entities.length, @@ -720,9 +752,9 @@ export class QuerySystem { public queryByComponent(componentType: ComponentType): QueryResult { const startTime = performance.now(); this.queryStats.totalQueries++; - + const cacheKey = `component:${componentType.name}`; - + // 检查缓存 const cached = this.getFromCache(cacheKey); if (cached) { @@ -734,14 +766,14 @@ export class QuerySystem { fromCache: true }; } - + // 使用索引查询 this.queryStats.indexHits++; const entities = Array.from(this.entityIndex.byComponentType.get(componentType) || []); - + // 缓存结果 this.addToCache(cacheKey, entities); - + return { entities, count: entities.length, @@ -756,13 +788,13 @@ export class QuerySystem { private getFromCache(cacheKey: string): Entity[] | null { const entry = this.queryCache.get(cacheKey); if (!entry) return null; - + // 检查缓存是否过期 if (Date.now() - entry.timestamp > this.cacheTimeout) { this.queryCache.delete(cacheKey); return null; } - + entry.hitCount++; return entry.entities; } @@ -775,7 +807,7 @@ export class QuerySystem { if (this.queryCache.size >= this.cacheMaxSize) { this.cleanupCache(); } - + this.queryCache.set(cacheKey, { entities: [...entities], // 复制数组避免引用问题 timestamp: Date.now(), @@ -794,12 +826,12 @@ export class QuerySystem { this.queryCache.delete(key); } } - + // 如果还是太满,移除最少使用的条目 if (this.queryCache.size >= this.cacheMaxSize) { const entries = Array.from(this.queryCache.entries()); entries.sort((a, b) => a[1].hitCount - b[1].hitCount); - + const toRemove = Math.floor(this.cacheMaxSize * 0.2); // 移除20% for (let i = 0; i < toRemove && i < entries.length; i++) { this.queryCache.delete(entries[i][0]); @@ -841,7 +873,7 @@ export class QuerySystem { * querySystem.batchUpdateComponents(updates); * ``` */ - public batchUpdateComponents(updates: Array<{entityId: number, componentMask: bigint}>): void { + public batchUpdateComponents(updates: Array<{ entityId: number, componentMask: bigint }>): void { if (this.wasmAvailable && updates.length > 100) { try { const entityIds = updates.map(u => u.entityId); @@ -855,7 +887,7 @@ export class QuerySystem { } else { this.batchUpdateComponentsJS(updates); } - + // 批量更新后清除缓存 this.clearQueryCache(); } @@ -863,7 +895,7 @@ export class QuerySystem { /** * JavaScript实现的批量更新 */ - private batchUpdateComponentsJS(updates: Array<{entityId: number, componentMask: bigint}>): void { + private batchUpdateComponentsJS(updates: Array<{ entityId: number, componentMask: bigint }>): void { for (const update of updates) { const entity = this.entities.find(e => e.id === update.entityId); if (entity) { @@ -897,7 +929,7 @@ export class QuerySystem { wasmEnabled: this.wasmAvailable, cacheStats: { size: this.queryCache.size, - hitRate: this.queryStats.totalQueries > 0 ? + hitRate: this.queryStats.totalQueries > 0 ? (this.queryStats.cacheHits / this.queryStats.totalQueries * 100).toFixed(2) + '%' : '0%' } } @@ -929,12 +961,12 @@ export class QuerySystem { private createComponentMask(componentTypes: ComponentType[]): bigint { // 使用位掩码优化器创建掩码 const componentNames = componentTypes.map(type => type.name); - + // 确保组件类型已注册到优化器 for (const name of componentNames) { this.bitMaskOptimizer.registerComponentType(name); } - + return this.bitMaskOptimizer.createCombinedMask(componentNames); } @@ -960,8 +992,15 @@ export class QuerySystem { cacheHits: number; indexHits: number; linearScans: number; + archetypeHits: number; + dirtyChecks: number; cacheHitRate: string; }; + optimizationStats: { + componentIndex: any; + archetypeSystem: any; + dirtyTracking: any; + }; } { return { entityCount: this.entities.length, @@ -974,11 +1013,89 @@ export class QuerySystem { accelerationStatus: this.getAccelerationStatus(), queryStats: { ...this.queryStats, - cacheHitRate: this.queryStats.totalQueries > 0 ? + cacheHitRate: this.queryStats.totalQueries > 0 ? (this.queryStats.cacheHits / this.queryStats.totalQueries * 100).toFixed(2) + '%' : '0%' + }, + optimizationStats: { + 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() } }; } + + /** + * 切换组件索引类型 + * + * @param indexType 新的索引类型 + */ + public switchComponentIndexType(indexType: IndexType): void { + this.componentIndexManager.switchIndexType(indexType); + } + + /** + * 配置脏标记系统 + * + * @param batchSize 批处理大小 + * @param maxProcessingTime 最大处理时间 + */ + public configureDirtyTracking(batchSize: number, maxProcessingTime: number): void { + this.dirtyTrackingSystem.configureBatchProcessing(batchSize, maxProcessingTime); + } + + /** + * 手动触发性能优化 + */ + public optimizePerformance(): void { + this.dirtyTrackingSystem.processDirtyEntities(); + this.cleanupCache(); + + const stats = this.componentIndexManager.getStats(); + if (stats.avgQueryTime > 2.0 && stats.type !== IndexType.HASH) { + this.switchComponentIndexType(IndexType.HASH); + } else if (stats.memoryUsage > 50 * 1024 * 1024 && stats.type !== IndexType.BITMAP) { + this.switchComponentIndexType(IndexType.BITMAP); + } + } + + /** + * 开始新的帧 + */ + public beginFrame(): void { + this.dirtyTrackingSystem.beginFrame(); + } + + /** + * 结束当前帧 + */ + public endFrame(): void { + this.dirtyTrackingSystem.endFrame(); + } + + /** + * 标记实体组件已修改(用于脏标记追踪) + * + * @param entity 修改的实体 + * @param componentTypes 修改的组件类型 + */ + public markEntityDirty(entity: Entity, componentTypes: ComponentType[]): void { + this.queryStats.dirtyChecks++; + this.dirtyTrackingSystem.markDirty(entity, DirtyFlag.COMPONENT_MODIFIED, componentTypes); + this.clearQueryCache(); + } + + /** + * 获取实体所属的原型信息 + * + * @param entity 要查询的实体 + */ + public getEntityArchetype(entity: Entity): Archetype | undefined { + return this.archetypeSystem.getEntityArchetype(entity); + } } /** @@ -1057,7 +1174,7 @@ export class QueryBuilder { */ public execute(): QueryResult { const startTime = performance.now(); - + // 简化实现:目前只支持单一条件 if (this.conditions.length === 1) { const condition = this.conditions[0]; @@ -1070,7 +1187,7 @@ export class QueryBuilder { return this.querySystem.queryNone(...condition.componentTypes); } } - + // 多条件查询的复杂实现留待后续扩展 return { entities: [], diff --git a/source/src/ECS/CoreEvents.ts b/source/src/ECS/CoreEvents.ts index df65f424..9b489f33 100644 --- a/source/src/ECS/CoreEvents.ts +++ b/source/src/ECS/CoreEvents.ts @@ -16,3 +16,194 @@ export enum CoreEvents { */ renderChanged, } + +/** + * ECS事件类型枚举 + * 定义实体组件系统中的所有事件类型 + */ +export enum ECSEventType { + // 实体相关事件 + ENTITY_CREATED = 'entity:created', + ENTITY_DESTROYED = 'entity:destroyed', + ENTITY_ENABLED = 'entity:enabled', + ENTITY_DISABLED = 'entity:disabled', + ENTITY_TAG_ADDED = 'entity:tag:added', + ENTITY_TAG_REMOVED = 'entity:tag:removed', + ENTITY_NAME_CHANGED = 'entity:name:changed', + + // 组件相关事件 + COMPONENT_ADDED = 'component:added', + COMPONENT_REMOVED = 'component:removed', + COMPONENT_MODIFIED = 'component:modified', + COMPONENT_ENABLED = 'component:enabled', + COMPONENT_DISABLED = 'component:disabled', + + // 系统相关事件 + SYSTEM_ADDED = 'system:added', + SYSTEM_REMOVED = 'system:removed', + SYSTEM_ENABLED = 'system:enabled', + SYSTEM_DISABLED = 'system:disabled', + SYSTEM_PROCESSING_START = 'system:processing:start', + SYSTEM_PROCESSING_END = 'system:processing:end', + SYSTEM_ERROR = 'system:error', + + // 场景相关事件 + SCENE_CREATED = 'scene:created', + SCENE_DESTROYED = 'scene:destroyed', + SCENE_ACTIVATED = 'scene:activated', + SCENE_DEACTIVATED = 'scene:deactivated', + SCENE_PAUSED = 'scene:paused', + SCENE_RESUMED = 'scene:resumed', + + // 查询相关事件 + QUERY_EXECUTED = 'query:executed', + QUERY_CACHE_HIT = 'query:cache:hit', + QUERY_CACHE_MISS = 'query:cache:miss', + QUERY_OPTIMIZED = 'query:optimized', + + // 性能相关事件 + PERFORMANCE_WARNING = 'performance:warning', + PERFORMANCE_CRITICAL = 'performance:critical', + MEMORY_USAGE_HIGH = 'memory:usage:high', + FRAME_RATE_DROP = 'frame:rate:drop', + + // 索引相关事件 + INDEX_CREATED = 'index:created', + INDEX_UPDATED = 'index:updated', + INDEX_OPTIMIZED = 'index:optimized', + + // Archetype相关事件 + ARCHETYPE_CREATED = 'archetype:created', + ARCHETYPE_ENTITY_ADDED = 'archetype:entity:added', + ARCHETYPE_ENTITY_REMOVED = 'archetype:entity:removed', + + // 脏标记相关事件 + DIRTY_MARK_ADDED = 'dirty:mark:added', + DIRTY_BATCH_PROCESSED = 'dirty:batch:processed', + + // 错误和警告事件 + ERROR_OCCURRED = 'error:occurred', + WARNING_ISSUED = 'warning:issued', + + // 生命周期事件 + FRAMEWORK_INITIALIZED = 'framework:initialized', + FRAMEWORK_SHUTDOWN = 'framework:shutdown', + + // 调试相关事件 + DEBUG_INFO = 'debug:info', + DEBUG_STATS_UPDATED = 'debug:stats:updated' +} + +/** + * 事件优先级枚举 + * 定义事件处理的优先级级别 + */ +export enum EventPriority { + LOWEST = 0, + LOW = 25, + NORMAL = 50, + HIGH = 75, + HIGHEST = 100, + CRITICAL = 200 +} + +/** + * 预定义的事件类型常量 + * 提供类型安全的事件类型字符串 + */ +export const EVENT_TYPES = { + // 核心事件 + CORE: { + SCENE_CHANGED: 'core:scene:changed', + FRAME_UPDATED: 'core:frame:updated', + RENDER_CHANGED: 'core:render:changed' + }, + + // 实体事件 + ENTITY: { + CREATED: ECSEventType.ENTITY_CREATED, + DESTROYED: ECSEventType.ENTITY_DESTROYED, + ENABLED: ECSEventType.ENTITY_ENABLED, + DISABLED: ECSEventType.ENTITY_DISABLED, + TAG_ADDED: ECSEventType.ENTITY_TAG_ADDED, + TAG_REMOVED: ECSEventType.ENTITY_TAG_REMOVED, + NAME_CHANGED: ECSEventType.ENTITY_NAME_CHANGED + }, + + // 组件事件 + COMPONENT: { + ADDED: ECSEventType.COMPONENT_ADDED, + REMOVED: ECSEventType.COMPONENT_REMOVED, + MODIFIED: ECSEventType.COMPONENT_MODIFIED, + ENABLED: ECSEventType.COMPONENT_ENABLED, + DISABLED: ECSEventType.COMPONENT_DISABLED + }, + + // 系统事件 + SYSTEM: { + ADDED: ECSEventType.SYSTEM_ADDED, + REMOVED: ECSEventType.SYSTEM_REMOVED, + ENABLED: ECSEventType.SYSTEM_ENABLED, + DISABLED: ECSEventType.SYSTEM_DISABLED, + PROCESSING_START: ECSEventType.SYSTEM_PROCESSING_START, + PROCESSING_END: ECSEventType.SYSTEM_PROCESSING_END, + ERROR: ECSEventType.SYSTEM_ERROR + }, + + // 性能事件 + PERFORMANCE: { + WARNING: ECSEventType.PERFORMANCE_WARNING, + CRITICAL: ECSEventType.PERFORMANCE_CRITICAL, + MEMORY_HIGH: ECSEventType.MEMORY_USAGE_HIGH, + FRAME_DROP: ECSEventType.FRAME_RATE_DROP + } +} as const; + +/** + * 事件类型验证器 + * 验证事件类型是否有效 + */ +export class EventTypeValidator { + private static validTypes = new Set([ + ...Object.values(CoreEvents).map(e => e.toString()), + ...Object.values(ECSEventType), + ...Object.values(EVENT_TYPES.CORE), + ...Object.values(EVENT_TYPES.ENTITY), + ...Object.values(EVENT_TYPES.COMPONENT), + ...Object.values(EVENT_TYPES.SYSTEM), + ...Object.values(EVENT_TYPES.PERFORMANCE) + ]); + + /** + * 验证事件类型是否有效 + * @param eventType 事件类型 + * @returns 是否有效 + */ + public static isValid(eventType: string): boolean { + return this.validTypes.has(eventType); + } + + /** + * 获取所有有效的事件类型 + * @returns 事件类型数组 + */ + public static getAllValidTypes(): string[] { + return Array.from(this.validTypes); + } + + /** + * 添加自定义事件类型 + * @param eventType 事件类型 + */ + public static addCustomType(eventType: string): void { + this.validTypes.add(eventType); + } + + /** + * 移除自定义事件类型 + * @param eventType 事件类型 + */ + public static removeCustomType(eventType: string): void { + this.validTypes.delete(eventType); + } +} diff --git a/source/src/ECS/Entity.ts b/source/src/ECS/Entity.ts index 30a28853..7ca40e05 100644 --- a/source/src/ECS/Entity.ts +++ b/source/src/ECS/Entity.ts @@ -1,5 +1,8 @@ import { Component } from './Component'; import { ComponentRegistry, ComponentType } from './Core/ComponentStorage'; +import { EventBus } from './Core/EventBus'; +import { ECSEventType } from './CoreEvents'; +import { IComponentEventData } from '../Types'; /** * 实体比较器 @@ -192,6 +195,12 @@ export class Entity { */ public static entityComparer: EntityComparer = new EntityComparer(); + /** + * 全局事件总线实例 + * 用于发射组件相关事件 + */ + public static eventBus: EventBus | null = null; + /** * 实体名称 * @@ -538,6 +547,19 @@ export class Entity { // 调用组件的生命周期方法 component.onAddedToEntity(); + // 发射组件添加事件 + if (Entity.eventBus) { + Entity.eventBus.emitComponentAdded({ + timestamp: Date.now(), + source: 'Entity', + entityId: this.id, + entityName: this.name, + entityTag: this.tag?.toString(), + componentType: componentType.name, + component: component + }); + } + // 通知场景实体已改变 if (this.scene && this.scene.entityProcessors) { for (const processor of this.scene.entityProcessors.processors) { @@ -744,6 +766,19 @@ export class Entity { // 调用组件的生命周期方法 component.onRemovedFromEntity(); + // 发射组件移除事件 + if (Entity.eventBus) { + Entity.eventBus.emitComponentRemoved({ + timestamp: Date.now(), + source: 'Entity', + entityId: this.id, + entityName: this.name, + entityTag: this.tag?.toString(), + componentType: componentType.name, + component: component + }); + } + // 清除组件的实体引用 component.entity = null as any; diff --git a/source/src/ECS/Scene.ts b/source/src/ECS/Scene.ts index 491b3f02..590b05b6 100644 --- a/source/src/ECS/Scene.ts +++ b/source/src/ECS/Scene.ts @@ -6,6 +6,7 @@ import { EntitySystem } from './Systems/EntitySystem'; import { ComponentStorageManager } from './Core/ComponentStorage'; import { QuerySystem } from './Core/QuerySystem'; import { TypeSafeEventSystem, GlobalEventSystem } from './Core/EventSystem'; +import type { IScene } from '../Types'; /** * 游戏场景类 diff --git a/source/src/ECS/Systems/EntitySystem.ts b/source/src/ECS/Systems/EntitySystem.ts index c64a1b1b..846fbd8e 100644 --- a/source/src/ECS/Systems/EntitySystem.ts +++ b/source/src/ECS/Systems/EntitySystem.ts @@ -3,6 +3,7 @@ import { Core } from '../../Core'; import { Matcher } from '../Utils/Matcher'; import { PerformanceMonitor } from '../../Utils/PerformanceMonitor'; import type { Scene } from '../Scene'; +import type { ISystemBase } from '../../Types'; /** * 实体系统的基类 @@ -27,7 +28,7 @@ import type { Scene } from '../Scene'; * } * ``` */ -export abstract class EntitySystem { +export abstract class EntitySystem implements ISystemBase { private _entities: Entity[] = []; private _updateOrder: number = 0; private _enabled: boolean = true; diff --git a/source/src/Types/index.ts b/source/src/Types/index.ts index 68fd4d0a..42ab59da 100644 --- a/source/src/Types/index.ts +++ b/source/src/Types/index.ts @@ -21,4 +21,557 @@ export enum ComponentTransform { Position = 1, Scale = 2, Rotation = 4 +} + +/** + * 组件接口 + * + * 定义组件的基本契约,所有组件都应该实现此接口 + */ +export interface IComponent { + /** 组件唯一标识符 */ + readonly id: number; + /** 组件所属的实体ID */ + entityId?: string | number; + /** 组件启用状态 */ + enabled: boolean; + /** 更新顺序 */ + updateOrder: number; + + /** 组件添加到实体时的回调 */ + onAddedToEntity(): void; + /** 组件从实体移除时的回调 */ + onRemovedFromEntity(): void; + /** 组件启用时的回调 */ + onEnabled(): void; + /** 组件禁用时的回调 */ + onDisabled(): void; + /** 更新组件 */ + update(): void; +} + +/** + * 实体接口 + * + * 定义实体的基本契约,所有实体都应该实现此接口 + */ +export interface IEntity { + /** 实体唯一标识符 */ + readonly id: string | number; + /** 实体名称 */ + name: string; + /** 实体激活状态 */ + active: boolean; + /** 实体启用状态 */ + enabled: boolean; + /** 实体是否已销毁 */ + readonly isDestroyed: boolean; + /** 更新顺序 */ + updateOrder: number; + /** 实体标签 */ + tag: number; + + /** 添加组件 */ + addComponent(component: T): T; + /** 创建并添加组件 */ + createComponent(componentType: ComponentType, ...args: any[]): T; + /** 获取组件 */ + getComponent(type: ComponentType): T | null; + /** 获取或创建组件 */ + getOrCreateComponent(type: ComponentType, ...args: any[]): T; + /** 移除组件 */ + removeComponent(component: IComponent): void; + /** 通过类型移除组件 */ + removeComponentByType(type: ComponentType): T | null; + /** 检查是否有组件 */ + hasComponent(type: ComponentType): boolean; + /** 获取所有指定类型的组件 */ + getComponents(type: ComponentType): T[]; + + /** 添加子实体 */ + addChild(child: IEntity): IEntity; + /** 移除子实体 */ + removeChild(child: IEntity): boolean; + /** 查找子实体 */ + findChild(name: string, recursive?: boolean): IEntity | null; + + /** 更新实体 */ + update(): void; + /** 销毁实体 */ + destroy(): void; +} + +/** + * 实体基础接口(向后兼容) + * + * 为现有的Entity类提供更灵活的类型定义 + */ +export interface IEntityBase { + /** 实体唯一标识符 */ + readonly id: string | number; + /** 实体名称 */ + name: string; + /** 实体激活状态 */ + active: boolean; + /** 实体启用状态 */ + enabled: boolean; + /** 实体是否已销毁 */ + readonly isDestroyed: boolean; + /** 更新顺序 */ + updateOrder: number; + /** 实体标签 */ + tag: number; + + /** 添加组件(泛型版本) */ + addComponent(component: T): T; + /** 获取组件(泛型版本) */ + getComponent(type: ComponentClass): T | null; + /** 检查是否有组件(泛型版本) */ + hasComponent(type: ComponentClass): boolean; + + /** 添加子实体 */ + addChild(child: any): any; + /** 移除子实体 */ + removeChild(child: any): boolean; + /** 查找子实体 */ + findChild(name: string, recursive?: boolean): any; + + /** 更新实体 */ + update(): void; + /** 销毁实体 */ + destroy(): void; +} + +/** + * 系统接口 + * + * 定义系统的基本契约,所有系统都应该实现此接口 + */ +export interface ISystem { + /** 系统名称 */ + readonly systemName: string; + /** 系统处理的实体列表 */ + readonly entities: readonly IEntity[]; + /** 更新顺序/优先级 */ + updateOrder: number; + /** 系统启用状态 */ + enabled: boolean; + + /** 系统初始化 */ + initialize(): void; + /** 更新系统(主要处理阶段) */ + update(): void; + /** 延迟更新系统 */ + lateUpdate?(): void; + + /** 当实体添加到系统时的回调 */ + onEntityAdded?(entity: IEntity): void; + /** 当实体从系统移除时的回调 */ + onEntityRemoved?(entity: IEntity): void; + /** 当实体组件发生变化时的回调 */ + onEntityChanged?(entity: IEntity): void; +} + +/** + * 系统基础接口(向后兼容) + * + * 为现有的EntitySystem类提供更灵活的类型定义 + */ +export interface ISystemBase { + /** 系统名称 */ + readonly systemName: string; + /** 系统处理的实体列表(泛型版本) */ + readonly entities: readonly any[]; + /** 更新顺序/优先级 */ + updateOrder: number; + /** 系统启用状态 */ + enabled: boolean; + + /** 系统初始化 */ + initialize(): void; + /** 更新系统(主要处理阶段) */ + update(): void; + /** 延迟更新系统 */ + lateUpdate?(): void; +} + +/** + * 场景接口 + * + * 定义场景的基本契约 + */ +export interface IScene { + /** 场景名称 */ + name: string; + /** 场景中的实体列表 */ + readonly entities: readonly IEntity[]; + /** 场景中的系统列表 */ + readonly systems: readonly ISystem[]; + + /** 创建实体 */ + createEntity(name: string): IEntity; + /** 添加实体到场景 */ + addEntity(entity: IEntity): void; + /** 从场景移除实体 */ + removeEntity(entity: IEntity): void; + /** 查找实体 */ + findEntity(name: string): IEntity | null; + + /** 添加系统到场景 */ + addSystem(system: T): T; + /** 从场景移除系统 */ + removeSystem(system: ISystem): void; + /** 获取系统 */ + getSystem(systemType: new (...args: any[]) => T): T | null; + + /** 更新场景 */ + update(): void; +} + +/** + * 组件类型定义 + * + * 用于类型安全的组件操作 + */ +export type ComponentType = new (...args: any[]) => T; + +/** + * 原始组件类型(向后兼容) + * + * 用于与现有Component类的兼容 + */ +export type ComponentClass = new (...args: any[]) => T; + +/** + * 实体查询匹配器接口 + * + * 用于查询符合特定条件的实体 + */ +export interface IMatcher { + /** 必须包含的组件类型 */ + all(...componentTypes: ComponentType[]): IMatcher; + /** 至少包含其中一个组件类型 */ + any(...componentTypes: ComponentType[]): IMatcher; + /** 不能包含的组件类型 */ + exclude(...componentTypes: ComponentType[]): IMatcher; + /** 检查实体是否匹配 */ + isInterestedEntity(entity: IEntity): boolean; +} + +/** + * 性能监控接口 + */ +export interface IPerformanceData { + /** 执行时间(毫秒) */ + executionTime: number; + /** 调用次数 */ + callCount: number; + /** 平均执行时间 */ + averageTime: number; + /** 最大执行时间 */ + maxTime: number; + /** 最小执行时间 */ + minTime: number; +} + +/** + * 生命周期管理接口 + */ +export interface ILifecycle { + /** 初始化 */ + initialize?(): void; + /** 启动 */ + start?(): void; + /** 更新 */ + update?(): void; + /** 延迟更新 */ + lateUpdate?(): void; + /** 停止 */ + stop?(): void; + /** 销毁 */ + destroy?(): void; +} + +/** + * 实体管理器接口 + * + * 提供统一的实体管理和查询机制,支持高效的实体操作 + */ +export interface IEntityManager { + /** 所有实体数量 */ + readonly entityCount: number; + /** 激活的实体数量 */ + readonly activeEntityCount: number; + + /** 创建实体 */ + createEntity(name?: string): IEntity; + /** 销毁实体 */ + destroyEntity(entity: IEntity | string | number): boolean; + /** 批量销毁实体 */ + destroyEntities(entities: (IEntity | string | number)[]): number; + /** 销毁所有实体 */ + destroyAllEntities(): number; + + /** 根据ID获取实体 */ + getEntity(id: string | number): IEntity | null; + /** 根据名称获取实体 */ + getEntityByName(name: string): IEntity | null; + /** 根据名称获取所有实体 */ + getEntitiesByName(name: string): IEntity[]; + /** 根据标签获取实体 */ + getEntitiesByTag(tag: number): IEntity[]; + /** 获取所有实体 */ + getAllEntities(): IEntity[]; + /** 获取所有激活的实体 */ + getActiveEntities(): IEntity[]; + + /** 获取拥有指定组件的实体 */ + getEntitiesWithComponent(componentType: ComponentType): IEntity[]; + /** 获取拥有指定组件的实体及其组件 */ + getEntitiesWithComponentData(componentType: ComponentType): Array<{entity: IEntity, component: T}>; + /** 获取拥有所有指定组件的实体 */ + getEntitiesWithComponents(...componentTypes: ComponentType[]): IEntity[]; + /** 获取拥有任一指定组件的实体 */ + getEntitiesWithAnyComponent(...componentTypes: ComponentType[]): IEntity[]; + /** 获取不包含指定组件的实体 */ + getEntitiesWithoutComponent(componentType: ComponentType): IEntity[]; + + /** 对所有实体执行操作 */ + forEachEntity(action: (entity: IEntity) => void): void; + /** 对符合条件的实体执行操作 */ + forEachEntityWhere(predicate: (entity: IEntity) => boolean, action: (entity: IEntity) => void): void; + /** 对拥有指定组件的实体执行操作 */ + forEachEntityWithComponent( + componentType: ComponentType, + action: (entity: IEntity, component: T) => void + ): void; + + /** 查找第一个符合条件的实体 */ + findEntity(predicate: (entity: IEntity) => boolean): IEntity | null; + /** 查找所有符合条件的实体 */ + findEntities(predicate: (entity: IEntity) => boolean): IEntity[]; + + /** 获取统计信息 */ + getStatistics(): { + totalEntities: number; + activeEntities: number; + destroyedEntities: number; + entitiesByTag: Map; + componentsCount: Map; + }; + + /** 清理已销毁的实体 */ + cleanup(): number; + /** 压缩存储空间 */ + compact(): void; +} + +/** + * 实体查询构建器接口 + * + * 提供流式API构建复杂的实体查询条件 + */ +export interface IEntityQueryBuilder { + /** 必须包含所有指定组件 */ + withAll(...componentTypes: ComponentType[]): IEntityQueryBuilder; + /** 必须包含任一指定组件 */ + withAny(...componentTypes: ComponentType[]): IEntityQueryBuilder; + /** 必须不包含指定组件 */ + without(...componentTypes: ComponentType[]): IEntityQueryBuilder; + /** 必须包含指定标签 */ + withTag(tag: number): IEntityQueryBuilder; + /** 必须不包含指定标签 */ + withoutTag(tag: number): IEntityQueryBuilder; + /** 必须处于激活状态 */ + active(): IEntityQueryBuilder; + /** 必须处于启用状态 */ + enabled(): IEntityQueryBuilder; + /** 自定义过滤条件 */ + where(predicate: (entity: IEntity) => boolean): IEntityQueryBuilder; + + /** 执行查询,返回所有匹配的实体 */ + execute(): IEntity[]; + /** 执行查询,返回第一个匹配的实体 */ + first(): IEntity | null; + /** 执行查询,返回匹配实体的数量 */ + count(): number; + /** 对查询结果执行操作 */ + forEach(action: (entity: IEntity) => void): void; +} + +/** + * 事件总线接口 + * 提供类型安全的事件发布订阅机制 + */ +export interface IEventBus { + /** + * 发射事件 + * @param eventType 事件类型 + * @param data 事件数据 + */ + emit(eventType: string, data: T): void; + + /** + * 异步发射事件 + * @param eventType 事件类型 + * @param data 事件数据 + */ + emitAsync(eventType: string, data: T): Promise; + + /** + * 监听事件 + * @param eventType 事件类型 + * @param handler 事件处理器 + * @param config 监听器配置 + * @returns 监听器ID + */ + on(eventType: string, handler: (data: T) => void, config?: IEventListenerConfig): string; + + /** + * 监听事件(一次性) + * @param eventType 事件类型 + * @param handler 事件处理器 + * @param config 监听器配置 + * @returns 监听器ID + */ + once(eventType: string, handler: (data: T) => void, config?: IEventListenerConfig): string; + + /** + * 异步监听事件 + * @param eventType 事件类型 + * @param handler 异步事件处理器 + * @param config 监听器配置 + * @returns 监听器ID + */ + onAsync(eventType: string, handler: (data: T) => Promise, config?: IEventListenerConfig): string; + + /** + * 移除事件监听器 + * @param eventType 事件类型 + * @param listenerId 监听器ID + */ + off(eventType: string, listenerId: string): boolean; + + /** + * 移除指定事件类型的所有监听器 + * @param eventType 事件类型 + */ + offAll(eventType: string): void; + + /** + * 检查是否有指定事件的监听器 + * @param eventType 事件类型 + */ + hasListeners(eventType: string): boolean; + + /** + * 获取事件统计信息 + * @param eventType 事件类型(可选) + */ + getStats(eventType?: string): IEventStats | Map; + + /** + * 清空所有监听器 + */ + clear(): void; +} + +/** + * 事件监听器配置接口 + */ +export interface IEventListenerConfig { + /** 是否只执行一次 */ + once?: boolean; + /** 优先级(数字越大优先级越高) */ + priority?: number; + /** 是否异步执行 */ + async?: boolean; + /** 执行上下文 */ + context?: any; +} + +/** + * 事件统计信息接口 + */ +export interface IEventStats { + /** 事件类型 */ + eventType: string; + /** 监听器数量 */ + listenerCount: number; + /** 触发次数 */ + triggerCount: number; + /** 总执行时间(毫秒) */ + totalExecutionTime: number; + /** 平均执行时间(毫秒) */ + averageExecutionTime: number; + /** 最后触发时间 */ + lastTriggerTime: number; +} + +/** + * 事件数据基类接口 + */ +export interface IEventData { + /** 事件时间戳 */ + timestamp: number; + /** 事件来源 */ + source?: string; + /** 事件ID */ + eventId?: string; +} + +/** + * 实体事件数据接口 + */ +export interface IEntityEventData extends IEventData { + /** 实体ID */ + entityId: number; + /** 实体名称 */ + entityName?: string; + /** 实体标签 */ + entityTag?: string; +} + +/** + * 组件事件数据接口 + */ +export interface IComponentEventData extends IEntityEventData { + /** 组件类型名称 */ + componentType: string; + /** 组件实例 */ + component?: IComponent; +} + +/** + * 系统事件数据接口 + */ +export interface ISystemEventData extends IEventData { + /** 系统名称 */ + systemName: string; + /** 系统类型 */ + systemType: string; +} + +/** + * 场景事件数据接口 + */ +export interface ISceneEventData extends IEventData { + /** 场景名称 */ + sceneName: string; + /** 前一个场景名称 */ + previousSceneName?: string; +} + +/** + * 性能事件数据接口 + */ +export interface IPerformanceEventData extends IEventData { + /** 操作类型 */ + operation: string; + /** 执行时间(毫秒) */ + executionTime: number; + /** 内存使用量 */ + memoryUsage?: number; + /** 额外数据 */ + metadata?: Record; } \ No newline at end of file