Compare commits

...

3 Commits

Author SHA1 Message Date
YHH
3c7c3c98af style(core): 统一代码风格并强化命名规范 2025-10-31 23:53:39 +08:00
YHH
be7b3afb4a style(core): 统一代码风格并强化命名规范 2025-10-31 18:33:31 +08:00
YHH
3e037f4ae0 style(core): 统一代码风格并强化命名规范 2025-10-31 18:29:53 +08:00
88 changed files with 1126 additions and 988 deletions

View File

@@ -31,9 +31,32 @@
"@typescript-eslint/no-unsafe-call": "warn", "@typescript-eslint/no-unsafe-call": "warn",
"@typescript-eslint/no-unsafe-return": "warn", "@typescript-eslint/no-unsafe-return": "warn",
"@typescript-eslint/no-unsafe-argument": "warn", "@typescript-eslint/no-unsafe-argument": "warn",
"@typescript-eslint/no-unsafe-function-type": "error",
"@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }], "@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }],
"@typescript-eslint/no-non-null-assertion": "off" "@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "memberLike",
"modifiers": ["private"],
"format": ["camelCase"],
"leadingUnderscore": "require"
},
{
"selector": "memberLike",
"modifiers": ["public"],
"format": ["camelCase"],
"leadingUnderscore": "forbid"
},
{
"selector": "memberLike",
"modifiers": ["protected"],
"format": ["camelCase"],
"leadingUnderscore": "require"
}
]
}, },
"ignorePatterns": [ "ignorePatterns": [
"node_modules/", "node_modules/",

View File

@@ -329,8 +329,8 @@ export class Core {
*/ */
public static setScene<T extends IScene>(scene: T): T { public static setScene<T extends IScene>(scene: T): T {
if (!this._instance) { if (!this._instance) {
Core._logger.warn("Core实例未创建请先调用Core.create()"); Core._logger.warn('Core实例未创建请先调用Core.create()');
throw new Error("Core实例未创建"); throw new Error('Core实例未创建');
} }
return this._instance._sceneManager.setScene(scene); return this._instance._sceneManager.setScene(scene);
@@ -387,7 +387,7 @@ export class Core {
*/ */
public static loadScene<T extends IScene>(scene: T): void { public static loadScene<T extends IScene>(scene: T): void {
if (!this._instance) { if (!this._instance) {
Core._logger.warn("Core实例未创建请先调用Core.create()"); Core._logger.warn('Core实例未创建请先调用Core.create()');
return; return;
} }
@@ -422,7 +422,7 @@ export class Core {
*/ */
public static update(deltaTime: number): void { public static update(deltaTime: number): void {
if (!this._instance) { if (!this._instance) {
Core._logger.warn("Core实例未创建请先调用Core.create()"); Core._logger.warn('Core实例未创建请先调用Core.create()');
return; return;
} }
@@ -472,7 +472,7 @@ export class Core {
*/ */
public static enableDebug(config: IECSDebugConfig): void { public static enableDebug(config: IECSDebugConfig): void {
if (!this._instance) { if (!this._instance) {
Core._logger.warn("Core实例未创建请先调用Core.create()"); Core._logger.warn('Core实例未创建请先调用Core.create()');
return; return;
} }

View File

@@ -76,8 +76,8 @@ export interface UpdatableMetadata {
* ``` * ```
*/ */
export function Injectable(): ClassDecorator { export function Injectable(): ClassDecorator {
return function (target: Function): void { return function (target: Constructor): void {
const existing = injectableMetadata.get(target as Constructor); const existing = injectableMetadata.get(target);
injectableMetadata.set(target as Constructor, { injectableMetadata.set(target as Constructor, {
injectable: true, injectable: true,
@@ -117,13 +117,13 @@ export function Injectable(): ClassDecorator {
* ``` * ```
*/ */
export function Updatable(priority: number = 0): ClassDecorator { export function Updatable(priority: number = 0): ClassDecorator {
return function (target: Function): void { return function (target: Constructor): void {
// 验证类原型上是否有update方法 // 验证类原型上是否有update方法
const prototype = (target as Constructor & { prototype: { update?: unknown } }).prototype; const prototype = (target as Constructor & { prototype: { update?: unknown } }).prototype;
if (!prototype || typeof prototype.update !== 'function') { if (!prototype || typeof prototype.update !== 'function') {
throw new Error( throw new Error(
`@Updatable() decorator requires class ${target.name} to implement IUpdatable interface with update() method. ` + `@Updatable() decorator requires class ${target.name} to implement IUpdatable interface with update() method. ` +
`Please add 'implements IUpdatable' and define update(deltaTime?: number): void method.` "Please add 'implements IUpdatable' and define update(deltaTime?: number): void method."
); );
} }
@@ -228,6 +228,7 @@ export function getInjectMetadata(target: Constructor): Map<number, ServiceType<
* const instance = createInstance(MySystem, container); * const instance = createInstance(MySystem, container);
* ``` * ```
*/ */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function createInstance<T>( export function createInstance<T>(
constructor: new (...args: any[]) => T, constructor: new (...args: any[]) => T,
container: ServiceContainer container: ServiceContainer
@@ -249,7 +250,7 @@ export function createInstance<T>(
if (typeof serviceType === 'string' || typeof serviceType === 'symbol') { if (typeof serviceType === 'string' || typeof serviceType === 'symbol') {
// 字符串或Symbol类型的服务标识 // 字符串或Symbol类型的服务标识
throw new Error( throw new Error(
`String and Symbol service identifiers are not yet supported in constructor injection. ` + 'String and Symbol service identifiers are not yet supported in constructor injection. ' +
`Please use class types for ${constructor.name} parameter ${i}` `Please use class types for ${constructor.name} parameter ${i}`
); );
} else { } else {
@@ -338,7 +339,7 @@ export function registerInjectable<T extends IService>(
if (!isInjectable(serviceType)) { if (!isInjectable(serviceType)) {
throw new Error( throw new Error(
`${serviceType.name} is not marked as @Injectable(). ` + `${serviceType.name} is not marked as @Injectable(). ` +
`Please add @Injectable() decorator to the class.` 'Please add @Injectable() decorator to the class.'
); );
} }

View File

@@ -19,8 +19,9 @@ export interface IService {
* 服务类型 * 服务类型
* *
* 支持任意构造函数签名,以便与依赖注入装饰器配合使用 * 支持任意构造函数签名,以便与依赖注入装饰器配合使用
* 使用 any[] 以允许任意参数类型的构造函数 * 使用 any[] 以允许任意参数类型的构造函数,这是类型系统的必要妥协
*/ */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type ServiceType<T extends IService> = new (...args: any[]) => T; export type ServiceType<T extends IService> = new (...args: any[]) => T;
/** /**
@@ -240,7 +241,7 @@ export class ServiceContainer {
// 检测循环依赖 // 检测循环依赖
if (this._resolving.has(type as ServiceType<IService>)) { if (this._resolving.has(type as ServiceType<IService>)) {
const chain = Array.from(this._resolving).map(t => t.name).join(' -> '); const chain = Array.from(this._resolving).map((t) => t.name).join(' -> ');
throw new Error(`Circular dependency detected: ${chain} -> ${type.name}`); throw new Error(`Circular dependency detected: ${chain} -> ${type.name}`);
} }
@@ -337,7 +338,7 @@ export class ServiceContainer {
// 如果有单例实例,调用 dispose // 如果有单例实例,调用 dispose
if (registration.instance) { if (registration.instance) {
// 从可更新列表中移除 // 从可更新列表中移除
const index = this._updatableServices.findIndex(item => item.instance === registration.instance); const index = this._updatableServices.findIndex((item) => item.instance === registration.instance);
if (index !== -1) { if (index !== -1) {
this._updatableServices.splice(index, 1); this._updatableServices.splice(index, 1);
} }

View File

@@ -36,7 +36,16 @@ export abstract class Component implements IComponent {
* *
* 用于为每个组件分配唯一的ID。 * 用于为每个组件分配唯一的ID。
*/ */
public static _idGenerator: number = 0; private static _nextId: number = 0;
/**
* 获取下一个组件ID只读
*
* @returns 下一个将要分配的组件ID
*/
public static get nextComponentId(): number {
return Component._nextId;
}
/** /**
* 组件唯一标识符 * 组件唯一标识符
@@ -58,7 +67,7 @@ export abstract class Component implements IComponent {
* 自动分配唯一ID给组件。 * 自动分配唯一ID给组件。
*/ */
constructor() { constructor() {
this.id = Component._idGenerator++; this.id = Component._nextId++;
} }
/** /**

View File

@@ -1,7 +1,7 @@
import { Entity } from '../Entity'; import { Entity } from '../Entity';
import { ComponentType, ComponentRegistry } from './ComponentStorage'; import { ComponentType, ComponentRegistry } from './ComponentStorage';
import { BitMask64Data, BitMask64Utils } from "../Utils"; import { BitMask64Data, BitMask64Utils } from '../Utils';
import { BitMaskHashMap } from "../Utils/BitMaskHashMap"; import { BitMaskHashMap } from '../Utils/BitMaskHashMap';
/** /**
* 原型标识符 * 原型标识符
@@ -247,7 +247,7 @@ export class ArchetypeSystem {
*/ */
private updateAllArchetypeArrays(): void { private updateAllArchetypeArrays(): void {
this._allArchetypes = []; this._allArchetypes = [];
for (let archetype of this._archetypes.values()) { for (const archetype of this._archetypes.values()) {
this._allArchetypes.push(archetype); this._allArchetypes.push(archetype);
} }
} }
@@ -258,7 +258,7 @@ export class ArchetypeSystem {
private getEntityComponentTypes(entity: Entity): ComponentType[] { private getEntityComponentTypes(entity: Entity): ComponentType[] {
let componentTypes = this._entityComponentTypesCache.get(entity); let componentTypes = this._entityComponentTypesCache.get(entity);
if (!componentTypes) { if (!componentTypes) {
componentTypes = entity.components.map(component => component.constructor as ComponentType); componentTypes = entity.components.map((component) => component.constructor as ComponentType);
this._entityComponentTypesCache.set(entity, componentTypes); this._entityComponentTypesCache.set(entity, componentTypes);
} }
return componentTypes; return componentTypes;
@@ -269,7 +269,7 @@ export class ArchetypeSystem {
* 使用ComponentRegistry确保与Entity.componentMask使用相同的bitIndex * 使用ComponentRegistry确保与Entity.componentMask使用相同的bitIndex
*/ */
private generateArchetypeId(componentTypes: ComponentType[]): ArchetypeId { private generateArchetypeId(componentTypes: ComponentType[]): ArchetypeId {
let mask = BitMask64Utils.clone(BitMask64Utils.ZERO); const mask = BitMask64Utils.clone(BitMask64Utils.ZERO);
for (const type of componentTypes) { for (const type of componentTypes) {
if (!ComponentRegistry.isRegistered(type)) { if (!ComponentRegistry.isRegistered(type)) {
ComponentRegistry.register(type); ComponentRegistry.register(type);

View File

@@ -9,7 +9,6 @@ import { ComponentRegistry, ComponentType } from './ComponentStorage/ComponentRe
export { ComponentRegistry, ComponentType }; export { ComponentRegistry, ComponentType };
/** /**
* 高性能组件存储器 * 高性能组件存储器
*/ */
@@ -152,7 +151,7 @@ export class ComponentStorage<T extends Component> {
usedSlots: number; usedSlots: number;
freeSlots: number; freeSlots: number;
fragmentation: number; fragmentation: number;
} { } {
const totalSlots = this.dense.length; const totalSlots = this.dense.length;
const usedSlots = this.dense.length; const usedSlots = this.dense.length;
const freeSlots = 0; // 永远无空洞 const freeSlots = 0; // 永远无空洞
@@ -173,7 +172,7 @@ export class ComponentStorage<T extends Component> {
*/ */
export class ComponentStorageManager { export class ComponentStorageManager {
private static readonly _logger = createLogger('ComponentStorage'); private static readonly _logger = createLogger('ComponentStorage');
private storages = new Map<Function, ComponentStorage<Component> | SoAStorage<Component>>(); private storages = new Map<ComponentType, ComponentStorage<Component> | SoAStorage<Component>>();
/** /**
* 检查组件类型是否启用SoA存储 * 检查组件类型是否启用SoA存储
@@ -342,7 +341,7 @@ export class ComponentStorageManager {
* @returns 组件位掩码 * @returns 组件位掩码
*/ */
public getComponentMask(entityId: number): BitMask64Data { public getComponentMask(entityId: number): BitMask64Data {
let mask = BitMask64Utils.clone(BitMask64Utils.ZERO); const mask = BitMask64Utils.clone(BitMask64Utils.ZERO);
for (const [componentType, storage] of this.storages.entries()) { for (const [componentType, storage] of this.storages.entries()) {
if (storage.hasComponent(entityId)) { if (storage.hasComponent(entityId)) {

View File

@@ -6,6 +6,7 @@ import { getComponentTypeName } from '../../Decorators';
/** /**
* 组件类型定义 * 组件类型定义
*/ */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type ComponentType<T extends Component = Component> = new (...args: any[]) => T; export type ComponentType<T extends Component = Component> = new (...args: any[]) => T;
/** /**
@@ -14,9 +15,9 @@ export type ComponentType<T extends Component = Component> = new (...args: any[]
*/ */
export class ComponentRegistry { export class ComponentRegistry {
protected static readonly _logger = createLogger('ComponentStorage'); protected static readonly _logger = createLogger('ComponentStorage');
private static componentTypes = new Map<Function, number>(); private static componentTypes = new Map<ComponentType, number>();
private static bitIndexToType = new Map<number, Function>(); private static bitIndexToType = new Map<number, ComponentType>();
private static componentNameToType = new Map<string, Function>(); private static componentNameToType = new Map<string, ComponentType>();
private static componentNameToId = new Map<string, number>(); private static componentNameToId = new Map<string, number>();
private static maskCache = new Map<string, BitMask64Data>(); private static maskCache = new Map<string, BitMask64Data>();
private static nextBitIndex = 0; private static nextBitIndex = 0;
@@ -102,7 +103,7 @@ export class ComponentRegistry {
* @param componentName 组件名称 * @param componentName 组件名称
* @returns 组件类型构造函数 * @returns 组件类型构造函数
*/ */
public static getComponentType(componentName: string): Function | null { public static getComponentType(componentName: string): ComponentType | null {
return this.componentNameToType.get(componentName) || null; return this.componentNameToType.get(componentName) || null;
} }
@@ -110,7 +111,7 @@ export class ComponentRegistry {
* 获取所有已注册的组件类型 * 获取所有已注册的组件类型
* @returns 组件类型映射 * @returns 组件类型映射
*/ */
public static getAllRegisteredTypes(): Map<Function, number> { public static getAllRegisteredTypes(): Map<ComponentType, number> {
return new Map(this.componentTypes); return new Map(this.componentTypes);
} }
@@ -118,7 +119,7 @@ export class ComponentRegistry {
* 获取所有组件名称到类型的映射 * 获取所有组件名称到类型的映射
* @returns 名称到类型的映射 * @returns 名称到类型的映射
*/ */
public static getAllComponentNames(): Map<string, Function> { public static getAllComponentNames(): Map<string, ComponentType> {
return new Map(this.componentNameToType); return new Map(this.componentNameToType);
} }
@@ -181,7 +182,7 @@ export class ComponentRegistry {
return this.maskCache.get(cacheKey)!; return this.maskCache.get(cacheKey)!;
} }
let mask = BitMask64Utils.clone(BitMask64Utils.ZERO); const mask = BitMask64Utils.clone(BitMask64Utils.ZERO);
for (const name of componentNames) { for (const name of componentNames) {
const componentId = this.getComponentId(name); const componentId = this.getComponentId(name);
if (componentId !== undefined) { if (componentId !== undefined) {

View File

@@ -127,7 +127,7 @@ export class EventBus implements IEventBus {
handler: (data: T) => Promise<void>, handler: (data: T) => Promise<void>,
config: IEventListenerConfig = {} config: IEventListenerConfig = {}
): string { ): string {
return this.on(eventType, handler as any, { ...config, async: true }); return this.on(eventType, handler as (data: T) => void, { ...config, async: true });
} }
/** /**
@@ -466,4 +466,3 @@ export class GlobalEventBus {
} }
} }

View File

@@ -3,12 +3,12 @@ import { createLogger } from '../../Utils/Logger';
/** /**
* 事件处理器函数类型 * 事件处理器函数类型
*/ */
export type EventHandler<T = any> = (event: T) => void; export type EventHandler<T = unknown> = (event: T) => void;
/** /**
* 异步事件处理器函数类型 * 异步事件处理器函数类型
*/ */
export type AsyncEventHandler<T = any> = (event: T) => Promise<void>; export type AsyncEventHandler<T = unknown> = (event: T) => Promise<void>;
/** /**
* 事件监听器配置 * 事件监听器配置
@@ -21,13 +21,13 @@ export interface EventListenerConfig {
/** 是否异步执行 */ /** 是否异步执行 */
async?: boolean; async?: boolean;
/** 执行上下文 */ /** 执行上下文 */
context?: any; context?: unknown;
} }
/** /**
* 内部事件监听器 * 内部事件监听器
*/ */
interface InternalEventListener<T = any> { interface InternalEventListener<T = unknown> {
handler: EventHandler<T> | AsyncEventHandler<T>; handler: EventHandler<T> | AsyncEventHandler<T>;
config: EventListenerConfig; config: EventListenerConfig;
id: string; id: string;
@@ -71,8 +71,8 @@ export class TypeSafeEventSystem {
private static readonly _logger = createLogger('EventSystem'); private static readonly _logger = createLogger('EventSystem');
private listeners = new Map<string, InternalEventListener[]>(); private listeners = new Map<string, InternalEventListener[]>();
private stats = new Map<string, EventStats>(); private stats = new Map<string, EventStats>();
private batchQueue = new Map<string, any[]>(); private batchQueue = new Map<string, unknown[]>();
private batchTimers = new Map<string, number>(); private batchTimers = new Map<string, ReturnType<typeof setTimeout>>();
private batchConfigs = new Map<string, EventBatchConfig>(); private batchConfigs = new Map<string, EventBatchConfig>();
private nextListenerId = 0; private nextListenerId = 0;
private isEnabled = true; private isEnabled = true;
@@ -133,7 +133,7 @@ export class TypeSafeEventSystem {
const listeners = this.listeners.get(eventType); const listeners = this.listeners.get(eventType);
if (!listeners) return false; if (!listeners) return false;
const index = listeners.findIndex(l => l.id === listenerId); const index = listeners.findIndex((l) => l.id === listenerId);
if (index === -1) return false; if (index === -1) return false;
listeners.splice(index, 1); listeners.splice(index, 1);
@@ -353,7 +353,7 @@ export class TypeSafeEventSystem {
id: listenerId id: listenerId
}; };
listeners.push(listener); listeners.push(listener as InternalEventListener);
// 初始化统计信息 // 初始化统计信息
if (!this.stats.has(eventType)) { if (!this.stats.has(eventType)) {
@@ -379,8 +379,8 @@ export class TypeSafeEventSystem {
const sortedListeners = this.sortListenersByPriority(listeners); const sortedListeners = this.sortListenersByPriority(listeners);
// 分离同步和异步监听器 // 分离同步和异步监听器
const syncListeners = sortedListeners.filter(l => !l.config.async); const syncListeners = sortedListeners.filter((l) => !l.config.async);
const asyncListeners = sortedListeners.filter(l => l.config.async); const asyncListeners = sortedListeners.filter((l) => l.config.async);
// 执行同步监听器 // 执行同步监听器
for (const listener of syncListeners) { for (const listener of syncListeners) {
@@ -447,7 +447,7 @@ export class TypeSafeEventSystem {
if (!listeners) return; if (!listeners) return;
for (const id of listenerIds) { for (const id of listenerIds) {
const index = listeners.findIndex(l => l.id === id); const index = listeners.findIndex((l) => l.id === id);
if (index !== -1) { if (index !== -1) {
listeners.splice(index, 1); listeners.splice(index, 1);
} }
@@ -488,7 +488,7 @@ export class TypeSafeEventSystem {
this.flushBatch(eventType); this.flushBatch(eventType);
}, config.delay); }, config.delay);
this.batchTimers.set(eventType, timer as any); this.batchTimers.set(eventType, timer);
} }
} }
@@ -578,4 +578,3 @@ export class TypeSafeEventSystem {
*/ */
export const GlobalEventSystem = new TypeSafeEventSystem(); export const GlobalEventSystem = new TypeSafeEventSystem();

View File

@@ -164,7 +164,7 @@ export class ECSFluentAPI {
componentStats: Map<string, unknown>; componentStats: Map<string, unknown>;
queryStats: unknown; queryStats: unknown;
eventStats: Map<string, unknown>; eventStats: Map<string, unknown>;
} { } {
return { return {
entityCount: this.scene.entities.count, entityCount: this.scene.entities.count,
systemCount: this.scene.systems.length, systemCount: this.scene.systems.length,

View File

@@ -15,8 +15,8 @@ export class EntityBuilder {
this.scene = scene; this.scene = scene;
this.storageManager = storageManager; this.storageManager = storageManager;
const id = scene.identifierPool.checkOut(); const id = scene.identifierPool.checkOut();
this.entity = new Entity("", id); this.entity = new Entity('', id);
this.entity.scene = this.scene as any; this.entity.scene = this.scene;
} }
/** /**

View File

@@ -1,3 +1,2 @@
export { QuerySystem } from '../QuerySystem'; export { QuerySystem } from '../QuerySystem';
export { ECSFluentAPI, createECSAPI } from '../FluentAPI'; export { ECSFluentAPI, createECSAPI } from '../FluentAPI';

View File

@@ -131,7 +131,7 @@ export class QuerySystem {
if (entities.length === 0) return; if (entities.length === 0) return;
// 使用Set来快速检查重复 // 使用Set来快速检查重复
const existingIds = new Set(this.entities.map(e => e.id)); const existingIds = new Set(this.entities.map((e) => e.id));
let addedCount = 0; let addedCount = 0;
for (const entity of entities) { for (const entity of entities) {
@@ -679,7 +679,7 @@ export class QuerySystem {
} }
// 多组件查询:使用排序后的类型名称创建键 // 多组件查询:使用排序后的类型名称创建键
const sortKey = componentTypes.map(t => { const sortKey = componentTypes.map((t) => {
const name = getComponentTypeName(t); const name = getComponentTypeName(t);
return name; return name;
}).sort().join(','); }).sort().join(',');
@@ -810,7 +810,7 @@ export class QuerySystem {
*/ */
private createComponentMask(componentTypes: ComponentType[]): BitMask64Data { private createComponentMask(componentTypes: ComponentType[]): BitMask64Data {
// 生成缓存键 // 生成缓存键
const cacheKey = componentTypes.map(t => { const cacheKey = componentTypes.map((t) => {
return getComponentTypeName(t); return getComponentTypeName(t);
}).sort().join(','); }).sort().join(',');
@@ -821,7 +821,7 @@ export class QuerySystem {
} }
// 使用ComponentRegistry而不是ComponentTypeManager,确保bitIndex一致 // 使用ComponentRegistry而不是ComponentTypeManager,确保bitIndex一致
let mask = BitMask64Utils.clone(BitMask64Utils.ZERO); const mask = BitMask64Utils.clone(BitMask64Utils.ZERO);
for (const type of componentTypes) { for (const type of componentTypes) {
// 确保组件已注册 // 确保组件已注册
if (!ComponentRegistry.isRegistered(type)) { if (!ComponentRegistry.isRegistered(type)) {
@@ -843,11 +843,31 @@ export class QuerySystem {
return this._version; return this._version;
} }
/**
* 查询所有实体
*
* 返回场景中的所有实体,不进行任何过滤。
*
* @returns 所有实体的只读数组
*
* @example
* ```typescript
* const allEntities = scene.querySystem.queryAllEntities();
* console.log(`场景中共有 ${allEntities.length} 个实体`);
* ```
*/
public queryAllEntities(): readonly Entity[] {
return this.entities;
}
/** /**
* 获取所有实体 * 获取所有实体
*
* @deprecated 使用 queryAllEntities() 代替,以保持命名一致性
* @see {@link queryAllEntities}
*/ */
public getAllEntities(): readonly Entity[] { public getAllEntities(): readonly Entity[] {
return this.entities; return this.queryAllEntities();
} }
/** /**
@@ -875,13 +895,17 @@ export class QuerySystem {
cacheHitRate: string; cacheHitRate: string;
}; };
optimizationStats: { optimizationStats: {
archetypeSystem: any; archetypeSystem: Array<{
id: BitMask64Data;
componentTypes: string[];
entityCount: number;
}>;
}; };
cacheStats: { cacheStats: {
size: number; size: number;
hitRate: string; hitRate: string;
}; };
} { } {
return { return {
entityCount: this.entities.length, entityCount: this.entities.length,
indexStats: { indexStats: {
@@ -895,9 +919,9 @@ export class QuerySystem {
(this.queryStats.cacheHits / this.queryStats.totalQueries * 100).toFixed(2) + '%' : '0%' (this.queryStats.cacheHits / this.queryStats.totalQueries * 100).toFixed(2) + '%' : '0%'
}, },
optimizationStats: { optimizationStats: {
archetypeSystem: this.archetypeSystem.getAllArchetypes().map(a => ({ archetypeSystem: this.archetypeSystem.getAllArchetypes().map((a) => ({
id: a.id, id: a.id,
componentTypes: a.componentTypes.map(t => getComponentTypeName(t)), componentTypes: a.componentTypes.map((t) => getComponentTypeName(t)),
entityCount: a.entities.size entityCount: a.entities.size
})) }))
}, },
@@ -1023,7 +1047,7 @@ export class QuerySystem {
} }
case QueryConditionType.NONE: { case QueryConditionType.NONE: {
const mask = this.createComponentMask(componentTypes); const mask = this.createComponentMask(componentTypes);
return this.entities.filter(entity => return this.entities.filter((entity) =>
BitMask64Utils.hasNone(entity.componentMask, mask) BitMask64Utils.hasNone(entity.componentMask, mask)
); );
} }
@@ -1241,7 +1265,7 @@ export class QueryBuilder {
* 创建组件掩码 * 创建组件掩码
*/ */
private createComponentMask(componentTypes: ComponentType[]): BitMask64Data { private createComponentMask(componentTypes: ComponentType[]): BitMask64Data {
let mask = BitMask64Utils.clone(BitMask64Utils.ZERO); const mask = BitMask64Utils.clone(BitMask64Utils.ZERO);
for (const type of componentTypes) { for (const type of componentTypes) {
try { try {
const bitMask = ComponentRegistry.getBitMask(type); const bitMask = ComponentRegistry.getBitMask(type);

View File

@@ -136,7 +136,7 @@ export class ReactiveQuery {
private generateQueryId(): string { private generateQueryId(): string {
const typeStr = this._condition.type; const typeStr = this._condition.type;
const componentsStr = this._condition.componentTypes const componentsStr = this._condition.componentTypes
.map(t => t.name) .map((t) => t.name)
.sort() .sort()
.join(','); .join(',');
return `${typeStr}:${componentsStr}`; return `${typeStr}:${componentsStr}`;

View File

@@ -39,15 +39,22 @@ interface IWeakRefConstructor {
new <T extends object>(target: T): IWeakRef<T>; new <T extends object>(target: T): IWeakRef<T>;
} }
/**
* 包含 WeakRef 的全局对象类型
*/
interface GlobalWithWeakRef {
WeakRef?: IWeakRefConstructor;
}
/** /**
* WeakRef 实现 * WeakRef 实现
* *
* 优先使用原生 WeakRef不支持时降级到 Polyfill * 优先使用原生 WeakRef不支持时降级到 Polyfill
*/ */
const WeakRefImpl: IWeakRefConstructor = ( const WeakRefImpl: IWeakRefConstructor = (
(typeof globalThis !== 'undefined' && (globalThis as any).WeakRef) || (typeof globalThis !== 'undefined' && (globalThis as GlobalWithWeakRef).WeakRef) ||
(typeof global !== 'undefined' && (global as any).WeakRef) || (typeof global !== 'undefined' && (global as unknown as GlobalWithWeakRef).WeakRef) ||
(typeof window !== 'undefined' && (window as any).WeakRef) || (typeof window !== 'undefined' && (window as unknown as GlobalWithWeakRef).WeakRef) ||
WeakRefPolyfill WeakRefPolyfill
) as IWeakRefConstructor; ) as IWeakRefConstructor;
@@ -174,6 +181,8 @@ export class ReferenceTracker {
for (const record of validRecords) { for (const record of validRecords) {
const component = record.component.deref(); const component = record.component.deref();
if (component) { if (component) {
// 使用 any 进行动态属性访问,因为无法静态验证所有可能的组件属性
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(component as any)[record.propertyKey] = null; (component as any)[record.propertyKey] = null;
} }
} }
@@ -287,7 +296,7 @@ export class ReferenceTracker {
* 获取调试信息 * 获取调试信息
*/ */
public getDebugInfo(): object { public getDebugInfo(): object {
const info: Record<string, any> = {}; const info: Record<string, unknown> = {};
for (const [entityId, records] of this._references.entries()) { for (const [entityId, records] of this._references.entries()) {
const validRecords = []; const validRecords = [];

View File

@@ -2,12 +2,42 @@ import { Component } from '../Component';
import { ComponentType } from './ComponentStorage'; import { ComponentType } from './ComponentStorage';
import { createLogger } from '../../Utils/Logger'; import { createLogger } from '../../Utils/Logger';
/**
* 装饰器目标类型,用于存储元数据
*/
interface DecoratorTarget {
constructor: ComponentTypeWithMetadata;
}
/**
* 带有元数据的组件类型
*/
interface ComponentTypeWithMetadata {
__enableSoA?: boolean;
__highPrecisionFields?: Set<string>;
__float64Fields?: Set<string>;
__float32Fields?: Set<string>;
__int32Fields?: Set<string>;
__uint32Fields?: Set<string>;
__int16Fields?: Set<string>;
__uint16Fields?: Set<string>;
__int8Fields?: Set<string>;
__uint8Fields?: Set<string>;
__uint8ClampedFields?: Set<string>;
__serializeMapFields?: Set<string>;
__serializeSetFields?: Set<string>;
__serializeArrayFields?: Set<string>;
__deepCopyFields?: Set<string>;
__autoTypedFields?: Map<string, Record<string, unknown>>;
__bigIntFields?: Set<string>;
}
/** /**
* 启用SoA优化装饰器 * 启用SoA优化装饰器
* 默认关闭SoA只有在大规模批量操作场景下才建议开启 * 默认关闭SoA只有在大规模批量操作场景下才建议开启
*/ */
export function EnableSoA<T extends ComponentType>(target: T): T { export function EnableSoA<T extends ComponentType>(target: T): T {
(target as any).__enableSoA = true; (target as unknown as { __enableSoA: boolean }).__enableSoA = true;
return target; return target;
} }
@@ -16,7 +46,7 @@ export function EnableSoA<T extends ComponentType>(target: T): T {
* 高精度数值装饰器 * 高精度数值装饰器
* 标记字段需要保持完整精度存储为复杂对象而非TypedArray * 标记字段需要保持完整精度存储为复杂对象而非TypedArray
*/ */
export function HighPrecision(target: any, propertyKey: string | symbol): void { export function HighPrecision(target: DecoratorTarget, propertyKey: string | symbol): void {
const key = String(propertyKey); const key = String(propertyKey);
if (!target.constructor.__highPrecisionFields) { if (!target.constructor.__highPrecisionFields) {
target.constructor.__highPrecisionFields = new Set(); target.constructor.__highPrecisionFields = new Set();
@@ -28,7 +58,7 @@ export function HighPrecision(target: any, propertyKey: string | symbol): void {
* 64位浮点数装饰器 * 64位浮点数装饰器
* 标记字段使用Float64Array存储更高精度但更多内存 * 标记字段使用Float64Array存储更高精度但更多内存
*/ */
export function Float64(target: any, propertyKey: string | symbol): void { export function Float64(target: DecoratorTarget, propertyKey: string | symbol): void {
const key = String(propertyKey); const key = String(propertyKey);
if (!target.constructor.__float64Fields) { if (!target.constructor.__float64Fields) {
target.constructor.__float64Fields = new Set(); target.constructor.__float64Fields = new Set();
@@ -40,7 +70,7 @@ export function Float64(target: any, propertyKey: string | symbol): void {
* 32位浮点数装饰器 * 32位浮点数装饰器
* 标记字段使用Float32Array存储默认类型平衡性能和精度 * 标记字段使用Float32Array存储默认类型平衡性能和精度
*/ */
export function Float32(target: any, propertyKey: string | symbol): void { export function Float32(target: DecoratorTarget, propertyKey: string | symbol): void {
const key = String(propertyKey); const key = String(propertyKey);
if (!target.constructor.__float32Fields) { if (!target.constructor.__float32Fields) {
target.constructor.__float32Fields = new Set(); target.constructor.__float32Fields = new Set();
@@ -52,7 +82,7 @@ export function Float32(target: any, propertyKey: string | symbol): void {
* 32位整数装饰器 * 32位整数装饰器
* 标记字段使用Int32Array存储适用于整数值 * 标记字段使用Int32Array存储适用于整数值
*/ */
export function Int32(target: any, propertyKey: string | symbol): void { export function Int32(target: DecoratorTarget, propertyKey: string | symbol): void {
const key = String(propertyKey); const key = String(propertyKey);
if (!target.constructor.__int32Fields) { if (!target.constructor.__int32Fields) {
target.constructor.__int32Fields = new Set(); target.constructor.__int32Fields = new Set();
@@ -64,7 +94,7 @@ export function Int32(target: any, propertyKey: string | symbol): void {
* 32位无符号整数装饰器 * 32位无符号整数装饰器
* 标记字段使用Uint32Array存储适用于无符号整数如ID、标志位等 * 标记字段使用Uint32Array存储适用于无符号整数如ID、标志位等
*/ */
export function Uint32(target: any, propertyKey: string | symbol): void { export function Uint32(target: DecoratorTarget, propertyKey: string | symbol): void {
const key = String(propertyKey); const key = String(propertyKey);
if (!target.constructor.__uint32Fields) { if (!target.constructor.__uint32Fields) {
target.constructor.__uint32Fields = new Set(); target.constructor.__uint32Fields = new Set();
@@ -76,7 +106,7 @@ export function Uint32(target: any, propertyKey: string | symbol): void {
* 16位整数装饰器 * 16位整数装饰器
* 标记字段使用Int16Array存储适用于小范围整数 * 标记字段使用Int16Array存储适用于小范围整数
*/ */
export function Int16(target: any, propertyKey: string | symbol): void { export function Int16(target: DecoratorTarget, propertyKey: string | symbol): void {
const key = String(propertyKey); const key = String(propertyKey);
if (!target.constructor.__int16Fields) { if (!target.constructor.__int16Fields) {
target.constructor.__int16Fields = new Set(); target.constructor.__int16Fields = new Set();
@@ -88,7 +118,7 @@ export function Int16(target: any, propertyKey: string | symbol): void {
* 16位无符号整数装饰器 * 16位无符号整数装饰器
* 标记字段使用Uint16Array存储适用于小范围无符号整数 * 标记字段使用Uint16Array存储适用于小范围无符号整数
*/ */
export function Uint16(target: any, propertyKey: string | symbol): void { export function Uint16(target: DecoratorTarget, propertyKey: string | symbol): void {
const key = String(propertyKey); const key = String(propertyKey);
if (!target.constructor.__uint16Fields) { if (!target.constructor.__uint16Fields) {
target.constructor.__uint16Fields = new Set(); target.constructor.__uint16Fields = new Set();
@@ -100,7 +130,7 @@ export function Uint16(target: any, propertyKey: string | symbol): void {
* 8位整数装饰器 * 8位整数装饰器
* 标记字段使用Int8Array存储适用于很小的整数值 * 标记字段使用Int8Array存储适用于很小的整数值
*/ */
export function Int8(target: any, propertyKey: string | symbol): void { export function Int8(target: DecoratorTarget, propertyKey: string | symbol): void {
const key = String(propertyKey); const key = String(propertyKey);
if (!target.constructor.__int8Fields) { if (!target.constructor.__int8Fields) {
target.constructor.__int8Fields = new Set(); target.constructor.__int8Fields = new Set();
@@ -112,7 +142,7 @@ export function Int8(target: any, propertyKey: string | symbol): void {
* 8位无符号整数装饰器 * 8位无符号整数装饰器
* 标记字段使用Uint8Array存储适用于字节值、布尔标志等 * 标记字段使用Uint8Array存储适用于字节值、布尔标志等
*/ */
export function Uint8(target: any, propertyKey: string | symbol): void { export function Uint8(target: DecoratorTarget, propertyKey: string | symbol): void {
const key = String(propertyKey); const key = String(propertyKey);
if (!target.constructor.__uint8Fields) { if (!target.constructor.__uint8Fields) {
target.constructor.__uint8Fields = new Set(); target.constructor.__uint8Fields = new Set();
@@ -124,7 +154,7 @@ export function Uint8(target: any, propertyKey: string | symbol): void {
* 8位夹紧整数装饰器 * 8位夹紧整数装饰器
* 标记字段使用Uint8ClampedArray存储适用于颜色值等需要夹紧的数据 * 标记字段使用Uint8ClampedArray存储适用于颜色值等需要夹紧的数据
*/ */
export function Uint8Clamped(target: any, propertyKey: string | symbol): void { export function Uint8Clamped(target: DecoratorTarget, propertyKey: string | symbol): void {
const key = String(propertyKey); const key = String(propertyKey);
if (!target.constructor.__uint8ClampedFields) { if (!target.constructor.__uint8ClampedFields) {
target.constructor.__uint8ClampedFields = new Set(); target.constructor.__uint8ClampedFields = new Set();
@@ -137,7 +167,7 @@ export function Uint8Clamped(target: any, propertyKey: string | symbol): void {
* 序列化Map装饰器 * 序列化Map装饰器
* 标记Map字段需要序列化/反序列化存储 * 标记Map字段需要序列化/反序列化存储
*/ */
export function SerializeMap(target: any, propertyKey: string | symbol): void { export function SerializeMap(target: DecoratorTarget, propertyKey: string | symbol): void {
const key = String(propertyKey); const key = String(propertyKey);
if (!target.constructor.__serializeMapFields) { if (!target.constructor.__serializeMapFields) {
target.constructor.__serializeMapFields = new Set(); target.constructor.__serializeMapFields = new Set();
@@ -149,7 +179,7 @@ export function SerializeMap(target: any, propertyKey: string | symbol): void {
* 序列化Set装饰器 * 序列化Set装饰器
* 标记Set字段需要序列化/反序列化存储 * 标记Set字段需要序列化/反序列化存储
*/ */
export function SerializeSet(target: any, propertyKey: string | symbol): void { export function SerializeSet(target: DecoratorTarget, propertyKey: string | symbol): void {
const key = String(propertyKey); const key = String(propertyKey);
if (!target.constructor.__serializeSetFields) { if (!target.constructor.__serializeSetFields) {
target.constructor.__serializeSetFields = new Set(); target.constructor.__serializeSetFields = new Set();
@@ -161,7 +191,7 @@ export function SerializeSet(target: any, propertyKey: string | symbol): void {
* 序列化Array装饰器 * 序列化Array装饰器
* 标记Array字段需要序列化/反序列化存储 * 标记Array字段需要序列化/反序列化存储
*/ */
export function SerializeArray(target: any, propertyKey: string | symbol): void { export function SerializeArray(target: DecoratorTarget, propertyKey: string | symbol): void {
const key = String(propertyKey); const key = String(propertyKey);
if (!target.constructor.__serializeArrayFields) { if (!target.constructor.__serializeArrayFields) {
target.constructor.__serializeArrayFields = new Set(); target.constructor.__serializeArrayFields = new Set();
@@ -173,7 +203,7 @@ export function SerializeArray(target: any, propertyKey: string | symbol): void
* 深拷贝装饰器 * 深拷贝装饰器
* 标记字段需要深拷贝处理(适用于嵌套对象) * 标记字段需要深拷贝处理(适用于嵌套对象)
*/ */
export function DeepCopy(target: any, propertyKey: string | symbol): void { export function DeepCopy(target: DecoratorTarget, propertyKey: string | symbol): void {
const key = String(propertyKey); const key = String(propertyKey);
if (!target.constructor.__deepCopyFields) { if (!target.constructor.__deepCopyFields) {
target.constructor.__deepCopyFields = new Set(); target.constructor.__deepCopyFields = new Set();
@@ -197,7 +227,7 @@ export function AutoTyped(options?: {
precision?: boolean; precision?: boolean;
signed?: boolean; signed?: boolean;
}) { }) {
return function (target: any, propertyKey: string | symbol): void { return function (target: DecoratorTarget, propertyKey: string | symbol): void {
const key = String(propertyKey); const key = String(propertyKey);
if (!target.constructor.__autoTypedFields) { if (!target.constructor.__autoTypedFields) {
target.constructor.__autoTypedFields = new Map(); target.constructor.__autoTypedFields = new Map();
@@ -214,6 +244,7 @@ export class TypeInference {
/** /**
* 根据数值范围推断最优的TypedArray类型 * 根据数值范围推断最优的TypedArray类型
*/ */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public static inferOptimalType(value: any, options: { public static inferOptimalType(value: any, options: {
minValue?: number; minValue?: number;
maxValue?: number; maxValue?: number;
@@ -338,7 +369,7 @@ export class SoAStorage<T extends Component> {
private fields = new Map<string, SupportedTypedArray>(); private fields = new Map<string, SupportedTypedArray>();
private stringFields = new Map<string, string[]>(); // 专门存储字符串 private stringFields = new Map<string, string[]>(); // 专门存储字符串
private serializedFields = new Map<string, string[]>(); // 序列化存储Map/Set/Array private serializedFields = new Map<string, string[]>(); // 序列化存储Map/Set/Array
private complexFields = new Map<number, Map<string, any>>(); // 存储复杂对象 private complexFields = new Map<number, Map<string, unknown>>(); // 存储复杂对象
private entityToIndex = new Map<number, number>(); private entityToIndex = new Map<number, number>();
private indexToEntity: number[] = []; private indexToEntity: number[] = [];
private freeIndices: number[] = []; private freeIndices: number[] = [];
@@ -353,24 +384,24 @@ export class SoAStorage<T extends Component> {
private initializeFields(componentType: ComponentType<T>): void { private initializeFields(componentType: ComponentType<T>): void {
const instance = new componentType(); const instance = new componentType();
const highPrecisionFields = (componentType as any).__highPrecisionFields || new Set(); const highPrecisionFields = (componentType as unknown as ComponentTypeWithMetadata).__highPrecisionFields || new Set();
const float64Fields = (componentType as any).__float64Fields || new Set(); const float64Fields = (componentType as unknown as ComponentTypeWithMetadata).__float64Fields || new Set();
const float32Fields = (componentType as any).__float32Fields || new Set(); const float32Fields = (componentType as unknown as ComponentTypeWithMetadata).__float32Fields || new Set();
const int32Fields = (componentType as any).__int32Fields || new Set(); const int32Fields = (componentType as unknown as ComponentTypeWithMetadata).__int32Fields || new Set();
const uint32Fields = (componentType as any).__uint32Fields || new Set(); const uint32Fields = (componentType as unknown as ComponentTypeWithMetadata).__uint32Fields || new Set();
const int16Fields = (componentType as any).__int16Fields || new Set(); const int16Fields = (componentType as unknown as ComponentTypeWithMetadata).__int16Fields || new Set();
const uint16Fields = (componentType as any).__uint16Fields || new Set(); const uint16Fields = (componentType as unknown as ComponentTypeWithMetadata).__uint16Fields || new Set();
const int8Fields = (componentType as any).__int8Fields || new Set(); const int8Fields = (componentType as unknown as ComponentTypeWithMetadata).__int8Fields || new Set();
const uint8Fields = (componentType as any).__uint8Fields || new Set(); const uint8Fields = (componentType as unknown as ComponentTypeWithMetadata).__uint8Fields || new Set();
const uint8ClampedFields = (componentType as any).__uint8ClampedFields || new Set(); const uint8ClampedFields = (componentType as unknown as ComponentTypeWithMetadata).__uint8ClampedFields || new Set();
const autoTypedFields = (componentType as any).__autoTypedFields || new Map(); const autoTypedFields = (componentType as unknown as ComponentTypeWithMetadata).__autoTypedFields || new Map();
const serializeMapFields = (componentType as any).__serializeMapFields || new Set(); const serializeMapFields = (componentType as unknown as ComponentTypeWithMetadata).__serializeMapFields || new Set();
const serializeSetFields = (componentType as any).__serializeSetFields || new Set(); const serializeSetFields = (componentType as unknown as ComponentTypeWithMetadata).__serializeSetFields || new Set();
const serializeArrayFields = (componentType as any).__serializeArrayFields || new Set(); const serializeArrayFields = (componentType as unknown as ComponentTypeWithMetadata).__serializeArrayFields || new Set();
// const deepCopyFields = (componentType as any).__deepCopyFields || new Set(); // 未使用但保留供future使用 // const deepCopyFields = (componentType as unknown as ComponentTypeWithMetadata).__deepCopyFields || new Set(); // 未使用但保留供future使用
for (const key in instance) { for (const key in instance) {
if (instance.hasOwnProperty(key) && key !== 'id') { if (Object.prototype.hasOwnProperty.call(instance, key) && key !== 'id') {
const value = (instance as any)[key]; const value = (instance as any)[key];
const type = typeof value; const type = typeof value;
@@ -473,7 +504,7 @@ export class SoAStorage<T extends Component> {
// 处理所有字段 // 处理所有字段
for (const key in component) { for (const key in component) {
if (component.hasOwnProperty(key) && key !== 'id') { if (Object.prototype.hasOwnProperty.call(component, key) && key !== 'id') {
const value = (component as any)[key]; const value = (component as any)[key];
const type = typeof value; const type = typeof value;
@@ -578,7 +609,7 @@ export class SoAStorage<T extends Component> {
} }
if (obj instanceof Array) { if (obj instanceof Array) {
return obj.map(item => this.deepClone(item)); return obj.map((item) => this.deepClone(item));
} }
if (obj instanceof Map) { if (obj instanceof Map) {
@@ -600,7 +631,7 @@ export class SoAStorage<T extends Component> {
// 普通对象 // 普通对象
const cloned: any = {}; const cloned: any = {};
for (const key in obj) { for (const key in obj) {
if (obj.hasOwnProperty(key)) { if (Object.prototype.hasOwnProperty.call(obj, key)) {
cloned[key] = this.deepClone(obj[key]); cloned[key] = this.deepClone(obj[key]);
} }
} }

View File

@@ -1,6 +1,6 @@
import type {Component} from '../Component'; import type { Component } from '../Component';
import type {EntitySystem} from '../Systems'; import type { EntitySystem } from '../Systems';
import {ComponentType} from "../../Types"; import { ComponentType } from '../../Types';
/** /**
* 存储组件类型名称的Symbol键 * 存储组件类型名称的Symbol键

View File

@@ -28,7 +28,6 @@ export class EntityComparer {
} }
/** /**
* 游戏实体类 * 游戏实体类
* *
@@ -103,7 +102,16 @@ export class Entity {
/** /**
* 销毁状态标志 * 销毁状态标志
*/ */
public _isDestroyed: boolean = false; private _destroyed: boolean = false;
/**
* 设置销毁状态(仅供框架内部使用)
*
* @internal 此方法仅用于批量销毁优化,不应在外部调用
*/
public setDestroyed(value: boolean): void {
this._destroyed = value;
}
/** /**
* 父实体引用 * 父实体引用
@@ -161,7 +169,7 @@ export class Entity {
* @returns 如果实体已被销毁则返回true * @returns 如果实体已被销毁则返回true
*/ */
public get isDestroyed(): boolean { public get isDestroyed(): boolean {
return this._isDestroyed; return this._destroyed;
} }
/** /**
@@ -394,11 +402,11 @@ export class Entity {
const componentType = component.constructor as ComponentType<T>; const componentType = component.constructor as ComponentType<T>;
if (!this.scene) { if (!this.scene) {
throw new Error(`Entity must be added to Scene before adding components. Use scene.createEntity() instead of new Entity()`); throw new Error('Entity must be added to Scene before adding components. Use scene.createEntity() instead of new Entity()');
} }
if (!this.scene.componentStorageManager) { if (!this.scene.componentStorageManager) {
throw new Error(`Scene does not have componentStorageManager`); throw new Error('Scene does not have componentStorageManager');
} }
if (this.hasComponent(componentType)) { if (this.hasComponent(componentType)) {
@@ -465,8 +473,6 @@ export class Entity {
} }
/** /**
* 检查实体是否拥有指定类型的组件 * 检查实体是否拥有指定类型的组件
* *
@@ -646,7 +652,6 @@ export class Entity {
} }
/** /**
* 获取所有指定类型的组件 * 获取所有指定类型的组件
* *
@@ -700,7 +705,7 @@ export class Entity {
*/ */
public addChild(child: Entity): Entity { public addChild(child: Entity): Entity {
if (child === this) { if (child === this) {
throw new Error("Entity cannot be its own child"); throw new Error('Entity cannot be its own child');
} }
if (child._parent === this) { if (child._parent === this) {
@@ -898,11 +903,11 @@ export class Entity {
* 移除所有组件、子实体并标记为已销毁 * 移除所有组件、子实体并标记为已销毁
*/ */
public destroy(): void { public destroy(): void {
if (this._isDestroyed) { if (this._destroyed) {
return; return;
} }
this._isDestroyed = true; this._destroyed = true;
if (this.scene && this.scene.referenceTracker) { if (this.scene && this.scene.referenceTracker) {
this.scene.referenceTracker.clearReferencesTo(this.id); this.scene.referenceTracker.clearReferencesTo(this.id);
@@ -949,7 +954,7 @@ export class Entity {
collectChildren(this); collectChildren(this);
for (const entity of toDestroy) { for (const entity of toDestroy) {
entity._isDestroyed = true; entity.setDestroyed(true);
} }
for (const entity of toDestroy) { for (const entity of toDestroy) {
@@ -1007,20 +1012,20 @@ export class Entity {
childIds: number[]; childIds: number[];
depth: number; depth: number;
cacheBuilt: boolean; cacheBuilt: boolean;
} { } {
return { return {
name: this.name, name: this.name,
id: this.id, id: this.id,
enabled: this._enabled, enabled: this._enabled,
active: this._active, active: this._active,
activeInHierarchy: this.activeInHierarchy, activeInHierarchy: this.activeInHierarchy,
destroyed: this._isDestroyed, destroyed: this._destroyed,
componentCount: this.components.length, componentCount: this.components.length,
componentTypes: this.components.map(c => getComponentInstanceTypeName(c)), componentTypes: this.components.map((c) => getComponentInstanceTypeName(c)),
componentMask: BitMask64Utils.toString(this._componentMask, 2), // 二进制表示 componentMask: BitMask64Utils.toString(this._componentMask, 2), // 二进制表示
parentId: this._parent?.id || null, parentId: this._parent?.id || null,
childCount: this._children.length, childCount: this._children.length,
childIds: this._children.map(c => c.id), childIds: this._children.map((c) => c.id),
depth: this.getDepth(), depth: this.getDepth(),
cacheBuilt: this._componentCache !== null cacheBuilt: this._componentCache !== null
}; };

View File

@@ -8,7 +8,7 @@ import { TypeSafeEventSystem } from './Core/EventSystem';
import { EventBus } from './Core/EventBus'; import { EventBus } from './Core/EventBus';
import { ReferenceTracker } from './Core/ReferenceTracker'; import { ReferenceTracker } from './Core/ReferenceTracker';
import { IScene, ISceneConfig } from './IScene'; import { IScene, ISceneConfig } from './IScene';
import { getComponentInstanceTypeName, getSystemInstanceTypeName, getSystemMetadata } from "./Decorators"; import { getComponentInstanceTypeName, getSystemInstanceTypeName, getSystemMetadata } from './Decorators';
import { TypedQueryBuilder } from './Core/Query/TypedQuery'; import { TypedQueryBuilder } from './Core/Query/TypedQuery';
import { SceneSerializer, SceneSerializationOptions, SceneDeserializationOptions } from './Serialization/SceneSerializer'; import { SceneSerializer, SceneSerializationOptions, SceneDeserializationOptions } from './Serialization/SceneSerializer';
import { IncrementalSerializer, IncrementalSnapshot, IncrementalSerializationOptions } from './Serialization/IncrementalSerializer'; import { IncrementalSerializer, IncrementalSnapshot, IncrementalSerializationOptions } from './Serialization/IncrementalSerializer';
@@ -30,7 +30,7 @@ export class Scene implements IScene {
* *
* 用于标识和调试的友好名称。 * 用于标识和调试的友好名称。
*/ */
public name: string = ""; public name: string = '';
/** /**
* 场景自定义数据 * 场景自定义数据
@@ -338,7 +338,7 @@ export class Scene implements IScene {
* @param name 实体名称 * @param name 实体名称
*/ */
public createEntity(name: string) { public createEntity(name: string) {
let entity = new Entity(name, this.identifierPool.checkOut()); const entity = new Entity(name, this.identifierPool.checkOut());
this.eventSystem.emitSync('entity:created', { entityName: name, entity, scene: this }); this.eventSystem.emitSync('entity:created', { entityName: name, entity, scene: this });
@@ -384,7 +384,7 @@ export class Scene implements IScene {
* @param namePrefix 实体名称前缀 * @param namePrefix 实体名称前缀
* @returns 创建的实体列表 * @returns 创建的实体列表
*/ */
public createEntities(count: number, namePrefix: string = "Entity"): Entity[] { public createEntities(count: number, namePrefix: string = 'Entity'): Entity[] {
const entities: Entity[] = []; const entities: Entity[] = [];
// 批量创建实体对象,不立即添加到系统 // 批量创建实体对象,不立即添加到系统
@@ -416,7 +416,7 @@ export class Scene implements IScene {
if (entities.length === 0) return; if (entities.length === 0) return;
for (const entity of entities) { for (const entity of entities) {
entity._isDestroyed = true; entity.setDestroyed(true);
} }
for (const entity of entities) { for (const entity of entities) {
@@ -609,7 +609,7 @@ export class Scene implements IScene {
} else { } else {
this.logger.warn( this.logger.warn(
`Attempting to register a different instance of ${constructor.name}, ` + `Attempting to register a different instance of ${constructor.name}, ` +
`but type is already registered. Returning existing instance.` 'but type is already registered. Returning existing instance.'
); );
return existingSystem as T; return existingSystem as T;
} }
@@ -750,7 +750,7 @@ export class Scene implements IScene {
entityCount: number; entityCount: number;
processorCount: number; processorCount: number;
componentStorageStats: Map<string, any>; componentStorageStats: Map<string, any>;
} { } {
return { return {
entityCount: this.entities.count, entityCount: this.entities.count,
processorCount: this.systems.length, processorCount: this.systems.length,
@@ -779,20 +779,20 @@ export class Scene implements IScene {
entityCount: number; entityCount: number;
}>; }>;
componentStats: Map<string, any>; componentStats: Map<string, any>;
} { } {
const systems = this.systems; const systems = this.systems;
return { return {
name: this.name || this.constructor.name, name: this.name || this.constructor.name,
entityCount: this.entities.count, entityCount: this.entities.count,
processorCount: systems.length, processorCount: systems.length,
isRunning: this._didSceneBegin, isRunning: this._didSceneBegin,
entities: this.entities.buffer.map(entity => ({ entities: this.entities.buffer.map((entity) => ({
name: entity.name, name: entity.name,
id: entity.id, id: entity.id,
componentCount: entity.components.length, componentCount: entity.components.length,
componentTypes: entity.components.map(c => getComponentInstanceTypeName(c)) componentTypes: entity.components.map((c) => getComponentInstanceTypeName(c))
})), })),
processors: systems.map(processor => ({ processors: systems.map((processor) => ({
name: getSystemInstanceTypeName(processor), name: getSystemInstanceTypeName(processor),
updateOrder: processor.updateOrder, updateOrder: processor.updateOrder,
entityCount: (processor as any)._entities?.length || 0 entityCount: (processor as any)._entities?.length || 0

View File

@@ -212,7 +212,7 @@ export class ComponentSerializer {
// 数组 // 数组
if (Array.isArray(value)) { if (Array.isArray(value)) {
return value.map(item => this.serializeValue(item)); return value.map((item) => this.serializeValue(item));
} }
// Map (如果没有使用@SerializeMap装饰器) // Map (如果没有使用@SerializeMap装饰器)
@@ -276,7 +276,7 @@ export class ComponentSerializer {
// 数组 // 数组
if (Array.isArray(value)) { if (Array.isArray(value)) {
return value.map(item => this.deserializeValue(item)); return value.map((item) => this.deserializeValue(item));
} }
// 普通对象 // 普通对象
@@ -340,10 +340,10 @@ export class ComponentSerializer {
return { return {
type: metadata.options.typeId || getComponentTypeName(componentType), type: metadata.options.typeId || getComponentTypeName(componentType),
version: metadata.options.version, version: metadata.options.version,
fields: Array.from(metadata.fields.keys()).map(k => fields: Array.from(metadata.fields.keys()).map((k) =>
typeof k === 'symbol' ? k.toString() : k typeof k === 'symbol' ? k.toString() : k
), ),
ignoredFields: Array.from(metadata.ignoredFields).map(k => ignoredFields: Array.from(metadata.ignoredFields).map((k) =>
typeof k === 'symbol' ? k.toString() : k typeof k === 'symbol' ? k.toString() : k
), ),
isSerializable: true isSerializable: true

View File

@@ -696,22 +696,22 @@ export class IncrementalSerializer {
componentChanges: incremental.componentChanges.length, componentChanges: incremental.componentChanges.length,
sceneDataChanges: incremental.sceneDataChanges.length, sceneDataChanges: incremental.sceneDataChanges.length,
addedEntities: incremental.entityChanges.filter( addedEntities: incremental.entityChanges.filter(
c => c.operation === ChangeOperation.EntityAdded (c) => c.operation === ChangeOperation.EntityAdded
).length, ).length,
removedEntities: incremental.entityChanges.filter( removedEntities: incremental.entityChanges.filter(
c => c.operation === ChangeOperation.EntityRemoved (c) => c.operation === ChangeOperation.EntityRemoved
).length, ).length,
updatedEntities: incremental.entityChanges.filter( updatedEntities: incremental.entityChanges.filter(
c => c.operation === ChangeOperation.EntityUpdated (c) => c.operation === ChangeOperation.EntityUpdated
).length, ).length,
addedComponents: incremental.componentChanges.filter( addedComponents: incremental.componentChanges.filter(
c => c.operation === ChangeOperation.ComponentAdded (c) => c.operation === ChangeOperation.ComponentAdded
).length, ).length,
removedComponents: incremental.componentChanges.filter( removedComponents: incremental.componentChanges.filter(
c => c.operation === ChangeOperation.ComponentRemoved (c) => c.operation === ChangeOperation.ComponentRemoved
).length, ).length,
updatedComponents: incremental.componentChanges.filter( updatedComponents: incremental.componentChanges.filter(
c => c.operation === ChangeOperation.ComponentUpdated (c) => c.operation === ChangeOperation.ComponentUpdated
).length ).length
}; };
} }

View File

@@ -363,14 +363,14 @@ export class SceneSerializer {
// 数组 // 数组
if (Array.isArray(value)) { if (Array.isArray(value)) {
return value.map(item => this.serializeValue(item)); return value.map((item) => this.serializeValue(item));
} }
// 普通对象 // 普通对象
if (type === 'object') { if (type === 'object') {
const result: Record<string, any> = {}; const result: Record<string, any> = {};
for (const key in value) { for (const key in value) {
if (value.hasOwnProperty(key)) { if (Object.prototype.hasOwnProperty.call(value, key)) {
result[key] = this.serializeValue(value[key]); result[key] = this.serializeValue(value[key]);
} }
} }
@@ -409,14 +409,14 @@ export class SceneSerializer {
// 数组 // 数组
if (Array.isArray(value)) { if (Array.isArray(value)) {
return value.map(item => this.deserializeValue(item)); return value.map((item) => this.deserializeValue(item));
} }
// 普通对象 // 普通对象
if (type === 'object') { if (type === 'object') {
const result: Record<string, any> = {}; const result: Record<string, any> = {};
for (const key in value) { for (const key in value) {
if (value.hasOwnProperty(key)) { if (Object.prototype.hasOwnProperty.call(value, key)) {
result[key] = this.deserializeValue(value[key]); result[key] = this.deserializeValue(value[key]);
} }
} }
@@ -437,8 +437,8 @@ export class SceneSerializer {
const componentTypeSet = new Set(options.components); const componentTypeSet = new Set(options.components);
// 只返回拥有指定组件的实体 // 只返回拥有指定组件的实体
return entities.filter(entity => { return entities.filter((entity) => {
return Array.from(entity.components).some(component => return Array.from(entity.components).some((component) =>
componentTypeSet.has(component.constructor as ComponentType) componentTypeSet.has(component.constructor as ComponentType)
); );
}); });

View File

@@ -127,7 +127,7 @@ export class VersionMigrationManager {
return component; return component;
} }
let migratedData = { ...component }; const migratedData = { ...component };
let version = currentVersion; let version = currentVersion;
// 执行迁移链 // 执行迁移链
@@ -193,12 +193,12 @@ export class VersionMigrationManager {
private static migrateSceneComponents(scene: SerializedScene): SerializedScene { private static migrateSceneComponents(scene: SerializedScene): SerializedScene {
const migratedScene = { ...scene }; const migratedScene = { ...scene };
migratedScene.entities = scene.entities.map(entity => ({ migratedScene.entities = scene.entities.map((entity) => ({
...entity, ...entity,
components: entity.components.map(component => { components: entity.components.map((component) => {
// 查找组件的目标版本 // 查找组件的目标版本
const typeInfo = scene.componentTypeRegistry.find( const typeInfo = scene.componentTypeRegistry.find(
t => t.typeName === component.type (t) => t.typeName === component.type
); );
if (typeInfo && typeInfo.version !== component.version) { if (typeInfo && typeInfo.version !== component.version) {
@@ -220,10 +220,10 @@ export class VersionMigrationManager {
entities: any[], entities: any[],
typeRegistry: Array<{ typeName: string; version: number }> typeRegistry: Array<{ typeName: string; version: number }>
): any[] { ): any[] {
return entities.map(entity => ({ return entities.map((entity) => ({
...entity, ...entity,
components: entity.components.map((component: SerializedComponent) => { components: entity.components.map((component: SerializedComponent) => {
const typeInfo = typeRegistry.find(t => t.typeName === component.type); const typeInfo = typeRegistry.find((t) => t.typeName === component.type);
if (typeInfo && typeInfo.version !== component.version) { if (typeInfo && typeInfo.version !== component.version) {
return this.migrateComponent(component, typeInfo.version); return this.migrateComponent(component, typeInfo.version);

View File

@@ -9,6 +9,7 @@ import { createLogger } from '../../Utils/Logger';
import type { EventListenerConfig, TypeSafeEventSystem, EventHandler } from '../Core/EventSystem'; import type { EventListenerConfig, TypeSafeEventSystem, EventHandler } from '../Core/EventSystem';
import type { ComponentConstructor, ComponentInstance } from '../../Types/TypeHelpers'; import type { ComponentConstructor, ComponentInstance } from '../../Types/TypeHelpers';
import type { IService } from '../../Core/ServiceContainer'; import type { IService } from '../../Core/ServiceContainer';
import type { ComponentType } from '../Core/ComponentStorage';
/** /**
* 事件监听器记录 * 事件监听器记录
@@ -259,8 +260,11 @@ export abstract class EntitySystem<
} }
/** /**
* 清除实体缓存(内部使用) * 清除实体缓存
* 当Scene中的实体发生变化时调用 *
* 当 Scene 中的实体发生变化时调用,使系统的实体缓存失效。
*
* @internal 框架内部使用,不应在外部代码中直接调用
*/ */
public clearEntityCache(): void { public clearEntityCache(): void {
this._entityCache.invalidate(); this._entityCache.invalidate();
@@ -299,7 +303,7 @@ export abstract class EntitySystem<
// 空条件返回所有实体 // 空条件返回所有实体
if (this._matcher.isEmpty()) { if (this._matcher.isEmpty()) {
currentEntities = querySystem.getAllEntities(); currentEntities = querySystem.queryAllEntities();
} else if (this.isSingleCondition(condition)) { } else if (this.isSingleCondition(condition)) {
// 单一条件优化查询 // 单一条件优化查询
currentEntities = this.executeSingleConditionQuery(condition, querySystem); currentEntities = this.executeSingleConditionQuery(condition, querySystem);
@@ -403,7 +407,7 @@ export abstract class EntitySystem<
// 6. 应用none条件 (差集) // 6. 应用none条件 (差集)
if (condition.none.length > 0) { if (condition.none.length > 0) {
if (!resultIds) { if (!resultIds) {
resultIds = this.extractEntityIds(querySystem.getAllEntities()); resultIds = this.extractEntityIds(querySystem.queryAllEntities());
} }
const noneResult = querySystem.queryAny(...condition.none); const noneResult = querySystem.queryAny(...condition.none);
@@ -411,16 +415,23 @@ export abstract class EntitySystem<
resultIds = this.differenceIdSets(resultIds, noneIds); resultIds = this.differenceIdSets(resultIds, noneIds);
} }
return resultIds ? this.idSetToEntityArray(resultIds, querySystem.getAllEntities()) : []; return resultIds ? this.idSetToEntityArray(resultIds, querySystem.queryAllEntities()) : [];
} }
/** /**
* 提取实体ID集合 * 提取实体ID集合
*
* 使用位运算 | 0 强制转换为 32 位整数,帮助 JavaScript 引擎的 JIT 编译器
* 进行整数优化,在大规模实体集合操作时可以提供微小的性能提升。
*
* @param entities 实体数组
* @returns 包含所有实体ID的集合
*/ */
private extractEntityIds(entities: readonly Entity[]): Set<number> { private extractEntityIds(entities: readonly Entity[]): Set<number> {
const len = entities.length; const len = entities.length;
const idSet = new Set<number>(); const idSet = new Set<number>();
// 使用位运算 | 0 进行整数优化JIT 友好)
for (let i = 0; i < len; i = (i + 1) | 0) { for (let i = 0; i < len; i = (i + 1) | 0) {
idSet.add(entities[i]!.id | 0); idSet.add(entities[i]!.id | 0);
} }
@@ -482,6 +493,12 @@ export abstract class EntitySystem<
/** /**
* 重建实体ID映射 * 重建实体ID映射
*
* 重新构建从实体ID到实体引用的映射表。使用位运算优化性能。
*
* @param allEntities 所有实体的数组
* @param version QuerySystem 的版本号,用于缓存失效判断
* @returns 重建后的实体ID映射表
*/ */
private rebuildEntityIdMap(allEntities: readonly Entity[], version: number): Map<number, Entity> { private rebuildEntityIdMap(allEntities: readonly Entity[], version: number): Map<number, Entity> {
let entityMap = this._entityIdMap; let entityMap = this._entityIdMap;
@@ -493,6 +510,7 @@ export abstract class EntitySystem<
} }
const len = allEntities.length; const len = allEntities.length;
// 使用位运算 | 0 进行整数优化JIT 友好)
for (let i = 0; i < len; i = (i + 1) | 0) { for (let i = 0; i < len; i = (i + 1) | 0) {
const entity = allEntities[i]!; const entity = allEntities[i]!;
entityMap.set(entity.id | 0, entity); entityMap.set(entity.id | 0, entity);
@@ -506,6 +524,12 @@ export abstract class EntitySystem<
/** /**
* 从ID集合构建Entity数组 * 从ID集合构建Entity数组
*
* 将实体ID集合转换为实体引用数组。跳过无效的实体ID已被删除的实体
*
* @param idSet 实体ID集合
* @param allEntities 所有实体的数组(用于构建映射表)
* @returns 实体引用数组
*/ */
private idSetToEntityArray(idSet: Set<number>, allEntities: readonly Entity[]): readonly Entity[] { private idSetToEntityArray(idSet: Set<number>, allEntities: readonly Entity[]): readonly Entity[] {
const entityMap = this.getEntityIdMap(allEntities); const entityMap = this.getEntityIdMap(allEntities);
@@ -518,10 +542,12 @@ export abstract class EntitySystem<
const entity = entityMap.get(id); const entity = entityMap.get(id);
if (entity !== undefined) { if (entity !== undefined) {
result[index] = entity; result[index] = entity;
// 使用位运算 | 0 进行整数优化JIT 友好)
index = (index + 1) | 0; index = (index + 1) | 0;
} }
} }
// 如果有无效ID调整数组长度
if (index < size) { if (index < size) {
result.length = index; result.length = index;
} }
@@ -786,7 +812,7 @@ export abstract class EntitySystem<
this._eventListeners.push({ this._eventListeners.push({
eventSystem: this.scene.eventSystem, eventSystem: this.scene.eventSystem,
eventType, eventType,
handler, handler: handler as EventHandler,
listenerRef listenerRef
}); });
} }
@@ -803,7 +829,7 @@ export abstract class EntitySystem<
handler: EventHandler<T> handler: EventHandler<T>
): void { ): void {
const listenerIndex = this._eventListeners.findIndex( const listenerIndex = this._eventListeners.findIndex(
listener => listener.eventType === eventType && listener.handler === handler (listener) => listener.eventType === eventType && listener.handler === handler
); );
if (listenerIndex >= 0) { if (listenerIndex >= 0) {
@@ -891,7 +917,7 @@ export abstract class EntitySystem<
entity: Entity, entity: Entity,
componentType: T componentType: T
): ComponentInstance<T> { ): ComponentInstance<T> {
const component = entity.getComponent(componentType as any); const component = entity.getComponent(componentType as ComponentType);
if (!component) { if (!component) {
throw new Error( throw new Error(
`Component ${componentType.name} not found on entity ${entity.name} in ${this.systemName}` `Component ${componentType.name} not found on entity ${entity.name} in ${this.systemName}`
@@ -929,7 +955,7 @@ export abstract class EntitySystem<
): { [K in keyof T]: ComponentInstance<T[K]> } { ): { [K in keyof T]: ComponentInstance<T[K]> } {
return components.map((type) => return components.map((type) =>
this.requireComponent(entity, type) this.requireComponent(entity, type)
) as any; ) as { [K in keyof T]: ComponentInstance<T[K]> };
} }
/** /**

View File

@@ -414,7 +414,7 @@ export abstract class WorkerEntitySystem<TEntityData = any> extends EntitySystem
${sharedProcessFunctionBody} ${sharedProcessFunctionBody}
}; };
userProcessFunction(sharedFloatArray, startIndex, endIndex, deltaTime, systemConfig); userProcessFunction(sharedFloatArray, startIndex, endIndex, deltaTime, systemConfig);
` : ``} ` : ''}
} }
`; `;
} }
@@ -494,7 +494,7 @@ export abstract class WorkerEntitySystem<TEntityData = any> extends EntitySystem
const deltaTime = Time.deltaTime; const deltaTime = Time.deltaTime;
// 3. Worker执行阶段 // 3. Worker执行阶段
const promises = batches.map(batch => const promises = batches.map((batch) =>
this.workerPool!.execute({ this.workerPool!.execute({
entities: batch, entities: batch,
deltaTime, deltaTime,
@@ -525,7 +525,7 @@ export abstract class WorkerEntitySystem<TEntityData = any> extends EntitySystem
*/ */
private processSynchronously(entities: readonly Entity[]): void { private processSynchronously(entities: readonly Entity[]): void {
// 1. 数据提取阶段 // 1. 数据提取阶段
const entityData = entities.map(entity => this.extractEntityData(entity)); const entityData = entities.map((entity) => this.extractEntityData(entity));
// 2. 主线程处理阶段 // 2. 主线程处理阶段
const deltaTime = Time.deltaTime; const deltaTime = Time.deltaTime;
@@ -534,7 +534,7 @@ export abstract class WorkerEntitySystem<TEntityData = any> extends EntitySystem
// 3. 结果应用阶段 // 3. 结果应用阶段
// 处理Promise返回值 // 处理Promise返回值
if (results && typeof (results as any).then === 'function') { if (results && typeof (results as any).then === 'function') {
(results as Promise<TEntityData[]>).then(finalResults => { (results as Promise<TEntityData[]>).then((finalResults) => {
entities.forEach((entity, index) => { entities.forEach((entity, index) => {
this.applyResult(entity, finalResults[index]!); this.applyResult(entity, finalResults[index]!);
}); });
@@ -813,7 +813,7 @@ export abstract class WorkerEntitySystem<TEntityData = any> extends EntitySystem
sharedArrayBufferSupported: boolean; sharedArrayBufferSupported: boolean;
sharedArrayBufferEnabled: boolean; sharedArrayBufferEnabled: boolean;
currentMode: 'shared-buffer' | 'worker' | 'sync'; currentMode: 'shared-buffer' | 'worker' | 'sync';
} { } {
let currentMode: 'shared-buffer' | 'worker' | 'sync' = 'sync'; let currentMode: 'shared-buffer' | 'worker' | 'sync' = 'sync';
if (this.config.enableWorker && this.workerPool) { if (this.config.enableWorker && this.workerPool) {

View File

@@ -69,7 +69,7 @@ export class BitMask64Utils {
return maskSegments.some((seg, index) => { return maskSegments.some((seg, index) => {
const bitsSeg = bitsSegments[index]; const bitsSeg = bitsSegments[index];
return bitsSeg && ((seg[SegmentPart.LOW] & bitsSeg[SegmentPart.LOW]) !== 0 || (seg[SegmentPart.HIGH] & bitsSeg[SegmentPart.HIGH]) !== 0); return bitsSeg && ((seg[SegmentPart.LOW] & bitsSeg[SegmentPart.LOW]) !== 0 || (seg[SegmentPart.HIGH] & bitsSeg[SegmentPart.HIGH]) !== 0);
}) });
} }
/** /**
@@ -145,7 +145,7 @@ export class BitMask64Utils {
return baseIsZero; return baseIsZero;
} }
// 额外检查扩展区域是否都为0 // 额外检查扩展区域是否都为0
return mask.segments.every(seg => seg[SegmentPart.LOW] === 0 && seg[SegmentPart.HIGH] === 0); return mask.segments.every((seg) => seg[SegmentPart.LOW] === 0 && seg[SegmentPart.HIGH] === 0);
} }
/** /**
@@ -155,7 +155,7 @@ export class BitMask64Utils {
* @returns 如果两个掩码完全相等则返回true * @returns 如果两个掩码完全相等则返回true
*/ */
public static equals(a: BitMask64Data, b: BitMask64Data): boolean { public static equals(a: BitMask64Data, b: BitMask64Data): boolean {
let baseEquals = a.base[SegmentPart.LOW] === b.base[SegmentPart.LOW] && a.base[SegmentPart.HIGH] === b.base[SegmentPart.HIGH]; const baseEquals = a.base[SegmentPart.LOW] === b.base[SegmentPart.LOW] && a.base[SegmentPart.HIGH] === b.base[SegmentPart.HIGH];
// base不相等或ab都没有扩展区域位直接返回base比较结果 // base不相等或ab都没有扩展区域位直接返回base比较结果
if(!baseEquals || (!a.segments && !b.segments)) return baseEquals; if(!baseEquals || (!a.segments && !b.segments)) return baseEquals;
// 不能假设ab的segments都存在或长度相同. // 不能假设ab的segments都存在或长度相同.
@@ -355,7 +355,7 @@ export class BitMask64Utils {
if(!source.segments || source.segments.length == 0) return; if(!source.segments || source.segments.length == 0) return;
// 没有拓展段,则直接复制数组 // 没有拓展段,则直接复制数组
if(!target.segments){ if(!target.segments){
target.segments = source.segments.map(seg => [...seg]); target.segments = source.segments.map((seg) => [...seg]);
return; return;
} }
// source有扩展段target扩展段不足则补充长度 // source有扩展段target扩展段不足则补充长度
@@ -382,7 +382,7 @@ export class BitMask64Utils {
public static clone(mask: BitMask64Data): BitMask64Data { public static clone(mask: BitMask64Data): BitMask64Data {
return { return {
base: mask.base.slice() as BitMask64Segment, base: mask.base.slice() as BitMask64Segment,
...(mask.segments && { segments: mask.segments.map(seg => [...seg] as BitMask64Segment) }) ...(mask.segments && { segments: mask.segments.map((seg) => [...seg] as BitMask64Segment) })
}; };
} }
@@ -414,8 +414,8 @@ export class BitMask64Utils {
for (let i = -1; i < totalLength; i++) { for (let i = -1; i < totalLength; i++) {
let segResult = ''; let segResult = '';
const bitMaskData = i == -1 ? mask.base : mask.segments![i]!; const bitMaskData = i == -1 ? mask.base : mask.segments![i]!;
let hi = bitMaskData[SegmentPart.HIGH]; const hi = bitMaskData[SegmentPart.HIGH];
let lo = bitMaskData[SegmentPart.LOW]; const lo = bitMaskData[SegmentPart.LOW];
if(radix == 2){ if(radix == 2){
const hiBits = hi.toString(2).padStart(32, '0'); const hiBits = hi.toString(2).padStart(32, '0');
const loBits = lo.toString(2).padStart(32, '0'); const loBits = lo.toString(2).padStart(32, '0');

View File

@@ -1,4 +1,4 @@
import { BitMask64Data } from "./BigIntCompatibility"; import { BitMask64Data } from './BigIntCompatibility';
// FlatHashMapFast.ts // FlatHashMapFast.ts

View File

@@ -77,7 +77,7 @@ export class ComponentSparseSet {
this.removeEntity(entity); this.removeEntity(entity);
} }
let componentMask = BitMask64Utils.clone(BitMask64Utils.ZERO); const componentMask = BitMask64Utils.clone(BitMask64Utils.ZERO);
const entityComponents = new Set<ComponentType>(); const entityComponents = new Set<ComponentType>();
// 分析实体组件并构建位掩码 // 分析实体组件并构建位掩码
@@ -169,7 +169,7 @@ export class ComponentSparseSet {
} }
// 构建目标位掩码 // 构建目标位掩码
let targetMask = BitMask64Utils.clone(BitMask64Utils.ZERO); const targetMask = BitMask64Utils.clone(BitMask64Utils.ZERO);
for (const componentType of componentTypes) { for (const componentType of componentTypes) {
if (!ComponentRegistry.isRegistered(componentType)) { if (!ComponentRegistry.isRegistered(componentType)) {
return new Set<Entity>(); // 未注册的组件类型,结果为空 return new Set<Entity>(); // 未注册的组件类型,结果为空
@@ -209,7 +209,7 @@ export class ComponentSparseSet {
} }
// 构建目标位掩码 // 构建目标位掩码
let targetMask = BitMask64Utils.clone(BitMask64Utils.ZERO); const targetMask = BitMask64Utils.clone(BitMask64Utils.ZERO);
for (const componentType of componentTypes) { for (const componentType of componentTypes) {
if (ComponentRegistry.isRegistered(componentType)) { if (ComponentRegistry.isRegistered(componentType)) {
const bitMask = ComponentRegistry.getBitMask(componentType); const bitMask = ComponentRegistry.getBitMask(componentType);
@@ -272,14 +272,26 @@ export class ComponentSparseSet {
} }
/** /**
* 获取所有实体 * 查询所有实体
*
* 返回拥有此组件的所有实体。
* *
* @returns 所有实体的数组 * @returns 所有实体的数组
*/ */
public getAllEntities(): Entity[] { public queryAllEntities(): Entity[] {
return this._entities.toArray(); return this._entities.toArray();
} }
/**
* 获取所有实体
*
* @deprecated 使用 queryAllEntities() 代替,以保持命名一致性
* @see {@link queryAllEntities}
*/
public getAllEntities(): Entity[] {
return this.queryAllEntities();
}
/** /**
* 获取实体数量 * 获取实体数量
*/ */
@@ -327,7 +339,7 @@ export class ComponentSparseSet {
masksMemory: number; masksMemory: number;
mappingsMemory: number; mappingsMemory: number;
totalMemory: number; totalMemory: number;
} { } {
const entitiesStats = this._entities.getMemoryStats(); const entitiesStats = this._entities.getMemoryStats();
const masksMemory = this._componentMasks.length * 16; // 估计每个BigInt 16字节 const masksMemory = this._componentMasks.length * 16; // 估计每个BigInt 16字节

View File

@@ -263,7 +263,7 @@ export class EntityList {
pendingAdd: number; pendingAdd: number;
pendingRemove: number; pendingRemove: number;
nameIndexSize: number; nameIndexSize: number;
} { } {
let activeCount = 0; let activeCount = 0;
for (const entity of this.buffer) { for (const entity of this.buffer) {
if (entity.enabled && !entity.isDestroyed) { if (entity.enabled && !entity.isDestroyed) {

View File

@@ -117,8 +117,8 @@ export class IdentifierPool {
if (this._nextAvailableIndex > IdentifierPool.MAX_INDEX) { if (this._nextAvailableIndex > IdentifierPool.MAX_INDEX) {
throw new Error( throw new Error(
`实体索引已达到框架设计限制 (${IdentifierPool.MAX_INDEX})。` + `实体索引已达到框架设计限制 (${IdentifierPool.MAX_INDEX})。` +
`这意味着您已经分配了超过65535个不同的实体索引。` + '这意味着您已经分配了超过65535个不同的实体索引。' +
`这是16位索引设计的限制考虑优化实体回收策略或升级到64位ID设计。` '这是16位索引设计的限制考虑优化实体回收策略或升级到64位ID设计。'
); );
} }
@@ -155,7 +155,7 @@ export class IdentifierPool {
// 检查是否已经在待回收队列中 // 检查是否已经在待回收队列中
const alreadyPending = this._pendingRecycle.some( const alreadyPending = this._pendingRecycle.some(
item => item.index === index && item.generation === generation (item) => item.index === index && item.generation === generation
); );
if (alreadyPending) { if (alreadyPending) {
@@ -217,7 +217,7 @@ export class IdentifierPool {
averageGeneration: number; averageGeneration: number;
/** 世代存储大小 */ /** 世代存储大小 */
generationStorageSize: number; generationStorageSize: number;
} { } {
// 计算平均世代版本 // 计算平均世代版本
let totalGeneration = 0; let totalGeneration = 0;
let generationCount = 0; let generationCount = 0;

View File

@@ -267,15 +267,15 @@ export class Matcher {
const parts: string[] = []; const parts: string[] = [];
if (this.condition.all.length > 0) { if (this.condition.all.length > 0) {
parts.push(`all(${this.condition.all.map(t => getComponentTypeName(t)).join(', ')})`); parts.push(`all(${this.condition.all.map((t) => getComponentTypeName(t)).join(', ')})`);
} }
if (this.condition.any.length > 0) { if (this.condition.any.length > 0) {
parts.push(`any(${this.condition.any.map(t => getComponentTypeName(t)).join(', ')})`); parts.push(`any(${this.condition.any.map((t) => getComponentTypeName(t)).join(', ')})`);
} }
if (this.condition.none.length > 0) { if (this.condition.none.length > 0) {
parts.push(`none(${this.condition.none.map(t => getComponentTypeName(t)).join(', ')})`); parts.push(`none(${this.condition.none.map((t) => getComponentTypeName(t)).join(', ')})`);
} }
if (this.condition.tag !== undefined) { if (this.condition.tag !== undefined) {

View File

@@ -267,7 +267,7 @@ export class SparseSet<T> {
denseArraySize: number; denseArraySize: number;
sparseMapSize: number; sparseMapSize: number;
totalMemory: number; totalMemory: number;
} { } {
const denseArraySize = this._dense.length * 8; // 估计每个引用8字节 const denseArraySize = this._dense.length * 8; // 估计每个引用8字节
const sparseMapSize = this._sparse.size * 16; // 估计每个Map条目16字节 const sparseMapSize = this._sparse.size * 16; // 估计每个Map条目16字节

View File

@@ -408,7 +408,7 @@ export class World {
globalSystemCount: this._globalSystems.length, globalSystemCount: this._globalSystems.length,
createdAt: this._createdAt, createdAt: this._createdAt,
config: { ...this._config }, config: { ...this._config },
scenes: Array.from(this._scenes.keys()).map(sceneId => ({ scenes: Array.from(this._scenes.keys()).map((sceneId) => ({
id: sceneId, id: sceneId,
isActive: this._activeScenes.has(sceneId), isActive: this._activeScenes.has(sceneId),
name: this._scenes.get(sceneId)?.name || sceneId name: this._scenes.get(sceneId)?.name || sceneId

View File

@@ -444,7 +444,7 @@ export class WorldManager implements IService {
// 检查是否所有Scene都是空的 // 检查是否所有Scene都是空的
const allScenes = world.getAllScenes(); const allScenes = world.getAllScenes();
const hasEntities = allScenes.some(scene => const hasEntities = allScenes.some((scene) =>
scene.entities && scene.entities.count > 0 scene.entities && scene.entities.count > 0
); );

View File

@@ -98,7 +98,7 @@ export class PlatformManager {
platformSupportsSharedArrayBuffer: boolean; platformSupportsSharedArrayBuffer: boolean;
platformMaxWorkerCount: number; platformMaxWorkerCount: number;
platformLimitations: any; platformLimitations: any;
} { } {
if (!this.adapter) { if (!this.adapter) {
return { return {
platformSupportsWorker: false, platformSupportsWorker: false,

View File

@@ -208,8 +208,8 @@ export class DebugPlugin implements IPlugin, IService {
return { return {
name: scene.name, name: scene.name,
entityCount: entities.length, entityCount: entities.length,
systems: systems.map(sys => this.getSystemInfo(sys)), systems: systems.map((sys) => this.getSystemInfo(sys)),
entities: entities.map(entity => this.getEntityInfo(entity)) entities: entities.map((entity) => this.getEntityInfo(entity))
}; };
} }
@@ -246,7 +246,7 @@ export class DebugPlugin implements IPlugin, IService {
enabled: entity.enabled, enabled: entity.enabled,
tag: entity.tag, tag: entity.tag,
componentCount: components.length, componentCount: components.length,
components: components.map(comp => this.getComponentInfo(comp)) components: components.map((comp) => this.getComponentInfo(comp))
}; };
} }
@@ -304,7 +304,7 @@ export class DebugPlugin implements IPlugin, IService {
if (filter.hasComponent) { if (filter.hasComponent) {
const hasComp = entity.components.some( const hasComp = entity.components.some(
c => c.constructor.name === filter.hasComponent (c) => c.constructor.name === filter.hasComponent
); );
if (!hasComp) { if (!hasComp) {
continue; continue;

View File

@@ -47,8 +47,8 @@ export class ComponentDataCollector {
}); });
// 获取池利用率信息 // 获取池利用率信息
let poolUtilizations = new Map<string, number>(); const poolUtilizations = new Map<string, number>();
let poolSizes = new Map<string, number>(); const poolSizes = new Map<string, number>();
try { try {
const poolManager = ComponentPoolManager.getInstance(); const poolManager = ComponentPoolManager.getInstance();

View File

@@ -135,7 +135,7 @@ export class DebugManager implements IService, IUpdatable {
* 格式化日志消息 * 格式化日志消息
*/ */
private formatLogMessage(args: unknown[]): string { private formatLogMessage(args: unknown[]): string {
return args.map(arg => { return args.map((arg) => {
if (typeof arg === 'string') return arg; if (typeof arg === 'string') return arg;
if (arg instanceof Error) return `${arg.name}: ${arg.message}`; if (arg instanceof Error) return `${arg.name}: ${arg.message}`;
if (arg === null) return 'null'; if (arg === null) return 'null';
@@ -173,7 +173,7 @@ export class DebugManager implements IService, IUpdatable {
seen.add(value); seen.add(value);
if (Array.isArray(value)) { if (Array.isArray(value)) {
const result = value.map(item => stringify(item, depth + 1)); const result = value.map((item) => stringify(item, depth + 1));
seen.delete(value); seen.delete(value);
return result; return result;
} }
@@ -436,9 +436,6 @@ export class DebugManager implements IService, IUpdatable {
} }
/** /**
* 处理内存快照请求 * 处理内存快照请求
*/ */
@@ -519,7 +516,7 @@ export class DebugManager implements IService, IUpdatable {
jsHeapSizeLimit: number; jsHeapSizeLimit: number;
} | null; } | null;
detailedMemory?: unknown; detailedMemory?: unknown;
} { } {
const memoryInfo = { const memoryInfo = {
totalMemory: 0, totalMemory: 0,
usedMemory: 0, usedMemory: 0,
@@ -575,7 +572,6 @@ export class DebugManager implements IService, IUpdatable {
} }
/** /**
* 收集组件内存统计(仅用于内存快照) * 收集组件内存统计(仅用于内存快照)
*/ */
@@ -672,7 +668,7 @@ export class DebugManager implements IService, IUpdatable {
enabled: boolean; enabled: boolean;
updateOrder: number; updateOrder: number;
}>; }>;
} { } {
const scene = this.sceneManager.currentScene; const scene = this.sceneManager.currentScene;
let totalSystemMemory = 0; let totalSystemMemory = 0;
const systemBreakdown: Array<{ const systemBreakdown: Array<{
@@ -766,7 +762,7 @@ export class DebugManager implements IService, IUpdatable {
utilization: number; utilization: number;
hitRate?: number; hitRate?: number;
}>; }>;
} { } {
let totalPoolMemory = 0; let totalPoolMemory = 0;
const poolBreakdown: Array<{ const poolBreakdown: Array<{
typeName: string; typeName: string;
@@ -845,7 +841,7 @@ export class DebugManager implements IService, IUpdatable {
samples: number; samples: number;
}>; }>;
error?: string; error?: string;
} { } {
try { try {
if (!this.performanceMonitor) { if (!this.performanceMonitor) {
return { enabled: false }; return { enabled: false };

View File

@@ -182,17 +182,17 @@ export class EntityDataCollector {
try { try {
stats = entityList.getStats ? entityList.getStats() : this.calculateFallbackEntityStats(entityList); stats = entityList.getStats ? entityList.getStats() : this.calculateFallbackEntityStats(entityList);
} catch (error) { } catch (error) {
return { return {
totalEntities: 0, totalEntities: 0,
activeEntities: 0, activeEntities: 0,
pendingAdd: 0, pendingAdd: 0,
pendingRemove: 0, pendingRemove: 0,
entitiesPerArchetype: [], entitiesPerArchetype: [],
topEntitiesByComponents: [], topEntitiesByComponents: [],
entityHierarchy: [], entityHierarchy: [],
entityDetailsMap: {} entityDetailsMap: {}
}; };
} }
const archetypeData = this.collectArchetypeDataWithMemory(scene); const archetypeData = this.collectArchetypeDataWithMemory(scene);
@@ -369,7 +369,6 @@ export class EntityDataCollector {
} }
private getArchetypeDistributionWithMemory(entityContainer: any): Array<{ signature: string; count: number; memory: number }> { private getArchetypeDistributionWithMemory(entityContainer: any): Array<{ signature: string; count: number; memory: number }> {
const distribution = new Map<string, { count: number; memory: number; componentTypes: string[] }>(); const distribution = new Map<string, { count: number; memory: number; componentTypes: string[] }>();
@@ -437,7 +436,7 @@ export class EntityDataCollector {
private calculateFallbackEntityStats(entityList: any): any { private calculateFallbackEntityStats(entityList: any): any {
const allEntities = entityList.buffer || []; const allEntities = entityList.buffer || [];
const activeEntities = allEntities.filter((entity: any) => const activeEntities = allEntities.filter((entity: any) =>
entity.enabled && !entity._isDestroyed entity.enabled && !entity.isDestroyed
); );
return { return {
@@ -694,7 +693,7 @@ export class EntityDataCollector {
try { try {
const propertyKeys = Object.keys(component); const propertyKeys = Object.keys(component);
propertyKeys.forEach(propertyKey => { propertyKeys.forEach((propertyKey) => {
if (!propertyKey.startsWith('_') && propertyKey !== 'entity' && propertyKey !== 'constructor') { if (!propertyKey.startsWith('_') && propertyKey !== 'entity' && propertyKey !== 'constructor') {
const propertyValue = (component as any)[propertyKey]; const propertyValue = (component as any)[propertyKey];
if (propertyValue !== undefined && propertyValue !== null) { if (propertyValue !== undefined && propertyValue !== null) {
@@ -739,20 +738,20 @@ export class EntityDataCollector {
const component = entity.components[componentIndex]; const component = entity.components[componentIndex];
const properties: Record<string, any> = {}; const properties: Record<string, any> = {};
const propertyKeys = Object.keys(component); const propertyKeys = Object.keys(component);
propertyKeys.forEach(propertyKey => { propertyKeys.forEach((propertyKey) => {
if (!propertyKey.startsWith('_') && propertyKey !== 'entity') { if (!propertyKey.startsWith('_') && propertyKey !== 'entity') {
const propertyValue = (component as any)[propertyKey]; const propertyValue = (component as any)[propertyKey];
if (propertyValue !== undefined && propertyValue !== null) { if (propertyValue !== undefined && propertyValue !== null) {
properties[propertyKey] = this.formatPropertyValue(propertyValue); properties[propertyKey] = this.formatPropertyValue(propertyValue);
} }
} }
}); });
return properties; return properties;
} catch (error) { } catch (error) {
return { _error: '属性提取失败' }; return { _error: '属性提取失败' };
} }
} }
/** /**
@@ -786,7 +785,7 @@ export class EntityDataCollector {
if (obj.length === 0) return []; if (obj.length === 0) return [];
if (obj.length > 10) { if (obj.length > 10) {
const sample = obj.slice(0, 3).map(item => this.formatPropertyValue(item, 1)); const sample = obj.slice(0, 3).map((item) => this.formatPropertyValue(item, 1));
return { return {
_isLazyArray: true, _isLazyArray: true,
_arrayLength: obj.length, _arrayLength: obj.length,
@@ -795,7 +794,7 @@ export class EntityDataCollector {
}; };
} }
return obj.map(item => this.formatPropertyValue(item, 1)); return obj.map((item) => this.formatPropertyValue(item, 1));
} }
const keys = Object.keys(obj); const keys = Object.keys(obj);
@@ -843,7 +842,7 @@ export class EntityDataCollector {
const typeName = obj.constructor?.name || 'Object'; const typeName = obj.constructor?.name || 'Object';
const summary = this.getObjectSummary(obj, typeName); const summary = this.getObjectSummary(obj, typeName);
return { return {
_isLazyObject: true, _isLazyObject: true,
_typeName: typeName, _typeName: typeName,
_summary: summary, _summary: summary,

View File

@@ -34,7 +34,7 @@ export class PerformanceDataCollector {
} }
// 计算ECS执行时间统计 // 计算ECS执行时间统计
const history = this.frameTimeHistory.filter(t => t >= 0); const history = this.frameTimeHistory.filter((t) => t >= 0);
const averageECSTime = history.length > 0 ? history.reduce((a, b) => a + b, 0) / history.length : ecsExecutionTimeMs; const averageECSTime = history.length > 0 ? history.reduce((a, b) => a + b, 0) / history.length : ecsExecutionTimeMs;
const minECSTime = history.length > 0 ? Math.min(...history) : ecsExecutionTimeMs; const minECSTime = history.length > 0 ? Math.min(...history) : ecsExecutionTimeMs;
const maxECSTime = history.length > 0 ? Math.max(...history) : ecsExecutionTimeMs; const maxECSTime = history.length > 0 ? Math.max(...history) : ecsExecutionTimeMs;
@@ -100,7 +100,7 @@ export class PerformanceDataCollector {
} }
// 计算各系统占ECS总时间的百分比 // 计算各系统占ECS总时间的百分比
systemBreakdown.forEach(system => { systemBreakdown.forEach((system) => {
system.percentage = totalTime > 0 ? (system.executionTime / totalTime * 100) : 0; system.percentage = totalTime > 0 ? (system.executionTime / totalTime * 100) : 0;
}); });

View File

@@ -82,7 +82,8 @@ export class WebSocketManager {
try { try {
const message = typeof data === 'string' ? data : JSON.stringify(data); const message = typeof data === 'string' ? data : JSON.stringify(data);
this.ws.send(message); this.ws.send(message);
} catch (error) { } catch (_error) {
// 发送失败时静默忽略WebSocket 断开会触发 error 事件
} }
} }
@@ -112,7 +113,7 @@ export class WebSocketManager {
this.reconnectAttempts++; this.reconnectAttempts++;
this.reconnectTimer = setTimeout(() => { this.reconnectTimer = setTimeout(() => {
this.connect().catch(_error => { this.connect().catch((_error) => {
if (this.reconnectAttempts < this.maxReconnectAttempts) { if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.scheduleReconnect(); this.scheduleReconnect();
} }
@@ -130,7 +131,8 @@ export class WebSocketManager {
if (this.messageHandler) { if (this.messageHandler) {
this.messageHandler(message); this.messageHandler(message);
} }
} catch (error) { } catch (_error) {
// 解析失败时静默忽略,避免非 JSON 消息导致错误
} }
} }

View File

@@ -1,13 +1,15 @@
type EventHandler = (...args: unknown[]) => void;
/** /**
* 用于包装事件的一个小类 * 用于包装事件的一个小类
*/ */
export class FuncPack<TContext = unknown> { export class FuncPack<TContext = unknown> {
/** 函数 */ /** 函数 */
public func: Function; public func: EventHandler;
/** 上下文 */ /** 上下文 */
public context: TContext; public context: TContext;
constructor(func: Function, context: TContext) { constructor(func: EventHandler, context: TContext) {
this.func = func; this.func = func;
this.context = context; this.context = context;
} }
@@ -29,7 +31,7 @@ export class Emitter<T, TContext = unknown> {
* @param handler 监听函数 * @param handler 监听函数
* @param context 监听上下文 * @param context 监听上下文
*/ */
public addObserver(eventType: T, handler: Function, context: TContext) { public addObserver(eventType: T, handler: EventHandler, context: TContext) {
let list = this._messageTable.get(eventType); let list = this._messageTable.get(eventType);
if (!list) { if (!list) {
list = []; list = [];
@@ -46,10 +48,10 @@ export class Emitter<T, TContext = unknown> {
* @param eventType 事件类型 * @param eventType 事件类型
* @param handler 事件函数 * @param handler 事件函数
*/ */
public removeObserver(eventType: T, handler: Function) { public removeObserver(eventType: T, handler: EventHandler) {
let messageData = this._messageTable.get(eventType); const messageData = this._messageTable.get(eventType);
if (messageData) { if (messageData) {
let index = messageData.findIndex(data => data.func == handler); const index = messageData.findIndex((data) => data.func == handler);
if (index != -1) if (index != -1)
messageData.splice(index, 1); messageData.splice(index, 1);
} }
@@ -61,9 +63,9 @@ export class Emitter<T, TContext = unknown> {
* @param data 事件数据 * @param data 事件数据
*/ */
public emit<TData = unknown>(eventType: T, ...data: TData[]) { public emit<TData = unknown>(eventType: T, ...data: TData[]) {
let list = this._messageTable.get(eventType); const list = this._messageTable.get(eventType);
if (list) { if (list) {
for (let observer of list) { for (const observer of list) {
observer.func.call(observer.context, ...data); observer.func.call(observer.context, ...data);
} }
} }
@@ -74,9 +76,9 @@ export class Emitter<T, TContext = unknown> {
* @param eventType 事件类型 * @param eventType 事件类型
* @param handler 事件函数 * @param handler 事件函数
*/ */
public hasObserver(eventType: T, handler: Function): boolean { public hasObserver(eventType: T, handler: EventHandler): boolean {
let list = this._messageTable.get(eventType); const list = this._messageTable.get(eventType);
return list ? list.some(observer => observer.func === handler) : false; return list ? list.some((observer) => observer.func === handler) : false;
} }
/** /**

View File

@@ -1,5 +1,5 @@
import { Colors, LogLevel } from "./Constants"; import { Colors, LogLevel } from './Constants';
import { ILogger, LoggerColorConfig, LoggerConfig } from "./Types"; import { ILogger, LoggerColorConfig, LoggerConfig } from './Types';
/** /**

View File

@@ -1,6 +1,6 @@
import { ConsoleLogger } from "./ConsoleLogger"; import { ConsoleLogger } from './ConsoleLogger';
import { LogLevel } from "./Constants"; import { LogLevel } from './Constants';
import { ILogger, LoggerColorConfig } from "./Types"; import { ILogger, LoggerColorConfig } from './Types';
/** /**
* 日志管理器 * 日志管理器

View File

@@ -1,4 +1,4 @@
import type { LogLevel } from "./Constants"; import type { LogLevel } from './Constants';
/** /**
* 日志接口 * 日志接口

View File

@@ -276,12 +276,12 @@ export class PerformanceMonitor implements IService {
*/ */
public getPerformanceReport(): string { public getPerformanceReport(): string {
if (!this._isEnabled) { if (!this._isEnabled) {
return "Performance monitoring is disabled."; return 'Performance monitoring is disabled.';
} }
const lines: string[] = []; const lines: string[] = [];
lines.push("=== ECS Performance Report ==="); lines.push('=== ECS Performance Report ===');
lines.push(""); lines.push('');
// 按平均执行时间排序 // 按平均执行时间排序
const sortedSystems = Array.from(this._systemStats.entries()) const sortedSystems = Array.from(this._systemStats.entries())
@@ -300,7 +300,7 @@ export class PerformanceMonitor implements IService {
lines.push(` Per Entity: ${data.averageTimePerEntity.toFixed(4)}ms`); lines.push(` Per Entity: ${data.averageTimePerEntity.toFixed(4)}ms`);
} }
lines.push(""); lines.push('');
} }
// 总体统计 // 总体统计

View File

@@ -1,11 +1,13 @@
import { IPoolable, PoolStats } from './IPoolable'; import { IPoolable, PoolStats } from './IPoolable';
type Constructor<T = unknown> = new (...args: unknown[]) => T;
/** /**
* 高性能通用对象池 * 高性能通用对象池
* 支持任意类型的对象池化,包含详细的统计信息 * 支持任意类型的对象池化,包含详细的统计信息
*/ */
export class Pool<T extends IPoolable> { export class Pool<T extends IPoolable> {
private static _pools = new Map<Function, Pool<any>>(); private static _pools = new Map<Constructor, Pool<IPoolable>>();
private _objects: T[] = []; private _objects: T[] = [];
private _createFn: () => T; private _createFn: () => T;
@@ -46,11 +48,11 @@ export class Pool<T extends IPoolable> {
maxSize: number = 100, maxSize: number = 100,
estimatedObjectSize: number = 1024 estimatedObjectSize: number = 1024
): Pool<T> { ): Pool<T> {
let pool = this._pools.get(type); let pool = this._pools.get(type) as Pool<T> | undefined;
if (!pool) { if (!pool) {
pool = new Pool<T>(() => new type(), maxSize, estimatedObjectSize); pool = new Pool<T>(() => new type(), maxSize, estimatedObjectSize);
this._pools.set(type, pool); this._pools.set(type, pool as Pool<IPoolable>);
} }
return pool; return pool;
@@ -197,7 +199,7 @@ export class Pool<T extends IPoolable> {
* 获取所有已注册的池类型 * 获取所有已注册的池类型
* @returns 所有池类型的数组 * @returns 所有池类型的数组
*/ */
public static getAllPoolTypes(): Function[] { public static getAllPoolTypes(): Constructor[] {
return Array.from(this._pools.keys()); return Array.from(this._pools.keys());
} }

View File

@@ -7,7 +7,7 @@ import type { IService } from '../../Core/ServiceContainer';
* 统一管理所有对象池 * 统一管理所有对象池
*/ */
export class PoolManager implements IService { export class PoolManager implements IService {
private pools = new Map<string, Pool<any>>(); private pools = new Map<string, Pool<IPoolable>>();
private autoCompactInterval = 60000; // 60秒 private autoCompactInterval = 60000; // 60秒
private lastCompactTime = 0; private lastCompactTime = 0;
@@ -30,7 +30,7 @@ export class PoolManager implements IService {
* @returns 池实例 * @returns 池实例
*/ */
public getPool<T extends IPoolable>(name: string): Pool<T> | null { public getPool<T extends IPoolable>(name: string): Pool<T> | null {
return this.pools.get(name) || null; return (this.pools.get(name) as Pool<T> | undefined) || null;
} }
/** /**

View File

@@ -30,7 +30,7 @@ export class TimerManager implements IService, IUpdatable {
* @param onTime * @param onTime
*/ */
public schedule<TContext = unknown>(timeInSeconds: number, repeats: boolean, context: TContext, onTime: (timer: ITimer<TContext>)=>void): Timer<TContext> { public schedule<TContext = unknown>(timeInSeconds: number, repeats: boolean, context: TContext, onTime: (timer: ITimer<TContext>)=>void): Timer<TContext> {
let timer = new Timer<TContext>(); const timer = new Timer<TContext>();
timer.initialize(timeInSeconds, repeats, context, onTime); timer.initialize(timeInSeconds, repeats, context, onTime);
this._timers.push(timer as Timer<unknown>); this._timers.push(timer as Timer<unknown>);

View File

@@ -27,7 +27,6 @@ describe('Component - 组件基类测试', () => {
let scene: Scene; let scene: Scene;
beforeEach(() => { beforeEach(() => {
Component._idGenerator = 0;
component = new TestComponent(); component = new TestComponent();
scene = new Scene(); scene = new Scene();
entity = scene.createEntity('TestEntity'); entity = scene.createEntity('TestEntity');
@@ -51,7 +50,7 @@ describe('Component - 组件基类测试', () => {
}); });
test('组件ID应该递增分配', () => { test('组件ID应该递增分配', () => {
const startId = Component._idGenerator; const startId = Component.nextComponentId;
const component1 = new TestComponent(); const component1 = new TestComponent();
const component2 = new TestComponent(); const component2 = new TestComponent();