对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

@@ -0,0 +1,404 @@
/**
* 类型安全的Query查询系统
*
* 提供完整的TypeScript类型推断在编译时确保类型安全
*/
import type { Entity } from '../../Entity';
import type { ComponentConstructor, ComponentInstance, ComponentTypeMap } from '../../../Types/TypeHelpers';
import { Matcher, type QueryCondition } from '../../Utils/Matcher';
/**
* 类型安全的查询结果
*
* 根据查询条件自动推断实体必定拥有的组件类型
*/
export class TypedQueryResult<TAll extends readonly ComponentConstructor[]> {
private _entities: readonly Entity[];
private _componentTypes: TAll;
constructor(entities: readonly Entity[], componentTypes: TAll) {
this._entities = entities;
this._componentTypes = componentTypes;
}
/**
* 获取实体列表
*/
get entities(): readonly Entity[] {
return this._entities;
}
/**
* 实体数量
*/
get length(): number {
return this._entities.length;
}
/**
* 遍历所有实体
*
* @example
* ```typescript
* query.forEach((entity) => {
* // entity.getComponent返回类型自动推断
* const pos = entity.getComponent(Position); // Position类型
* const vel = entity.getComponent(Velocity); // Velocity类型
* });
* ```
*/
forEach(callback: (entity: Entity, index: number) => void): void {
this._entities.forEach(callback);
}
/**
* 映射转换实体
*/
map<R>(callback: (entity: Entity, index: number) => R): R[] {
return this._entities.map(callback);
}
/**
* 过滤实体
*/
filter(predicate: (entity: Entity, index: number) => boolean): TypedQueryResult<TAll> {
return new TypedQueryResult(this._entities.filter(predicate), this._componentTypes);
}
/**
* 查找第一个匹配的实体
*/
find(predicate: (entity: Entity, index: number) => boolean): Entity | undefined {
return this._entities.find(predicate);
}
/**
* 检查是否存在匹配的实体
*/
some(predicate: (entity: Entity, index: number) => boolean): boolean {
return this._entities.some(predicate);
}
/**
* 检查是否所有实体都匹配
*/
every(predicate: (entity: Entity, index: number) => boolean): boolean {
return this._entities.every(predicate);
}
/**
* 获取指定索引的实体
*/
get(index: number): Entity | undefined {
return this._entities[index];
}
/**
* 获取第一个实体
*/
get first(): Entity | undefined {
return this._entities[0];
}
/**
* 获取最后一个实体
*/
get last(): Entity | undefined {
return this._entities[this._entities.length - 1];
}
/**
* 检查查询结果是否为空
*/
get isEmpty(): boolean {
return this._entities.length === 0;
}
/**
* 转换为数组
*/
toArray(): Entity[] {
return [...this._entities];
}
/**
* 获取组件类型信息(用于调试)
*/
getComponentTypes(): readonly ComponentConstructor[] {
return this._componentTypes;
}
/**
* 迭代器支持
*/
[Symbol.iterator](): Iterator<Entity> {
return this._entities[Symbol.iterator]();
}
}
/**
* 类型安全的查询构建器
*
* 支持链式调用,自动推断查询结果的类型
*
* @example
* ```typescript
* // 基础查询
* const query = new TypedQueryBuilder()
* .withAll(Position, Velocity)
* .build();
*
* // 复杂查询
* const complexQuery = new TypedQueryBuilder()
* .withAll(Transform, Renderer)
* .withAny(BoxCollider, CircleCollider)
* .withNone(Disabled)
* .withTag(EntityTags.Enemy)
* .build();
* ```
*/
export class TypedQueryBuilder<
TAll extends readonly ComponentConstructor[] = [],
TAny extends readonly ComponentConstructor[] = [],
TNone extends readonly ComponentConstructor[] = []
> {
private _all: TAll;
private _any: TAny;
private _none: TNone;
private _tag?: number;
private _name?: string;
constructor(
all?: TAll,
any?: TAny,
none?: TNone,
tag?: number,
name?: string
) {
this._all = (all || []) as TAll;
this._any = (any || []) as TAny;
this._none = (none || []) as TNone;
this._tag = tag;
this._name = name;
}
/**
* 要求实体拥有所有指定的组件
*
* @param types 组件类型
* @returns 新的查询构建器,类型参数更新
*/
withAll<TNewAll extends readonly ComponentConstructor[]>(
...types: TNewAll
): TypedQueryBuilder<
readonly [...TAll, ...TNewAll],
TAny,
TNone
> {
return new TypedQueryBuilder(
[...this._all, ...types] as readonly [...TAll, ...TNewAll],
this._any,
this._none,
this._tag,
this._name
);
}
/**
* 要求实体至少拥有一个指定的组件
*
* @param types 组件类型
* @returns 新的查询构建器
*/
withAny<TNewAny extends readonly ComponentConstructor[]>(
...types: TNewAny
): TypedQueryBuilder<
TAll,
readonly [...TAny, ...TNewAny],
TNone
> {
return new TypedQueryBuilder(
this._all,
[...this._any, ...types] as readonly [...TAny, ...TNewAny],
this._none,
this._tag,
this._name
);
}
/**
* 排除拥有指定组件的实体
*
* @param types 组件类型
* @returns 新的查询构建器
*/
withNone<TNewNone extends readonly ComponentConstructor[]>(
...types: TNewNone
): TypedQueryBuilder<
TAll,
TAny,
readonly [...TNone, ...TNewNone]
> {
return new TypedQueryBuilder(
this._all,
this._any,
[...this._none, ...types] as readonly [...TNone, ...TNewNone],
this._tag,
this._name
);
}
/**
* 按标签过滤实体
*
* @param tag 标签值
* @returns 新的查询构建器
*/
withTag(tag: number): TypedQueryBuilder<TAll, TAny, TNone> {
return new TypedQueryBuilder(
this._all,
this._any,
this._none,
tag,
this._name
);
}
/**
* 按名称过滤实体
*
* @param name 实体名称
* @returns 新的查询构建器
*/
withName(name: string): TypedQueryBuilder<TAll, TAny, TNone> {
return new TypedQueryBuilder(
this._all,
this._any,
this._none,
this._tag,
name
);
}
/**
* 构建Matcher对象
*
* @returns Matcher实例用于传统查询API
*/
buildMatcher(): Matcher {
let matcher = Matcher.complex();
if (this._all.length > 0) {
matcher = matcher.all(...(this._all as unknown as ComponentConstructor[]));
}
if (this._any.length > 0) {
matcher = matcher.any(...(this._any as unknown as ComponentConstructor[]));
}
if (this._none.length > 0) {
matcher = matcher.none(...(this._none as unknown as ComponentConstructor[]));
}
if (this._tag !== undefined) {
matcher = matcher.withTag(this._tag);
}
if (this._name !== undefined) {
matcher = matcher.withName(this._name);
}
return matcher;
}
/**
* 获取查询条件
*
* @returns 查询条件对象
*/
getCondition(): QueryCondition {
return {
all: [...this._all] as ComponentConstructor[],
any: [...this._any] as ComponentConstructor[],
none: [...this._none] as ComponentConstructor[],
tag: this._tag,
name: this._name
};
}
/**
* 获取required组件类型用于类型推断
*/
getRequiredTypes(): TAll {
return this._all;
}
/**
* 克隆查询构建器
*/
clone(): TypedQueryBuilder<TAll, TAny, TNone> {
return new TypedQueryBuilder(
[...this._all] as unknown as TAll,
[...this._any] as unknown as TAny,
[...this._none] as unknown as TNone,
this._tag,
this._name
);
}
}
/**
* 创建类型安全的查询构建器
*
* @example
* ```typescript
* const query = createQuery()
* .withAll(Position, Velocity)
* .withNone(Disabled);
*
* // 在System或Scene中使用
* const entities = scene.query(query);
* entities.forEach(entity => {
* const pos = entity.getComponent(Position); // 自动推断为Position
* const vel = entity.getComponent(Velocity); // 自动推断为Velocity
* });
* ```
*/
export function createQuery(): TypedQueryBuilder<[], [], []> {
return new TypedQueryBuilder();
}
/**
* 创建单组件查询的便捷方法
*
* @param componentType 组件类型
* @returns 查询构建器
*
* @example
* ```typescript
* const healthEntities = queryFor(HealthComponent);
* ```
*/
export function queryFor<T extends ComponentConstructor>(
componentType: T
): TypedQueryBuilder<readonly [T], [], []> {
return new TypedQueryBuilder([componentType] as readonly [T]);
}
/**
* 创建多组件查询的便捷方法
*
* @param types 组件类型数组
* @returns 查询构建器
*
* @example
* ```typescript
* const movableEntities = queryForAll(Position, Velocity);
* ```
*/
export function queryForAll<T extends readonly ComponentConstructor[]>(
...types: T
): TypedQueryBuilder<T, [], []> {
return new TypedQueryBuilder(types);
}

View File

@@ -346,13 +346,19 @@ export class Entity {
/**
* 创建并添加组件
*
* @param componentType - 组件类型
*
* @param componentType - 组件类型构造函数
* @param args - 组件构造函数参数
* @returns 创建的组件实例
*
* @example
* ```typescript
* const position = entity.createComponent(Position, 100, 200);
* const health = entity.createComponent(Health, 100);
* ```
*/
public createComponent<T extends Component>(
componentType: ComponentType<T>,
componentType: ComponentType<T>,
...args: any[]
): T {
const component = new componentType(...args);
@@ -387,10 +393,16 @@ export class Entity {
/**
* 添加组件到实体
*
*
* @param component - 要添加的组件实例
* @returns 添加的组件实例
* @throws {Error} 如果组件类型已存在
* @throws {Error} 如果实体已存在该类型的组件
*
* @example
* ```typescript
* const position = new Position(100, 200);
* entity.addComponent(position);
* ```
*/
public addComponent<T extends Component>(component: T): T {
const componentType = component.constructor as ComponentType<T>;
@@ -429,8 +441,17 @@ export class Entity {
/**
* 获取指定类型的组件
*
* @param type - 组件类型
* @returns 组件实例null
* @param type - 组件类型构造函数
* @returns 组件实例,如果不存在则返回null
*
* @example
* ```typescript
* const position = entity.getComponent(Position);
* if (position) {
* position.x += 10;
* position.y += 20;
* }
* ```
*/
public getComponent<T extends Component>(type: ComponentType<T>): T | null {
// 快速检查:位掩码
@@ -442,7 +463,7 @@ export class Entity {
if (this.scene?.componentStorageManager) {
const component = this.scene.componentStorageManager.getComponent(this.id, type);
if (component) {
return component;
return component as T;
}
}
@@ -454,10 +475,18 @@ export class Entity {
/**
* 检查实体是否有指定类型的组件
*
* @param type - 组件类型
* @returns 如果有该组件返回true
* 检查实体是否有指定类型的组件
*
* @param type - 组件类型构造函数
* @returns 如果实体拥有该组件返回true否则返回false
*
* @example
* ```typescript
* if (entity.hasComponent(Position)) {
* const position = entity.getComponent(Position)!;
* position.x += 10;
* }
* ```
*/
public hasComponent<T extends Component>(type: ComponentType<T>): boolean {
if (!ComponentRegistry.isRegistered(type)) {
@@ -470,13 +499,22 @@ export class Entity {
/**
* 获取或创建指定类型的组件
*
* @param type - 组件类型
* @param args - 组件构造函数参数(仅在创建时使用)
*
* 如果组件已存在则返回现有组件,否则创建新组件并添加到实体
*
* @param type - 组件类型构造函数
* @param args - 组件构造函数参数(仅在创建新组件时使用)
* @returns 组件实例
*
* @example
* ```typescript
* // 确保实体拥有Position组件
* const position = entity.getOrCreateComponent(Position, 0, 0);
* position.x = 100;
* ```
*/
public getOrCreateComponent<T extends Component>(
type: ComponentType<T>,
type: ComponentType<T>,
...args: any[]
): T {
let component = this.getComponent(type);

View File

@@ -9,6 +9,7 @@ import { TypeSafeEventSystem } from './Core/EventSystem';
import { EventBus } from './Core/EventBus';
import { IScene, ISceneConfig } from './IScene';
import { getComponentInstanceTypeName, getSystemInstanceTypeName } from './Decorators';
import { TypedQueryBuilder } from './Core/Query/TypedQuery';
/**
* 游戏场景默认实现类
@@ -319,6 +320,70 @@ export class Scene implements IScene {
return this.findEntitiesByTag(tag);
}
/**
* 查询拥有所有指定组件的实体
*
* @param componentTypes - 组件类型数组
* @returns 查询结果
*
* @example
* ```typescript
* const result = scene.queryAll(Position, Velocity);
* for (const entity of result.entities) {
* const pos = entity.getComponent(Position);
* const vel = entity.getComponent(Velocity);
* }
* ```
*/
public queryAll(...componentTypes: any[]): { entities: readonly Entity[] } {
return this.querySystem.queryAll(...componentTypes);
}
/**
* 查询拥有任意一个指定组件的实体
*
* @param componentTypes - 组件类型数组
* @returns 查询结果
*/
public queryAny(...componentTypes: any[]): { entities: readonly Entity[] } {
return this.querySystem.queryAny(...componentTypes);
}
/**
* 查询不包含指定组件的实体
*
* @param componentTypes - 组件类型数组
* @returns 查询结果
*/
public queryNone(...componentTypes: any[]): { entities: readonly Entity[] } {
return this.querySystem.queryNone(...componentTypes);
}
/**
* 创建类型安全的查询构建器
*
* @returns 查询构建器,支持链式调用
*
* @example
* ```typescript
* // 使用查询构建器
* const matcher = scene.query()
* .withAll(Position, Velocity)
* .withNone(Disabled)
* .buildMatcher();
*
* // 在System中使用
* class MovementSystem extends EntitySystem {
* constructor() {
* super(matcher);
* }
* }
* ```
*/
public query(): TypedQueryBuilder {
return new TypedQueryBuilder();
}
/**
* 在场景中添加一个EntitySystem处理器
* @param processor 处理器

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;
}
}

View File

@@ -0,0 +1,307 @@
/**
* Entity类型安全工具函数
*
* 提供类型安全的组件操作工具函数无需修改Entity类
*/
import { Entity } from './Entity';
import type { Component } from './Component';
import type { ComponentType } from './Core/ComponentStorage';
import type { ComponentConstructor, ComponentInstance } from '../Types/TypeHelpers';
/**
* 获取组件,如果不存在则抛出错误
*
* @param entity - 实体实例
* @param componentType - 组件类型构造函数
* @returns 组件实例(保证非空)
* @throws {Error} 如果组件不存在
*
* @example
* ```typescript
* const position = requireComponent(entity, Position);
* position.x += 10;
* ```
*/
export function requireComponent<T extends ComponentConstructor>(
entity: Entity,
componentType: T
): ComponentInstance<T> {
const component = entity.getComponent(componentType as unknown as ComponentType<ComponentInstance<T>>);
if (!component) {
throw new Error(
`Component ${componentType.name} not found on entity ${entity.name} (id: ${entity.id})`
);
}
return component;
}
/**
* 尝试获取组件
*
* @param entity - 实体实例
* @param componentType - 组件类型构造函数
* @returns 组件实例或undefined
*
* @example
* ```typescript
* const health = tryGetComponent(entity, Health);
* if (health) {
* health.value -= 10;
* }
* ```
*/
export function tryGetComponent<T extends ComponentConstructor>(
entity: Entity,
componentType: T
): ComponentInstance<T> | undefined {
const component = entity.getComponent(componentType as unknown as ComponentType<ComponentInstance<T>>);
return component !== null ? component : undefined;
}
/**
* 批量获取组件
*
* @param entity - 实体实例
* @param types - 组件类型构造函数数组
* @returns 组件实例元组每个元素可能为null
*
* @example
* ```typescript
* const [pos, vel, health] = getComponents(entity, Position, Velocity, Health);
* if (pos && vel && health) {
* pos.x += vel.dx;
* }
* ```
*/
export function getComponents<T extends readonly ComponentConstructor[]>(
entity: Entity,
...types: T
): { [K in keyof T]: ComponentInstance<T[K]> | null } {
return types.map((type) =>
entity.getComponent(type as unknown as ComponentType<ComponentInstance<typeof type>>)
) as { [K in keyof T]: ComponentInstance<T[K]> | null };
}
/**
* 检查实体是否拥有所有指定的组件
*
* @param entity - 实体实例
* @param types - 组件类型构造函数数组
* @returns 如果拥有所有组件返回true否则返回false
*
* @example
* ```typescript
* if (hasComponents(entity, Position, Velocity)) {
* const pos = entity.getComponent(Position)!;
* const vel = entity.getComponent(Velocity)!;
* }
* ```
*/
export function hasComponents(entity: Entity, ...types: ComponentConstructor[]): boolean {
return types.every((type) => entity.hasComponent(type as unknown as ComponentType));
}
/**
* 检查实体是否拥有至少一个指定的组件
*
* @param entity - 实体实例
* @param types - 组件类型构造函数数组
* @returns 如果拥有任意一个组件返回true否则返回false
*/
export function hasAnyComponent(entity: Entity, ...types: ComponentConstructor[]): boolean {
return types.some((type) => entity.hasComponent(type as unknown as ComponentType));
}
/**
* 添加组件并立即配置
*
* @param entity - 实体实例
* @param component - 组件实例
* @param configure - 配置回调函数
* @returns 实体实例(支持链式调用)
*
* @example
* ```typescript
* addAndConfigure(entity, new Health(), health => {
* health.maxValue = 100;
* health.value = 50;
* });
* ```
*/
export function addAndConfigure<T extends Component>(
entity: Entity,
component: T,
configure: (component: T) => void
): Entity {
entity.addComponent(component);
configure(component);
return entity;
}
/**
* 获取或添加组件
*
* 如果组件已存在则返回现有组件,否则通过工厂函数创建并添加
*
* @param entity - 实体实例
* @param componentType - 组件类型构造函数
* @param factory - 组件工厂函数(仅在组件不存在时调用)
* @returns 组件实例
*
* @example
* ```typescript
* const health = getOrAddComponent(entity, Health, () => new Health(100));
* ```
*/
export function getOrAddComponent<T extends ComponentConstructor>(
entity: Entity,
componentType: T,
factory: () => ComponentInstance<T>
): ComponentInstance<T> {
let component = entity.getComponent(componentType as unknown as ComponentType<ComponentInstance<T>>);
if (!component) {
component = factory();
entity.addComponent(component);
}
return component;
}
/**
* 更新组件的部分字段
*
* @param entity - 实体实例
* @param componentType - 组件类型构造函数
* @param data - 要更新的部分数据
* @returns 如果更新成功返回true组件不存在返回false
*
* @example
* ```typescript
* updateComponent(entity, Position, { x: 100 });
* ```
*/
export function updateComponent<T extends ComponentConstructor>(
entity: Entity,
componentType: T,
data: Partial<ComponentInstance<T>>
): boolean {
const component = entity.getComponent(componentType as unknown as ComponentType<ComponentInstance<T>>);
if (!component) {
return false;
}
Object.assign(component, data);
return true;
}
/**
* 类型安全的实体构建器
*
* @example
* ```typescript
* const player = buildEntity(scene.createEntity("Player"))
* .with(new Position(100, 100))
* .with(new Velocity(0, 0))
* .withTag(1)
* .build();
* ```
*/
export class TypedEntityBuilder {
private _entity: Entity;
constructor(entity: Entity) {
this._entity = entity;
}
/**
* 添加组件
*/
with<T extends Component>(component: T): this {
this._entity.addComponent(component);
return this;
}
/**
* 添加并配置组件
*/
withConfigured<T extends Component>(
component: T,
configure: (component: T) => void
): this {
this._entity.addComponent(component);
configure(component);
return this;
}
/**
* 设置标签
*/
withTag(tag: number): this {
this._entity.tag = tag;
return this;
}
/**
* 设置名称
*/
withName(name: string): this {
this._entity.name = name;
return this;
}
/**
* 设置激活状态
*/
withActive(active: boolean): this {
this._entity.active = active;
return this;
}
/**
* 设置启用状态
*/
withEnabled(enabled: boolean): this {
this._entity.enabled = enabled;
return this;
}
/**
* 设置更新顺序
*/
withUpdateOrder(order: number): this {
this._entity.updateOrder = order;
return this;
}
/**
* 添加子实体
*/
withChild(child: Entity): this {
this._entity.addChild(child);
return this;
}
/**
* 完成构建
*/
build(): Entity {
return this._entity;
}
/**
* 获取正在构建的实体
*/
get entity(): Entity {
return this._entity;
}
}
/**
* 创建类型安全的实体构建器
*
* @param entity - 要包装的实体
* @returns 实体构建器
*/
export function buildEntity(entity: Entity): TypedEntityBuilder {
return new TypedEntityBuilder(entity);
}

View File

@@ -0,0 +1,295 @@
/**
* TypeScript类型工具集
*
* 提供高级类型推断和类型安全的工具类型
*/
import type { IComponent } from './index';
import { Component } from '../ECS/Component';
/**
* 组件类型提取器
* 从组件构造函数中提取实例类型
*/
export type ComponentInstance<T> = T extends new (...args: any[]) => infer R ? R : never;
/**
* 组件构造函数类型
*
* 与 ComponentType 保持一致,避免类型转换
*/
export type ComponentConstructor<T extends IComponent = IComponent> = new (...args: any[]) => T;
/**
* 组件类型的通用约束
*
* 用于确保类型参数是有效的组件构造函数
*/
export type AnyComponentConstructor = ComponentConstructor<any>;
/**
* 多组件类型提取
* 从组件构造函数数组中提取所有实例类型的联合
*/
export type ExtractComponents<T extends readonly ComponentConstructor[]> = {
[K in keyof T]: ComponentInstance<T[K]>;
};
/**
* 组件类型映射
* 将组件构造函数数组转换为实例类型的元组
*/
export type ComponentTypeMap<T extends readonly ComponentConstructor[]> = {
[K in keyof T]: T[K] extends ComponentConstructor<infer C> ? C : never;
};
/**
* 实体with组件的类型
* 表示一个实体确定拥有某些组件
*/
export interface EntityWithComponents<T extends readonly ComponentConstructor[]> {
readonly id: number;
readonly name: string;
/**
* 类型安全的组件获取
* 确保返回非空的组件实例
*/
getComponent<C extends ComponentConstructor>(componentType: C): ComponentInstance<C>;
/**
* 检查是否拥有组件
*/
hasComponent<C extends ComponentConstructor>(componentType: C): boolean;
/**
* 获取所有组件
*/
readonly components: ComponentTypeMap<T>;
}
/**
* 查询结果类型
* 根据查询条件推断实体必定拥有的组件
*/
export type QueryResult<
All extends readonly ComponentConstructor[] = [],
Any extends readonly ComponentConstructor[] = [],
None extends readonly ComponentConstructor[] = []
> = {
/**
* 实体列表确保拥有All中的所有组件
*/
readonly entities: ReadonlyArray<EntityWithComponents<All>>;
/**
* 实体数量
*/
readonly length: number;
/**
* 遍历实体
*/
forEach(callback: (entity: EntityWithComponents<All>, index: number) => void): void;
/**
* 映射转换
*/
map<R>(callback: (entity: EntityWithComponents<All>, index: number) => R): R[];
/**
* 过滤实体
*/
filter(predicate: (entity: EntityWithComponents<All>, index: number) => boolean): QueryResult<All, Any, None>;
};
/**
* System处理的实体类型
* 根据Matcher推断System处理的实体类型
*/
export type SystemEntityType<M> = M extends {
getCondition(): {
all: infer All extends readonly ComponentConstructor[];
};
}
? EntityWithComponents<All>
: never;
/**
* 组件字段类型提取
* 提取组件中所有可序列化的字段
*/
export type SerializableFields<T> = {
[K in keyof T]: T[K] extends Function ? never : K;
}[keyof T];
/**
* 只读组件类型
* 将组件的所有字段转为只读
*/
export type ReadonlyComponent<T extends IComponent> = {
readonly [K in keyof T]: T[K];
};
/**
* 部分组件类型
* 用于组件更新操作
*/
export type PartialComponent<T extends IComponent> = {
[K in SerializableFields<T>]?: T[K];
};
/**
* 组件类型约束
* 确保类型参数是有效的组件
*/
export type ValidComponent<T> = T extends Component ? T : never;
/**
* 组件数组约束
* 确保数组中的所有元素都是组件构造函数
*/
export type ValidComponentArray<T extends readonly any[]> = T extends readonly ComponentConstructor[]
? T
: never;
/**
* 事件处理器类型
* 提供类型安全的事件处理
*/
export type TypedEventHandler<T> = (data: T) => void | Promise<void>;
/**
* 系统生命周期钩子类型
*/
export interface SystemLifecycleHooks<T extends readonly ComponentConstructor[]> {
/**
* 实体添加到系统时调用
*/
onAdded?: (entity: EntityWithComponents<T>) => void;
/**
* 实体从系统移除时调用
*/
onRemoved?: (entity: EntityWithComponents<T>) => void;
/**
* 系统初始化时调用
*/
onInitialize?: () => void;
/**
* 系统销毁时调用
*/
onDestroy?: () => void;
}
/**
* Fluent API构建器类型
*/
export interface TypeSafeBuilder<T> {
/**
* 完成构建
*/
build(): T;
}
/**
* 组件池类型
*/
export interface ComponentPool<T extends IComponent> {
/**
* 从池中获取组件实例
*/
obtain(): T;
/**
* 归还组件到池中
*/
free(component: T): void;
/**
* 清空池
*/
clear(): void;
/**
* 池中可用对象数量
*/
readonly available: number;
}
/**
* 实体查询条件类型
*/
export interface TypedQueryCondition<
All extends readonly ComponentConstructor[] = [],
Any extends readonly ComponentConstructor[] = [],
None extends readonly ComponentConstructor[] = []
> {
all: All;
any: Any;
none: None;
tag?: number;
name?: string;
}
/**
* 组件类型守卫
*/
export function isComponentType<T extends IComponent>(
value: any
): value is ComponentConstructor<T> {
return typeof value === 'function' && value.prototype instanceof Component;
}
/**
* 类型安全的组件数组守卫
*/
export function isComponentArray(
value: any[]
): value is ComponentConstructor[] {
return value.every(isComponentType);
}
/**
* 提取组件类型名称(编译时)
*/
export type ComponentTypeName<T extends ComponentConstructor> = T extends {
prototype: { constructor: { name: infer N } };
}
? N
: string;
/**
* 多组件类型名称联合
*/
export type ComponentTypeNames<T extends readonly ComponentConstructor[]> = {
[K in keyof T]: ComponentTypeName<T[K]>;
}[number];
/**
* 深度只读类型
*/
export type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
/**
* 深度可选类型
*/
export type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};
/**
* 排除方法的类型
*/
export type DataOnly<T> = {
[K in keyof T as T[K] extends Function ? never : K]: T[K];
};
/**
* 可序列化的组件数据
*/
export type SerializableComponent<T extends IComponent> = DeepPartial<DataOnly<T>>;

View File

@@ -2,6 +2,9 @@
* 框架核心类型定义
*/
// 导出TypeScript类型增强工具
export * from './TypeHelpers';
/**
* 组件接口
*

View File

@@ -27,6 +27,11 @@ export type { ILogger, LoggerConfig } from './Utils/Logger';
// ECS核心组件
export * from './ECS';
// TypeScript类型增强API
export * from './ECS/TypedEntity';
export * from './ECS/Systems/TypedEntitySystem';
export * from './ECS/Core/Query/TypedQuery';
// 事件系统
export { ECSEventType, EventPriority, EVENT_TYPES, EventTypeValidator } from './ECS/CoreEvents';