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-return": "warn",
"@typescript-eslint/no-unsafe-argument": "warn",
"@typescript-eslint/no-unsafe-function-type": "error",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@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": [
"node_modules/",

View File

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

View File

@@ -76,8 +76,8 @@ export interface UpdatableMetadata {
* ```
*/
export function Injectable(): ClassDecorator {
return function (target: Function): void {
const existing = injectableMetadata.get(target as Constructor);
return function (target: Constructor): void {
const existing = injectableMetadata.get(target);
injectableMetadata.set(target as Constructor, {
injectable: true,
@@ -117,13 +117,13 @@ export function Injectable(): ClassDecorator {
* ```
*/
export function Updatable(priority: number = 0): ClassDecorator {
return function (target: Function): void {
return function (target: Constructor): void {
// 验证类原型上是否有update方法
const prototype = (target as Constructor & { prototype: { update?: unknown } }).prototype;
if (!prototype || typeof prototype.update !== 'function') {
throw new Error(
`@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);
* ```
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function createInstance<T>(
constructor: new (...args: any[]) => T,
container: ServiceContainer
@@ -249,7 +250,7 @@ export function createInstance<T>(
if (typeof serviceType === 'string' || typeof serviceType === 'symbol') {
// 字符串或Symbol类型的服务标识
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}`
);
} else {
@@ -338,7 +339,7 @@ export function registerInjectable<T extends IService>(
if (!isInjectable(serviceType)) {
throw new Error(
`${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;
/**
@@ -240,7 +241,7 @@ export class ServiceContainer {
// 检测循环依赖
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}`);
}
@@ -337,7 +338,7 @@ export class ServiceContainer {
// 如果有单例实例,调用 dispose
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) {
this._updatableServices.splice(index, 1);
}

View File

@@ -36,7 +36,16 @@ export abstract class Component implements IComponent {
*
* 用于为每个组件分配唯一的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给组件。
*/
constructor() {
this.id = Component._idGenerator++;
this.id = Component._nextId++;
}
/**

View File

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

View File

@@ -9,7 +9,6 @@ import { ComponentRegistry, ComponentType } from './ComponentStorage/ComponentRe
export { ComponentRegistry, ComponentType };
/**
* 高性能组件存储器
*/
@@ -152,7 +151,7 @@ export class ComponentStorage<T extends Component> {
usedSlots: number;
freeSlots: number;
fragmentation: number;
} {
} {
const totalSlots = this.dense.length;
const usedSlots = this.dense.length;
const freeSlots = 0; // 永远无空洞
@@ -173,7 +172,7 @@ export class ComponentStorage<T extends Component> {
*/
export class ComponentStorageManager {
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存储
@@ -342,7 +341,7 @@ export class ComponentStorageManager {
* @returns 组件位掩码
*/
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()) {
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;
/**
@@ -14,9 +15,9 @@ export type ComponentType<T extends Component = Component> = new (...args: any[]
*/
export class ComponentRegistry {
protected static readonly _logger = createLogger('ComponentStorage');
private static componentTypes = new Map<Function, number>();
private static bitIndexToType = new Map<number, Function>();
private static componentNameToType = new Map<string, Function>();
private static componentTypes = new Map<ComponentType, number>();
private static bitIndexToType = new Map<number, ComponentType>();
private static componentNameToType = new Map<string, ComponentType>();
private static componentNameToId = new Map<string, number>();
private static maskCache = new Map<string, BitMask64Data>();
private static nextBitIndex = 0;
@@ -102,7 +103,7 @@ export class ComponentRegistry {
* @param componentName 组件名称
* @returns 组件类型构造函数
*/
public static getComponentType(componentName: string): Function | null {
public static getComponentType(componentName: string): ComponentType | null {
return this.componentNameToType.get(componentName) || null;
}
@@ -110,7 +111,7 @@ export class ComponentRegistry {
* 获取所有已注册的组件类型
* @returns 组件类型映射
*/
public static getAllRegisteredTypes(): Map<Function, number> {
public static getAllRegisteredTypes(): Map<ComponentType, number> {
return new Map(this.componentTypes);
}
@@ -118,7 +119,7 @@ export class ComponentRegistry {
* 获取所有组件名称到类型的映射
* @returns 名称到类型的映射
*/
public static getAllComponentNames(): Map<string, Function> {
public static getAllComponentNames(): Map<string, ComponentType> {
return new Map(this.componentNameToType);
}
@@ -181,7 +182,7 @@ export class ComponentRegistry {
return this.maskCache.get(cacheKey)!;
}
let mask = BitMask64Utils.clone(BitMask64Utils.ZERO);
const mask = BitMask64Utils.clone(BitMask64Utils.ZERO);
for (const name of componentNames) {
const componentId = this.getComponentId(name);
if (componentId !== undefined) {

View File

@@ -127,7 +127,7 @@ export class EventBus implements IEventBus {
handler: (data: T) => Promise<void>,
config: IEventListenerConfig = {}
): 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;
/** 执行上下文 */
context?: any;
context?: unknown;
}
/**
* 内部事件监听器
*/
interface InternalEventListener<T = any> {
interface InternalEventListener<T = unknown> {
handler: EventHandler<T> | AsyncEventHandler<T>;
config: EventListenerConfig;
id: string;
@@ -71,8 +71,8 @@ export class TypeSafeEventSystem {
private static readonly _logger = createLogger('EventSystem');
private listeners = new Map<string, InternalEventListener[]>();
private stats = new Map<string, EventStats>();
private batchQueue = new Map<string, any[]>();
private batchTimers = new Map<string, number>();
private batchQueue = new Map<string, unknown[]>();
private batchTimers = new Map<string, ReturnType<typeof setTimeout>>();
private batchConfigs = new Map<string, EventBatchConfig>();
private nextListenerId = 0;
private isEnabled = true;
@@ -133,7 +133,7 @@ export class TypeSafeEventSystem {
const listeners = this.listeners.get(eventType);
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;
listeners.splice(index, 1);
@@ -353,7 +353,7 @@ export class TypeSafeEventSystem {
id: listenerId
};
listeners.push(listener);
listeners.push(listener as InternalEventListener);
// 初始化统计信息
if (!this.stats.has(eventType)) {
@@ -379,8 +379,8 @@ export class TypeSafeEventSystem {
const sortedListeners = this.sortListenersByPriority(listeners);
// 分离同步和异步监听器
const syncListeners = sortedListeners.filter(l => !l.config.async);
const asyncListeners = sortedListeners.filter(l => l.config.async);
const syncListeners = sortedListeners.filter((l) => !l.config.async);
const asyncListeners = sortedListeners.filter((l) => l.config.async);
// 执行同步监听器
for (const listener of syncListeners) {
@@ -447,7 +447,7 @@ export class TypeSafeEventSystem {
if (!listeners) return;
for (const id of listenerIds) {
const index = listeners.findIndex(l => l.id === id);
const index = listeners.findIndex((l) => l.id === id);
if (index !== -1) {
listeners.splice(index, 1);
}
@@ -488,7 +488,7 @@ export class TypeSafeEventSystem {
this.flushBatch(eventType);
}, 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();

View File

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

View File

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

View File

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

View File

@@ -131,7 +131,7 @@ export class QuerySystem {
if (entities.length === 0) return;
// 使用Set来快速检查重复
const existingIds = new Set(this.entities.map(e => e.id));
const existingIds = new Set(this.entities.map((e) => e.id));
let addedCount = 0;
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);
return name;
}).sort().join(',');
@@ -810,7 +810,7 @@ export class QuerySystem {
*/
private createComponentMask(componentTypes: ComponentType[]): BitMask64Data {
// 生成缓存键
const cacheKey = componentTypes.map(t => {
const cacheKey = componentTypes.map((t) => {
return getComponentTypeName(t);
}).sort().join(',');
@@ -821,7 +821,7 @@ export class QuerySystem {
}
// 使用ComponentRegistry而不是ComponentTypeManager,确保bitIndex一致
let mask = BitMask64Utils.clone(BitMask64Utils.ZERO);
const mask = BitMask64Utils.clone(BitMask64Utils.ZERO);
for (const type of componentTypes) {
// 确保组件已注册
if (!ComponentRegistry.isRegistered(type)) {
@@ -843,11 +843,31 @@ export class QuerySystem {
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[] {
return this.entities;
return this.queryAllEntities();
}
/**
@@ -875,13 +895,17 @@ export class QuerySystem {
cacheHitRate: string;
};
optimizationStats: {
archetypeSystem: any;
archetypeSystem: Array<{
id: BitMask64Data;
componentTypes: string[];
entityCount: number;
}>;
};
cacheStats: {
size: number;
hitRate: string;
};
} {
} {
return {
entityCount: this.entities.length,
indexStats: {
@@ -895,9 +919,9 @@ export class QuerySystem {
(this.queryStats.cacheHits / this.queryStats.totalQueries * 100).toFixed(2) + '%' : '0%'
},
optimizationStats: {
archetypeSystem: this.archetypeSystem.getAllArchetypes().map(a => ({
archetypeSystem: this.archetypeSystem.getAllArchetypes().map((a) => ({
id: a.id,
componentTypes: a.componentTypes.map(t => getComponentTypeName(t)),
componentTypes: a.componentTypes.map((t) => getComponentTypeName(t)),
entityCount: a.entities.size
}))
},
@@ -1023,7 +1047,7 @@ export class QuerySystem {
}
case QueryConditionType.NONE: {
const mask = this.createComponentMask(componentTypes);
return this.entities.filter(entity =>
return this.entities.filter((entity) =>
BitMask64Utils.hasNone(entity.componentMask, mask)
);
}
@@ -1241,7 +1265,7 @@ export class QueryBuilder {
* 创建组件掩码
*/
private createComponentMask(componentTypes: ComponentType[]): BitMask64Data {
let mask = BitMask64Utils.clone(BitMask64Utils.ZERO);
const mask = BitMask64Utils.clone(BitMask64Utils.ZERO);
for (const type of componentTypes) {
try {
const bitMask = ComponentRegistry.getBitMask(type);

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
import type {Component} from '../Component';
import type {EntitySystem} from '../Systems';
import {ComponentType} from "../../Types";
import type { Component } from '../Component';
import type { EntitySystem } from '../Systems';
import { ComponentType } from '../../Types';
/**
* 存储组件类型名称的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
*/
public get isDestroyed(): boolean {
return this._isDestroyed;
return this._destroyed;
}
/**
@@ -394,11 +402,11 @@ export class Entity {
const componentType = component.constructor as ComponentType<T>;
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) {
throw new Error(`Scene does not have componentStorageManager`);
throw new Error('Scene does not have componentStorageManager');
}
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 {
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) {
@@ -898,11 +903,11 @@ export class Entity {
* 移除所有组件、子实体并标记为已销毁
*/
public destroy(): void {
if (this._isDestroyed) {
if (this._destroyed) {
return;
}
this._isDestroyed = true;
this._destroyed = true;
if (this.scene && this.scene.referenceTracker) {
this.scene.referenceTracker.clearReferencesTo(this.id);
@@ -949,7 +954,7 @@ export class Entity {
collectChildren(this);
for (const entity of toDestroy) {
entity._isDestroyed = true;
entity.setDestroyed(true);
}
for (const entity of toDestroy) {
@@ -1007,20 +1012,20 @@ export class Entity {
childIds: number[];
depth: number;
cacheBuilt: boolean;
} {
} {
return {
name: this.name,
id: this.id,
enabled: this._enabled,
active: this._active,
activeInHierarchy: this.activeInHierarchy,
destroyed: this._isDestroyed,
destroyed: this._destroyed,
componentCount: this.components.length,
componentTypes: this.components.map(c => getComponentInstanceTypeName(c)),
componentTypes: this.components.map((c) => getComponentInstanceTypeName(c)),
componentMask: BitMask64Utils.toString(this._componentMask, 2), // 二进制表示
parentId: this._parent?.id || null,
childCount: this._children.length,
childIds: this._children.map(c => c.id),
childIds: this._children.map((c) => c.id),
depth: this.getDepth(),
cacheBuilt: this._componentCache !== null
};

View File

@@ -8,7 +8,7 @@ import { TypeSafeEventSystem } from './Core/EventSystem';
import { EventBus } from './Core/EventBus';
import { ReferenceTracker } from './Core/ReferenceTracker';
import { IScene, ISceneConfig } from './IScene';
import { getComponentInstanceTypeName, getSystemInstanceTypeName, getSystemMetadata } from "./Decorators";
import { getComponentInstanceTypeName, getSystemInstanceTypeName, getSystemMetadata } from './Decorators';
import { TypedQueryBuilder } from './Core/Query/TypedQuery';
import { SceneSerializer, SceneSerializationOptions, SceneDeserializationOptions } from './Serialization/SceneSerializer';
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 实体名称
*/
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 });
@@ -384,7 +384,7 @@ export class Scene implements IScene {
* @param namePrefix 实体名称前缀
* @returns 创建的实体列表
*/
public createEntities(count: number, namePrefix: string = "Entity"): Entity[] {
public createEntities(count: number, namePrefix: string = 'Entity'): Entity[] {
const entities: Entity[] = [];
// 批量创建实体对象,不立即添加到系统
@@ -416,7 +416,7 @@ export class Scene implements IScene {
if (entities.length === 0) return;
for (const entity of entities) {
entity._isDestroyed = true;
entity.setDestroyed(true);
}
for (const entity of entities) {
@@ -609,7 +609,7 @@ export class Scene implements IScene {
} else {
this.logger.warn(
`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;
}
@@ -750,7 +750,7 @@ export class Scene implements IScene {
entityCount: number;
processorCount: number;
componentStorageStats: Map<string, any>;
} {
} {
return {
entityCount: this.entities.count,
processorCount: this.systems.length,
@@ -779,20 +779,20 @@ export class Scene implements IScene {
entityCount: number;
}>;
componentStats: Map<string, any>;
} {
} {
const systems = this.systems;
return {
name: this.name || this.constructor.name,
entityCount: this.entities.count,
processorCount: systems.length,
isRunning: this._didSceneBegin,
entities: this.entities.buffer.map(entity => ({
entities: this.entities.buffer.map((entity) => ({
name: entity.name,
id: entity.id,
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),
updateOrder: processor.updateOrder,
entityCount: (processor as any)._entities?.length || 0

View File

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

View File

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

View File

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

View File

@@ -127,7 +127,7 @@ export class VersionMigrationManager {
return component;
}
let migratedData = { ...component };
const migratedData = { ...component };
let version = currentVersion;
// 执行迁移链
@@ -193,12 +193,12 @@ export class VersionMigrationManager {
private static migrateSceneComponents(scene: SerializedScene): SerializedScene {
const migratedScene = { ...scene };
migratedScene.entities = scene.entities.map(entity => ({
migratedScene.entities = scene.entities.map((entity) => ({
...entity,
components: entity.components.map(component => {
components: entity.components.map((component) => {
// 查找组件的目标版本
const typeInfo = scene.componentTypeRegistry.find(
t => t.typeName === component.type
(t) => t.typeName === component.type
);
if (typeInfo && typeInfo.version !== component.version) {
@@ -220,10 +220,10 @@ export class VersionMigrationManager {
entities: any[],
typeRegistry: Array<{ typeName: string; version: number }>
): any[] {
return entities.map(entity => ({
return entities.map((entity) => ({
...entity,
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) {
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 { ComponentConstructor, ComponentInstance } from '../../Types/TypeHelpers';
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 {
this._entityCache.invalidate();
@@ -299,7 +303,7 @@ export abstract class EntitySystem<
// 空条件返回所有实体
if (this._matcher.isEmpty()) {
currentEntities = querySystem.getAllEntities();
currentEntities = querySystem.queryAllEntities();
} else if (this.isSingleCondition(condition)) {
// 单一条件优化查询
currentEntities = this.executeSingleConditionQuery(condition, querySystem);
@@ -403,7 +407,7 @@ export abstract class EntitySystem<
// 6. 应用none条件 (差集)
if (condition.none.length > 0) {
if (!resultIds) {
resultIds = this.extractEntityIds(querySystem.getAllEntities());
resultIds = this.extractEntityIds(querySystem.queryAllEntities());
}
const noneResult = querySystem.queryAny(...condition.none);
@@ -411,16 +415,23 @@ export abstract class EntitySystem<
resultIds = this.differenceIdSets(resultIds, noneIds);
}
return resultIds ? this.idSetToEntityArray(resultIds, querySystem.getAllEntities()) : [];
return resultIds ? this.idSetToEntityArray(resultIds, querySystem.queryAllEntities()) : [];
}
/**
* 提取实体ID集合
*
* 使用位运算 | 0 强制转换为 32 位整数,帮助 JavaScript 引擎的 JIT 编译器
* 进行整数优化,在大规模实体集合操作时可以提供微小的性能提升。
*
* @param entities 实体数组
* @returns 包含所有实体ID的集合
*/
private extractEntityIds(entities: readonly Entity[]): Set<number> {
const len = entities.length;
const idSet = new Set<number>();
// 使用位运算 | 0 进行整数优化JIT 友好)
for (let i = 0; i < len; i = (i + 1) | 0) {
idSet.add(entities[i]!.id | 0);
}
@@ -482,6 +493,12 @@ export abstract class EntitySystem<
/**
* 重建实体ID映射
*
* 重新构建从实体ID到实体引用的映射表。使用位运算优化性能。
*
* @param allEntities 所有实体的数组
* @param version QuerySystem 的版本号,用于缓存失效判断
* @returns 重建后的实体ID映射表
*/
private rebuildEntityIdMap(allEntities: readonly Entity[], version: number): Map<number, Entity> {
let entityMap = this._entityIdMap;
@@ -493,6 +510,7 @@ export abstract class EntitySystem<
}
const len = allEntities.length;
// 使用位运算 | 0 进行整数优化JIT 友好)
for (let i = 0; i < len; i = (i + 1) | 0) {
const entity = allEntities[i]!;
entityMap.set(entity.id | 0, entity);
@@ -506,6 +524,12 @@ export abstract class EntitySystem<
/**
* 从ID集合构建Entity数组
*
* 将实体ID集合转换为实体引用数组。跳过无效的实体ID已被删除的实体
*
* @param idSet 实体ID集合
* @param allEntities 所有实体的数组(用于构建映射表)
* @returns 实体引用数组
*/
private idSetToEntityArray(idSet: Set<number>, allEntities: readonly Entity[]): readonly Entity[] {
const entityMap = this.getEntityIdMap(allEntities);
@@ -518,10 +542,12 @@ export abstract class EntitySystem<
const entity = entityMap.get(id);
if (entity !== undefined) {
result[index] = entity;
// 使用位运算 | 0 进行整数优化JIT 友好)
index = (index + 1) | 0;
}
}
// 如果有无效ID调整数组长度
if (index < size) {
result.length = index;
}
@@ -786,7 +812,7 @@ export abstract class EntitySystem<
this._eventListeners.push({
eventSystem: this.scene.eventSystem,
eventType,
handler,
handler: handler as EventHandler,
listenerRef
});
}
@@ -803,7 +829,7 @@ export abstract class EntitySystem<
handler: EventHandler<T>
): void {
const listenerIndex = this._eventListeners.findIndex(
listener => listener.eventType === eventType && listener.handler === handler
(listener) => listener.eventType === eventType && listener.handler === handler
);
if (listenerIndex >= 0) {
@@ -891,7 +917,7 @@ export abstract class EntitySystem<
entity: Entity,
componentType: T
): ComponentInstance<T> {
const component = entity.getComponent(componentType as any);
const component = entity.getComponent(componentType as ComponentType);
if (!component) {
throw new Error(
`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]> } {
return components.map((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}
};
userProcessFunction(sharedFloatArray, startIndex, endIndex, deltaTime, systemConfig);
` : ``}
` : ''}
}
`;
}
@@ -494,7 +494,7 @@ export abstract class WorkerEntitySystem<TEntityData = any> extends EntitySystem
const deltaTime = Time.deltaTime;
// 3. Worker执行阶段
const promises = batches.map(batch =>
const promises = batches.map((batch) =>
this.workerPool!.execute({
entities: batch,
deltaTime,
@@ -525,7 +525,7 @@ export abstract class WorkerEntitySystem<TEntityData = any> extends EntitySystem
*/
private processSynchronously(entities: readonly Entity[]): void {
// 1. 数据提取阶段
const entityData = entities.map(entity => this.extractEntityData(entity));
const entityData = entities.map((entity) => this.extractEntityData(entity));
// 2. 主线程处理阶段
const deltaTime = Time.deltaTime;
@@ -534,7 +534,7 @@ export abstract class WorkerEntitySystem<TEntityData = any> extends EntitySystem
// 3. 结果应用阶段
// 处理Promise返回值
if (results && typeof (results as any).then === 'function') {
(results as Promise<TEntityData[]>).then(finalResults => {
(results as Promise<TEntityData[]>).then((finalResults) => {
entities.forEach((entity, index) => {
this.applyResult(entity, finalResults[index]!);
});
@@ -813,7 +813,7 @@ export abstract class WorkerEntitySystem<TEntityData = any> extends EntitySystem
sharedArrayBufferSupported: boolean;
sharedArrayBufferEnabled: boolean;
currentMode: 'shared-buffer' | 'worker' | 'sync';
} {
} {
let currentMode: 'shared-buffer' | 'worker' | 'sync' = 'sync';
if (this.config.enableWorker && this.workerPool) {

View File

@@ -69,7 +69,7 @@ export class BitMask64Utils {
return maskSegments.some((seg, index) => {
const bitsSeg = bitsSegments[index];
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;
}
// 额外检查扩展区域是否都为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
*/
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比较结果
if(!baseEquals || (!a.segments && !b.segments)) return baseEquals;
// 不能假设ab的segments都存在或长度相同.
@@ -355,7 +355,7 @@ export class BitMask64Utils {
if(!source.segments || source.segments.length == 0) return;
// 没有拓展段,则直接复制数组
if(!target.segments){
target.segments = source.segments.map(seg => [...seg]);
target.segments = source.segments.map((seg) => [...seg]);
return;
}
// source有扩展段target扩展段不足则补充长度
@@ -382,7 +382,7 @@ export class BitMask64Utils {
public static clone(mask: BitMask64Data): BitMask64Data {
return {
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++) {
let segResult = '';
const bitMaskData = i == -1 ? mask.base : mask.segments![i]!;
let hi = bitMaskData[SegmentPart.HIGH];
let lo = bitMaskData[SegmentPart.LOW];
const hi = bitMaskData[SegmentPart.HIGH];
const lo = bitMaskData[SegmentPart.LOW];
if(radix == 2){
const hiBits = hi.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

View File

@@ -77,7 +77,7 @@ export class ComponentSparseSet {
this.removeEntity(entity);
}
let componentMask = BitMask64Utils.clone(BitMask64Utils.ZERO);
const componentMask = BitMask64Utils.clone(BitMask64Utils.ZERO);
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) {
if (!ComponentRegistry.isRegistered(componentType)) {
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) {
if (ComponentRegistry.isRegistered(componentType)) {
const bitMask = ComponentRegistry.getBitMask(componentType);
@@ -272,14 +272,26 @@ export class ComponentSparseSet {
}
/**
* 获取所有实体
* 查询所有实体
*
* 返回拥有此组件的所有实体。
*
* @returns 所有实体的数组
*/
public getAllEntities(): Entity[] {
public queryAllEntities(): Entity[] {
return this._entities.toArray();
}
/**
* 获取所有实体
*
* @deprecated 使用 queryAllEntities() 代替,以保持命名一致性
* @see {@link queryAllEntities}
*/
public getAllEntities(): Entity[] {
return this.queryAllEntities();
}
/**
* 获取实体数量
*/
@@ -327,7 +339,7 @@ export class ComponentSparseSet {
masksMemory: number;
mappingsMemory: number;
totalMemory: number;
} {
} {
const entitiesStats = this._entities.getMemoryStats();
const masksMemory = this._componentMasks.length * 16; // 估计每个BigInt 16字节

View File

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

View File

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

View File

@@ -267,15 +267,15 @@ export class Matcher {
const parts: string[] = [];
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) {
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) {
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) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -34,7 +34,7 @@ export class PerformanceDataCollector {
}
// 计算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 minECSTime = history.length > 0 ? Math.min(...history) : ecsExecutionTimeMs;
const maxECSTime = history.length > 0 ? Math.max(...history) : ecsExecutionTimeMs;
@@ -100,7 +100,7 @@ export class PerformanceDataCollector {
}
// 计算各系统占ECS总时间的百分比
systemBreakdown.forEach(system => {
systemBreakdown.forEach((system) => {
system.percentage = totalTime > 0 ? (system.executionTime / totalTime * 100) : 0;
});

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
import { ConsoleLogger } from "./ConsoleLogger";
import { LogLevel } from "./Constants";
import { ILogger, LoggerColorConfig } from "./Types";
import { ConsoleLogger } from './ConsoleLogger';
import { LogLevel } from './Constants';
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 {
if (!this._isEnabled) {
return "Performance monitoring is disabled.";
return 'Performance monitoring is disabled.';
}
const lines: string[] = [];
lines.push("=== ECS Performance Report ===");
lines.push("");
lines.push('=== ECS Performance Report ===');
lines.push('');
// 按平均执行时间排序
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("");
lines.push('');
}
// 总体统计

View File

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

View File

@@ -7,7 +7,7 @@ import type { IService } from '../../Core/ServiceContainer';
* 统一管理所有对象池
*/
export class PoolManager implements IService {
private pools = new Map<string, Pool<any>>();
private pools = new Map<string, Pool<IPoolable>>();
private autoCompactInterval = 60000; // 60秒
private lastCompactTime = 0;
@@ -30,7 +30,7 @@ export class PoolManager implements IService {
* @returns 池实例
*/
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
*/
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);
this._timers.push(timer as Timer<unknown>);

View File

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