对query/entity进行安全类型扩展

This commit is contained in:
YHH
2025-10-08 13:13:23 +08:00
parent f41c1a3ca3
commit c631290049
10 changed files with 1742 additions and 21 deletions

View File

@@ -7,6 +7,7 @@ import type { QuerySystem } from '../Core/QuerySystem';
import { getSystemInstanceTypeName } from '../Decorators';
import { createLogger } from '../../Utils/Logger';
import type { EventListenerConfig, TypeSafeEventSystem, EventHandler } from '../Core/EventSystem';
import type { ComponentConstructor, ComponentInstance } from '../../Types/TypeHelpers';
/**
* 事件监听器记录
@@ -21,17 +22,22 @@ interface EventListenerRecord {
/**
* 实体系统的基类
*
*
* 用于处理一组符合特定条件的实体。系统是ECS架构中的逻辑处理单元
* 负责对拥有特定组件组合的实体执行业务逻辑。
*
*
* 支持泛型参数以提供类型安全的组件访问:
*
* @template TComponents - 系统需要的组件类型数组
*
* @example
* ```typescript
* // 传统方式
* class MovementSystem extends EntitySystem {
* constructor() {
* super(Transform, Velocity);
* super(Matcher.of(Transform, Velocity));
* }
*
*
* protected process(entities: readonly Entity[]): void {
* for (const entity of entities) {
* const transform = entity.getComponent(Transform);
@@ -40,9 +46,26 @@ interface EventListenerRecord {
* }
* }
* }
*
* // 类型安全方式
* class MovementSystem extends EntitySystem<[typeof Transform, typeof Velocity]> {
* constructor() {
* super(Matcher.of(Transform, Velocity));
* }
*
* protected process(entities: readonly Entity[]): void {
* for (const entity of entities) {
* // 类型安全的组件访问
* const [transform, velocity] = this.getComponents(entity);
* transform.position.add(velocity.value);
* }
* }
* }
* ```
*/
export abstract class EntitySystem implements ISystemBase {
export abstract class EntitySystem<
TComponents extends readonly ComponentConstructor[] = []
> implements ISystemBase {
private _updateOrder: number;
private _enabled: boolean;
private _performanceMonitor: PerformanceMonitor;
@@ -793,4 +816,235 @@ export abstract class EntitySystem implements ISystemBase {
protected onDestroy(): void {
// 子类可以重写此方法进行清理操作
}
// ============================================================
// 类型安全的辅助方法
// ============================================================
/**
* 类型安全地获取单个组件
*
* 相比Entity.getComponent此方法保证返回非空值
* 如果组件不存在会抛出错误而不是返回null
*
* @param entity 实体
* @param componentType 组件类型
* @returns 组件实例(保证非空)
* @throws 如果组件不存在则抛出错误
*
* @example
* ```typescript
* protected process(entities: readonly Entity[]): void {
* for (const entity of entities) {
* const transform = this.requireComponent(entity, Transform);
* // transform 保证非空,类型为 Transform
* }
* }
* ```
*/
protected requireComponent<T extends ComponentConstructor>(
entity: Entity,
componentType: T
): ComponentInstance<T> {
const component = entity.getComponent(componentType as any);
if (!component) {
throw new Error(
`Component ${componentType.name} not found on entity ${entity.name} in ${this.systemName}`
);
}
return component as ComponentInstance<T>;
}
/**
* 批量获取实体的所有必需组件
*
* 根据泛型参数TComponents推断返回类型
* 返回一个元组,包含所有组件实例
*
* @param entity 实体
* @param components 组件类型数组
* @returns 组件实例元组
*
* @example
* ```typescript
* class MySystem extends EntitySystem<[typeof Position, typeof Velocity]> {
* protected process(entities: readonly Entity[]): void {
* for (const entity of entities) {
* const [pos, vel] = this.getComponents(entity, Position, Velocity);
* // pos: Position, vel: Velocity (自动类型推断)
* pos.x += vel.x;
* }
* }
* }
* ```
*/
protected getComponents<T extends readonly ComponentConstructor[]>(
entity: Entity,
...components: T
): { [K in keyof T]: ComponentInstance<T[K]> } {
return components.map((type) =>
this.requireComponent(entity, type)
) as any;
}
/**
* 遍历实体并处理每个实体
*
* 提供更简洁的语法糖,避免手动遍历
*
* @param entities 实体列表
* @param processor 处理函数
*
* @example
* ```typescript
* protected process(entities: readonly Entity[]): void {
* this.forEach(entities, (entity) => {
* const transform = this.requireComponent(entity, Transform);
* transform.position.y -= 9.8 * Time.deltaTime;
* });
* }
* ```
*/
protected forEach(
entities: readonly Entity[],
processor: (entity: Entity, index: number) => void
): void {
for (let i = 0; i < entities.length; i++) {
processor(entities[i], i);
}
}
/**
* 过滤实体
*
* @param entities 实体列表
* @param predicate 过滤条件
* @returns 过滤后的实体数组
*
* @example
* ```typescript
* protected process(entities: readonly Entity[]): void {
* const activeEntities = this.filterEntities(entities, (entity) => {
* const health = this.requireComponent(entity, Health);
* return health.value > 0;
* });
* }
* ```
*/
protected filterEntities(
entities: readonly Entity[],
predicate: (entity: Entity, index: number) => boolean
): Entity[] {
return Array.from(entities).filter(predicate);
}
/**
* 映射实体到另一种类型
*
* @param entities 实体列表
* @param mapper 映射函数
* @returns 映射后的结果数组
*
* @example
* ```typescript
* protected process(entities: readonly Entity[]): void {
* const positions = this.mapEntities(entities, (entity) => {
* const transform = this.requireComponent(entity, Transform);
* return transform.position;
* });
* }
* ```
*/
protected mapEntities<R>(
entities: readonly Entity[],
mapper: (entity: Entity, index: number) => R
): R[] {
return Array.from(entities).map(mapper);
}
/**
* 查找第一个满足条件的实体
*
* @param entities 实体列表
* @param predicate 查找条件
* @returns 第一个满足条件的实体或undefined
*
* @example
* ```typescript
* protected process(entities: readonly Entity[]): void {
* const player = this.findEntity(entities, (entity) =>
* entity.hasComponent(PlayerTag)
* );
* }
* ```
*/
protected findEntity(
entities: readonly Entity[],
predicate: (entity: Entity, index: number) => boolean
): Entity | undefined {
for (let i = 0; i < entities.length; i++) {
if (predicate(entities[i], i)) {
return entities[i];
}
}
return undefined;
}
/**
* 检查是否存在满足条件的实体
*
* @param entities 实体列表
* @param predicate 检查条件
* @returns 是否存在满足条件的实体
*
* @example
* ```typescript
* protected process(entities: readonly Entity[]): void {
* const hasLowHealth = this.someEntity(entities, (entity) => {
* const health = this.requireComponent(entity, Health);
* return health.value < 20;
* });
* }
* ```
*/
protected someEntity(
entities: readonly Entity[],
predicate: (entity: Entity, index: number) => boolean
): boolean {
for (let i = 0; i < entities.length; i++) {
if (predicate(entities[i], i)) {
return true;
}
}
return false;
}
/**
* 检查是否所有实体都满足条件
*
* @param entities 实体列表
* @param predicate 检查条件
* @returns 是否所有实体都满足条件
*
* @example
* ```typescript
* protected process(entities: readonly Entity[]): void {
* const allHealthy = this.everyEntity(entities, (entity) => {
* const health = this.requireComponent(entity, Health);
* return health.value > 50;
* });
* }
* ```
*/
protected everyEntity(
entities: readonly Entity[],
predicate: (entity: Entity, index: number) => boolean
): boolean {
for (let i = 0; i < entities.length; i++) {
if (!predicate(entities[i], i)) {
return false;
}
}
return true;
}
}