From bda547dd2e95eac001e8e2b39ab0ed56078054bf Mon Sep 17 00:00:00 2001 From: YHH <359807859@qq.com> Date: Wed, 3 Sep 2025 00:39:00 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8A=8A=E6=8E=A9=E7=A0=81=E4=BB=8EBigInt-like?= =?UTF-8?q?=E5=A4=9A=E6=80=81=E9=83=BD=E6=94=B9=E6=88=90Mask64?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/src/ECS/Core/ComponentStorage.ts | 204 +----------------- .../ComponentStorage/ComponentRegistry.ts | 19 +- packages/core/src/ECS/Core/QuerySystem.ts | 22 +- packages/core/src/ECS/Entity.ts | 20 +- .../core/src/ECS/Utils/ComponentSparseSet.ts | 30 +-- 5 files changed, 53 insertions(+), 242 deletions(-) diff --git a/packages/core/src/ECS/Core/ComponentStorage.ts b/packages/core/src/ECS/Core/ComponentStorage.ts index d4a33ed4..45c43690 100644 --- a/packages/core/src/ECS/Core/ComponentStorage.ts +++ b/packages/core/src/ECS/Core/ComponentStorage.ts @@ -1,205 +1,15 @@ import { Component } from '../Component'; -import { IBigIntLike, BigIntFactory } from '../Utils/BigIntCompatibility'; +import { BitMask64Utils, BitMask64Data } from '../Utils/BigIntCompatibility'; import { SoAStorage, EnableSoA, HighPrecision, Float64, Int32, SerializeMap, SerializeSet, SerializeArray, DeepCopy } from './SoAStorage'; import { createLogger } from '../../Utils/Logger'; import { getComponentTypeName } from '../Decorators'; +import { ComponentRegistry, ComponentType } from './ComponentStorage/ComponentRegistry'; -// 重新导出装饰器 +// 重新导出装饰器和核心类型 export { EnableSoA, HighPrecision, Float64, Int32, SerializeMap, SerializeSet, SerializeArray, DeepCopy }; +export { ComponentRegistry, ComponentType }; -/** - * 组件类型定义 - * 支持任意构造函数签名,提供更好的类型安全性 - */ -export type ComponentType = new (...args: any[]) => T; -/** - * 组件注册表 - * 管理组件类型的位掩码分配 - */ -export class ComponentRegistry { - protected static readonly _logger = createLogger('ComponentStorage'); - private static componentTypes = new Map(); - private static componentNameToType = new Map(); - private static componentNameToId = new Map(); - private static maskCache = new Map(); - private static nextBitIndex = 0; - private static maxComponents = 64; // 支持最多64种组件类型 - - /** - * 注册组件类型并分配位掩码 - * @param componentType 组件类型 - * @returns 分配的位索引 - */ - public static register(componentType: ComponentType): number { - if (this.componentTypes.has(componentType)) { - return this.componentTypes.get(componentType)!; - } - - if (this.nextBitIndex >= this.maxComponents) { - throw new Error(`Maximum number of component types (${this.maxComponents}) exceeded`); - } - - const bitIndex = this.nextBitIndex++; - this.componentTypes.set(componentType, bitIndex); - this.componentNameToType.set(getComponentTypeName(componentType), componentType); - this.componentNameToId.set(getComponentTypeName(componentType), bitIndex); - return bitIndex; - } - - /** - * 获取组件类型的位掩码 - * @param componentType 组件类型 - * @returns 位掩码 - */ - public static getBitMask(componentType: ComponentType): IBigIntLike { - const bitIndex = this.componentTypes.get(componentType); - if (bitIndex === undefined) { - throw new Error(`Component type ${getComponentTypeName(componentType)} is not registered`); - } - return BigIntFactory.one().shiftLeft(bitIndex); - } - - /** - * 获取组件类型的位索引 - * @param componentType 组件类型 - * @returns 位索引 - */ - public static getBitIndex(componentType: ComponentType): number { - const bitIndex = this.componentTypes.get(componentType); - if (bitIndex === undefined) { - throw new Error(`Component type ${getComponentTypeName(componentType)} is not registered`); - } - return bitIndex; - } - - /** - * 检查组件类型是否已注册 - * @param componentType 组件类型 - * @returns 是否已注册 - */ - public static isRegistered(componentType: ComponentType): boolean { - return this.componentTypes.has(componentType); - } - - /** - * 通过名称获取组件类型 - * @param componentName 组件名称 - * @returns 组件类型构造函数 - */ - public static getComponentType(componentName: string): Function | null { - return this.componentNameToType.get(componentName) || null; - } - - /** - * 获取所有已注册的组件类型 - * @returns 组件类型映射 - */ - public static getAllRegisteredTypes(): Map { - return new Map(this.componentTypes); - } - - /** - * 获取所有组件名称到类型的映射 - * @returns 名称到类型的映射 - */ - public static getAllComponentNames(): Map { - return new Map(this.componentNameToType); - } - - /** - * 通过名称获取组件类型ID - * @param componentName 组件名称 - * @returns 组件类型ID - */ - public static getComponentId(componentName: string): number | undefined { - return this.componentNameToId.get(componentName); - } - - /** - * 注册组件类型(通过名称) - * @param componentName 组件名称 - * @returns 分配的组件ID - */ - public static registerComponentByName(componentName: string): number { - if (this.componentNameToId.has(componentName)) { - return this.componentNameToId.get(componentName)!; - } - - if (this.nextBitIndex >= this.maxComponents) { - throw new Error(`Maximum number of component types (${this.maxComponents}) exceeded`); - } - - const bitIndex = this.nextBitIndex++; - this.componentNameToId.set(componentName, bitIndex); - return bitIndex; - } - - /** - * 创建单个组件的掩码 - * @param componentName 组件名称 - * @returns 组件掩码 - */ - public static createSingleComponentMask(componentName: string): IBigIntLike { - const cacheKey = `single:${componentName}`; - - if (this.maskCache.has(cacheKey)) { - return this.maskCache.get(cacheKey)!; - } - - const componentId = this.getComponentId(componentName); - if (componentId === undefined) { - throw new Error(`Component type ${componentName} is not registered`); - } - - const mask = BigIntFactory.one().shiftLeft(componentId); - this.maskCache.set(cacheKey, mask); - return mask; - } - - /** - * 创建多个组件的掩码 - * @param componentNames 组件名称数组 - * @returns 组合掩码 - */ - public static createComponentMask(componentNames: string[]): IBigIntLike { - const sortedNames = [...componentNames].sort(); - const cacheKey = `multi:${sortedNames.join(',')}`; - - if (this.maskCache.has(cacheKey)) { - return this.maskCache.get(cacheKey)!; - } - - let mask = BigIntFactory.zero(); - for (const name of componentNames) { - const componentId = this.getComponentId(name); - if (componentId !== undefined) { - mask = mask.or(BigIntFactory.one().shiftLeft(componentId)); - } - } - - this.maskCache.set(cacheKey, mask); - return mask; - } - - /** - * 清除掩码缓存 - */ - public static clearMaskCache(): void { - this.maskCache.clear(); - } - - /** - * 重置注册表(用于测试) - */ - public static reset(): void { - this.componentTypes.clear(); - this.componentNameToType.clear(); - this.componentNameToId.clear(); - this.maskCache.clear(); - this.nextBitIndex = 0; - } -} /** * 高性能组件存储器 @@ -532,13 +342,13 @@ export class ComponentStorageManager { * @param entityId 实体ID * @returns 组件位掩码 */ - public getComponentMask(entityId: number): IBigIntLike { - let mask = BigIntFactory.zero(); + public getComponentMask(entityId: number): BitMask64Data { + let mask = BitMask64Utils.clone(BitMask64Utils.ZERO); for (const [componentType, storage] of this.storages.entries()) { if (storage.hasComponent(entityId)) { const componentMask = ComponentRegistry.getBitMask(componentType as ComponentType); - mask = mask.or(componentMask); + BitMask64Utils.orInPlace(mask, componentMask); } } diff --git a/packages/core/src/ECS/Core/ComponentStorage/ComponentRegistry.ts b/packages/core/src/ECS/Core/ComponentStorage/ComponentRegistry.ts index 0b60f5a6..5352d459 100644 --- a/packages/core/src/ECS/Core/ComponentStorage/ComponentRegistry.ts +++ b/packages/core/src/ECS/Core/ComponentStorage/ComponentRegistry.ts @@ -1,5 +1,5 @@ import { Component } from '../../Component'; -import { IBigIntLike, BigIntFactory } from '../../Utils/BigIntCompatibility'; +import { BitMask64Utils, BitMask64Data } from '../../Utils/BigIntCompatibility'; import { createLogger } from '../../../Utils/Logger'; import { getComponentTypeName } from '../../Decorators'; @@ -17,7 +17,7 @@ export class ComponentRegistry { private static componentTypes = new Map(); private static componentNameToType = new Map(); private static componentNameToId = new Map(); - private static maskCache = new Map(); + private static maskCache = new Map(); private static nextBitIndex = 0; private static maxComponents = 64; // 支持最多64种组件类型 @@ -51,13 +51,13 @@ export class ComponentRegistry { * @param componentType 组件类型 * @returns 位掩码 */ - public static getBitMask(componentType: ComponentType): IBigIntLike { + public static getBitMask(componentType: ComponentType): BitMask64Data { const bitIndex = this.componentTypes.get(componentType); if (bitIndex === undefined) { const typeName = getComponentTypeName(componentType); throw new Error(`Component type ${typeName} is not registered`); } - return BigIntFactory.one().shiftLeft(bitIndex); + return BitMask64Utils.create(bitIndex); } /** @@ -141,7 +141,7 @@ export class ComponentRegistry { * @param componentName 组件名称 * @returns 组件掩码 */ - public static createSingleComponentMask(componentName: string): IBigIntLike { + public static createSingleComponentMask(componentName: string): BitMask64Data { const cacheKey = `single:${componentName}`; if (this.maskCache.has(cacheKey)) { @@ -153,7 +153,7 @@ export class ComponentRegistry { throw new Error(`Component type ${componentName} is not registered`); } - const mask = BigIntFactory.one().shiftLeft(componentId); + const mask = BitMask64Utils.create(componentId); this.maskCache.set(cacheKey, mask); return mask; } @@ -163,7 +163,7 @@ export class ComponentRegistry { * @param componentNames 组件名称数组 * @returns 组合掩码 */ - public static createComponentMask(componentNames: string[]): IBigIntLike { + public static createComponentMask(componentNames: string[]): BitMask64Data { const sortedNames = [...componentNames].sort(); const cacheKey = `multi:${sortedNames.join(',')}`; @@ -171,11 +171,12 @@ export class ComponentRegistry { return this.maskCache.get(cacheKey)!; } - let mask = BigIntFactory.zero(); + let mask = BitMask64Utils.clone(BitMask64Utils.ZERO); for (const name of componentNames) { const componentId = this.getComponentId(name); if (componentId !== undefined) { - mask = mask.or(BigIntFactory.one().shiftLeft(componentId)); + const componentMask = BitMask64Utils.create(componentId); + BitMask64Utils.orInPlace(mask, componentMask); } } diff --git a/packages/core/src/ECS/Core/QuerySystem.ts b/packages/core/src/ECS/Core/QuerySystem.ts index 1e634088..844def80 100644 --- a/packages/core/src/ECS/Core/QuerySystem.ts +++ b/packages/core/src/ECS/Core/QuerySystem.ts @@ -1,7 +1,7 @@ import { Entity } from '../Entity'; import { Component } from '../Component'; import { ComponentRegistry, ComponentType } from './ComponentStorage'; -import { IBigIntLike, BigIntFactory } from '../Utils/BigIntCompatibility'; +import { BitMask64Utils, BitMask64Data } from '../Utils/BigIntCompatibility'; import { createLogger } from '../../Utils/Logger'; import { getComponentTypeName } from '../Decorators'; @@ -28,7 +28,7 @@ export enum QueryConditionType { export interface QueryCondition { type: QueryConditionType; componentTypes: ComponentType[]; - mask: IBigIntLike; + mask: BitMask64Data; } /** @@ -483,7 +483,7 @@ export class QuerySystem { const result: Entity[] = []; for (const entity of smallestSet) { - if (entity.componentMask.and(mask).equals(mask)) { + if (BitMask64Utils.hasAll(entity.componentMask, mask)) { result.push(entity); } } @@ -587,7 +587,7 @@ export class QuerySystem { const mask = this.createComponentMask(componentTypes); const entities = this.entities.filter(entity => - entity.componentMask.and(mask).isZero() + BitMask64Utils.hasNone(entity.componentMask, mask) ); this.addToCache(cacheKey, entities); @@ -872,14 +872,14 @@ export class QuerySystem { * @param componentTypes 组件类型列表 * @returns 生成的位掩码 */ - private createComponentMask(componentTypes: ComponentType[]): IBigIntLike { - let mask = BigIntFactory.zero(); + private createComponentMask(componentTypes: ComponentType[]): BitMask64Data { + let mask = BitMask64Utils.clone(BitMask64Utils.ZERO); let hasValidComponents = false; for (const type of componentTypes) { try { const bitMask = ComponentRegistry.getBitMask(type); - mask = mask.or(bitMask); + BitMask64Utils.orInPlace(mask, bitMask); hasValidComponents = true; } catch (error) { this._logger.warn(`组件类型 ${getComponentTypeName(type)} 未注册,跳过`); @@ -888,7 +888,7 @@ export class QuerySystem { // 如果没有有效的组件类型,返回一个不可能匹配的掩码 if (!hasValidComponents) { - return BigIntFactory.create(-1); // 所有位都是1,不可能与任何实体匹配 + return { lo: 0xFFFFFFFF, hi: 0xFFFFFFFF }; // 所有位都是1,不可能与任何实体匹配 } return mask; @@ -1134,12 +1134,12 @@ export class QueryBuilder { /** * 创建组件掩码 */ - private createComponentMask(componentTypes: ComponentType[]): IBigIntLike { - let mask = BigIntFactory.zero(); + private createComponentMask(componentTypes: ComponentType[]): BitMask64Data { + let mask = BitMask64Utils.clone(BitMask64Utils.ZERO); for (const type of componentTypes) { try { const bitMask = ComponentRegistry.getBitMask(type); - mask = mask.or(bitMask); + BitMask64Utils.orInPlace(mask, bitMask); } catch (error) { this._logger.warn(`组件类型 ${getComponentTypeName(type)} 未注册,跳过`); } diff --git a/packages/core/src/ECS/Entity.ts b/packages/core/src/ECS/Entity.ts index 7309ebc0..dd4b8a0a 100644 --- a/packages/core/src/ECS/Entity.ts +++ b/packages/core/src/ECS/Entity.ts @@ -1,7 +1,7 @@ import { Component } from './Component'; import { ComponentRegistry, ComponentType } from './Core/ComponentStorage'; import { EventBus } from './Core/EventBus'; -import { IBigIntLike, BigIntFactory } from './Utils/BigIntCompatibility'; +import { BitMask64Utils, BitMask64Data } from './Utils/BigIntCompatibility'; import { createLogger } from '../Utils/Logger'; import { getComponentInstanceTypeName, getComponentTypeName } from './Decorators'; import type { IScene } from './IScene'; @@ -161,7 +161,7 @@ export class Entity { * * 用于快速查询实体拥有的组件类型。 */ - private _componentMask: IBigIntLike = BigIntFactory.zero(); + private _componentMask: BitMask64Data = BitMask64Utils.clone(BitMask64Utils.ZERO); /** * 按组件类型ID直址的稀疏数组 @@ -310,7 +310,7 @@ export class Entity { * * @returns 实体的组件位掩码 */ - public get componentMask(): IBigIntLike { + public get componentMask(): BitMask64Data { return this._componentMask; } @@ -354,7 +354,7 @@ export class Entity { // 更新位掩码 const componentMask = ComponentRegistry.getBitMask(componentType); - this._componentMask = this._componentMask.or(componentMask); + BitMask64Utils.orInPlace(this._componentMask, componentMask); return component; } @@ -422,7 +422,7 @@ export class Entity { } const mask = ComponentRegistry.getBitMask(type); - if (this._componentMask.and(mask).isZero()) { + if (BitMask64Utils.hasNone(this._componentMask, mask)) { return null; } @@ -475,7 +475,7 @@ export class Entity { } const mask = ComponentRegistry.getBitMask(type); - return !this._componentMask.and(mask).isZero(); + return BitMask64Utils.hasAny(this._componentMask, mask); } /** @@ -510,8 +510,8 @@ export class Entity { this._componentsByTypeId[typeId] = undefined; // 更新位掩码 - const componentMask = ComponentRegistry.getBitMask(componentType); - this._componentMask = this._componentMask.and(componentMask.not()); + const bitIndex = ComponentRegistry.getBitIndex(componentType); + BitMask64Utils.clearBit(this._componentMask, bitIndex); } // 从迭代数组中移除 @@ -579,7 +579,7 @@ export class Entity { // 清空稀疏数组和位掩码 this._componentsByTypeId.length = 0; - this._componentMask = BigIntFactory.zero(); + BitMask64Utils.clear(this._componentMask); // 移除组件 for (const component of componentsToRemove) { @@ -981,7 +981,7 @@ export class Entity { destroyed: this._isDestroyed, componentCount: this.components.length, componentTypes: this.components.map(c => getComponentInstanceTypeName(c)), - componentMask: this._componentMask.toString(2), // 二进制表示 + componentMask: BitMask64Utils.toString(this._componentMask, 2), // 二进制表示 parentId: this._parent?.id || null, childCount: this._children.length, childIds: this._children.map(c => c.id), diff --git a/packages/core/src/ECS/Utils/ComponentSparseSet.ts b/packages/core/src/ECS/Utils/ComponentSparseSet.ts index f09dfc4b..ffd87fd8 100644 --- a/packages/core/src/ECS/Utils/ComponentSparseSet.ts +++ b/packages/core/src/ECS/Utils/ComponentSparseSet.ts @@ -1,6 +1,6 @@ import { Entity } from '../Entity'; import { ComponentType, ComponentRegistry } from '../Core/ComponentStorage'; -import { IBigIntLike, BigIntFactory } from './BigIntCompatibility'; +import { BitMask64Utils, BitMask64Data } from './BigIntCompatibility'; import { SparseSet } from './SparseSet'; import { Pool } from '../../Utils/Pool/Pool'; import { IPoolable } from '../../Utils/Pool/IPoolable'; @@ -44,7 +44,7 @@ export class ComponentSparseSet { * 与实体稀疏集合的密集数组对应,存储每个实体的组件位掩码。 * 数组索引与稀疏集合的密集数组索引一一对应。 */ - private _componentMasks: IBigIntLike[] = []; + private _componentMasks: BitMask64Data[] = []; /** * 组件类型到实体集合的映射 @@ -77,7 +77,7 @@ export class ComponentSparseSet { this.removeEntity(entity); } - let componentMask = BigIntFactory.zero(); + let componentMask = BitMask64Utils.clone(BitMask64Utils.ZERO); const entityComponents = new Set(); // 分析实体组件并构建位掩码 @@ -92,7 +92,7 @@ export class ComponentSparseSet { // 获取组件位掩码并合并 const bitMask = ComponentRegistry.getBitMask(componentType); - componentMask = componentMask.or(bitMask); + BitMask64Utils.orInPlace(componentMask, bitMask); } // 添加实体到稀疏集合 @@ -101,7 +101,7 @@ export class ComponentSparseSet { // 确保位掩码数组有足够空间 while (this._componentMasks.length <= entityIndex) { - this._componentMasks.push(BigIntFactory.zero()); + this._componentMasks.push(BitMask64Utils.clone(BitMask64Utils.ZERO)); } this._componentMasks[entityIndex] = componentMask; @@ -169,13 +169,13 @@ export class ComponentSparseSet { } // 构建目标位掩码 - let targetMask = BigIntFactory.zero(); + let targetMask = BitMask64Utils.clone(BitMask64Utils.ZERO); for (const componentType of componentTypes) { if (!ComponentRegistry.isRegistered(componentType)) { return new Set(); // 未注册的组件类型,结果为空 } const bitMask = ComponentRegistry.getBitMask(componentType); - targetMask = targetMask.or(bitMask); + BitMask64Utils.orInPlace(targetMask, bitMask); } const result = ComponentSparseSet._entitySetPool.obtain(); @@ -183,7 +183,7 @@ export class ComponentSparseSet { // 遍历所有实体,检查位掩码匹配 this._entities.forEach((entity, index) => { const entityMask = this._componentMasks[index]; - if ((entityMask.and(targetMask)).equals(targetMask)) { + if (BitMask64Utils.hasAll(entityMask, targetMask)) { result.add(entity); } }); @@ -209,15 +209,15 @@ export class ComponentSparseSet { } // 构建目标位掩码 - let targetMask = BigIntFactory.zero(); + let targetMask = BitMask64Utils.clone(BitMask64Utils.ZERO); for (const componentType of componentTypes) { if (ComponentRegistry.isRegistered(componentType)) { const bitMask = ComponentRegistry.getBitMask(componentType); - targetMask = targetMask.or(bitMask); + BitMask64Utils.orInPlace(targetMask, bitMask); } } - if (targetMask.equals(BigIntFactory.zero())) { + if (BitMask64Utils.equals(targetMask, BitMask64Utils.ZERO)) { return new Set(); // 没有有效的组件类型 } @@ -226,7 +226,7 @@ export class ComponentSparseSet { // 遍历所有实体,检查位掩码匹配 this._entities.forEach((entity, index) => { const entityMask = this._componentMasks[index]; - if (!(entityMask.and(targetMask)).equals(BigIntFactory.zero())) { + if (BitMask64Utils.hasAny(entityMask, targetMask)) { result.add(entity); } }); @@ -254,7 +254,7 @@ export class ComponentSparseSet { const entityMask = this._componentMasks[entityIndex]; const componentMask = ComponentRegistry.getBitMask(componentType); - return !(entityMask.and(componentMask)).equals(BigIntFactory.zero()); + return BitMask64Utils.hasAny(entityMask, componentMask); } /** @@ -263,7 +263,7 @@ export class ComponentSparseSet { * @param entity 实体 * @returns 组件位掩码,如果实体不存在则返回undefined */ - public getEntityMask(entity: Entity): IBigIntLike | undefined { + public getEntityMask(entity: Entity): BitMask64Data | undefined { const entityIndex = this._entities.getIndex(entity); if (entityIndex === undefined) { return undefined; @@ -299,7 +299,7 @@ export class ComponentSparseSet { * * @param callback 遍历回调函数 */ - public forEach(callback: (entity: Entity, mask: IBigIntLike, index: number) => void): void { + public forEach(callback: (entity: Entity, mask: BitMask64Data, index: number) => void): void { this._entities.forEach((entity, index) => { callback(entity, this._componentMasks[index], index); });