项目统一改用Logger控制管理
拆分pool类和FluentAPI
This commit is contained in:
@@ -20,6 +20,5 @@
|
||||
},
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"useWorkspaces": true
|
||||
]
|
||||
}
|
||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -11427,7 +11427,7 @@
|
||||
"ws": "^8.18.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@esengine/ecs-framework": "file:../core",
|
||||
"@esengine/ecs-framework": "*",
|
||||
"@rollup/plugin-commonjs": "^28.0.3",
|
||||
"@rollup/plugin-node-resolve": "^16.0.1",
|
||||
"@rollup/plugin-terser": "^0.4.4",
|
||||
|
||||
@@ -42,7 +42,7 @@ module.exports = {
|
||||
verbose: true,
|
||||
transform: {
|
||||
'^.+\\.tsx?$': ['ts-jest', {
|
||||
tsconfig: 'tsconfig.test.json',
|
||||
tsconfig: 'tsconfig.json',
|
||||
}],
|
||||
},
|
||||
moduleNameMapper: {
|
||||
|
||||
@@ -5,6 +5,16 @@
|
||||
"type": "module",
|
||||
"main": "bin/index.js",
|
||||
"types": "bin/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./bin/index.d.ts",
|
||||
"import": "./bin/index.js",
|
||||
"development": {
|
||||
"types": "./src/index.ts",
|
||||
"import": "./src/index.ts"
|
||||
}
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"bin/**/*",
|
||||
"README.md",
|
||||
|
||||
@@ -4,12 +4,13 @@ import { ITimer } from './Utils/Timers/ITimer';
|
||||
import { Timer } from './Utils/Timers/Timer';
|
||||
import { Time } from './Utils/Time';
|
||||
import { PerformanceMonitor } from './Utils/PerformanceMonitor';
|
||||
import { PoolManager } from './Utils/Pool';
|
||||
import { PoolManager } from './Utils/Pool/PoolManager';
|
||||
import { ECSFluentAPI, createECSAPI } from './ECS/Core/FluentAPI';
|
||||
import { Scene } from './ECS/Scene';
|
||||
import { DebugManager } from './Utils/Debug';
|
||||
import { ICoreConfig, IECSDebugConfig } from './Types';
|
||||
import { BigIntFactory, EnvironmentInfo } from './ECS/Utils/BigIntCompatibility';
|
||||
import { createLogger } from './Utils/Logger';
|
||||
|
||||
/**
|
||||
* 游戏引擎核心类
|
||||
@@ -33,7 +34,7 @@ import { BigIntFactory, EnvironmentInfo } from './ECS/Utils/BigIntCompatibility'
|
||||
*
|
||||
* // 调度定时器
|
||||
* Core.schedule(1.0, false, null, (timer) => {
|
||||
* console.log("1秒后执行");
|
||||
* Core._logger.info("1秒后执行");
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
@@ -50,6 +51,11 @@ export class Core {
|
||||
*/
|
||||
private static _instance: Core;
|
||||
|
||||
/**
|
||||
* Core专用日志器
|
||||
*/
|
||||
private static _logger = createLogger('Core');
|
||||
|
||||
/**
|
||||
* 实体系统启用状态
|
||||
*
|
||||
@@ -265,7 +271,7 @@ export class Core {
|
||||
*/
|
||||
public static update(deltaTime: number): void {
|
||||
if (!this._instance) {
|
||||
console.warn("Core实例未创建,请先调用Core.create()");
|
||||
Core._logger.warn("Core实例未创建,请先调用Core.create()");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -341,7 +347,7 @@ export class Core {
|
||||
*/
|
||||
public static enableDebug(config: IECSDebugConfig): void {
|
||||
if (!this._instance) {
|
||||
console.warn("Core实例未创建,请先调用Core.create()");
|
||||
Core._logger.warn("Core实例未创建,请先调用Core.create()");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -449,13 +455,13 @@ export class Core {
|
||||
private logCompatibilityInfo(): void {
|
||||
const info = this._environmentInfo;
|
||||
|
||||
console.log('ECS Framework 兼容性检测结果:');
|
||||
console.log(` 环境: ${info.environment}`);
|
||||
console.log(` JavaScript引擎: ${info.jsEngine}`);
|
||||
console.log(` BigInt支持: ${info.supportsBigInt ? '支持' : '不支持'}`);
|
||||
Core._logger.info('ECS Framework 兼容性检测结果:');
|
||||
Core._logger.info(` 环境: ${info.environment}`);
|
||||
Core._logger.info(` JavaScript引擎: ${info.jsEngine}`);
|
||||
Core._logger.info(` BigInt支持: ${info.supportsBigInt ? '支持' : '不支持'}`);
|
||||
|
||||
if (!info.supportsBigInt) {
|
||||
console.warn('BigInt兼容模式已启用');
|
||||
Core._logger.warn('BigInt兼容模式已启用');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Component } from '../Component';
|
||||
import { IBigIntLike, BigIntFactory } from '../Utils/BigIntCompatibility';
|
||||
import { SoAStorage, EnableSoA, HighPrecision, Float64, Int32, SerializeMap, SerializeSet, SerializeArray, DeepCopy } from './SoAStorage';
|
||||
import { createLogger } from '../../Utils/Logger';
|
||||
|
||||
// 重新导出装饰器
|
||||
export { EnableSoA, HighPrecision, Float64, Int32, SerializeMap, SerializeSet, SerializeArray, DeepCopy };
|
||||
@@ -15,6 +16,7 @@ export type ComponentType<T extends Component = Component> = new (...args: unkno
|
||||
* 管理组件类型的位掩码分配
|
||||
*/
|
||||
export class ComponentRegistry {
|
||||
protected static readonly _logger = createLogger('ComponentStorage');
|
||||
private static componentTypes = new Map<Function, number>();
|
||||
private static componentNameToType = new Map<string, Function>();
|
||||
private static componentNameToId = new Map<string, number>();
|
||||
@@ -400,6 +402,7 @@ export class ComponentStorage<T extends Component> {
|
||||
* 管理所有组件类型的存储器
|
||||
*/
|
||||
export class ComponentStorageManager {
|
||||
private static readonly _logger = createLogger('ComponentStorage');
|
||||
private storages = new Map<Function, ComponentStorage<any> | SoAStorage<any>>();
|
||||
|
||||
/**
|
||||
@@ -417,7 +420,7 @@ export class ComponentStorageManager {
|
||||
if (enableSoA) {
|
||||
// 使用SoA优化存储
|
||||
storage = new SoAStorage(componentType);
|
||||
console.log(`[SoA] 为 ${componentType.name} 启用SoA优化(适用于大规模批量操作)`);
|
||||
ComponentStorageManager._logger.info(`为 ${componentType.name} 启用SoA优化(适用于大规模批量操作)`);
|
||||
} else {
|
||||
// 默认使用原始存储
|
||||
storage = new ComponentStorage(componentType);
|
||||
|
||||
196
packages/core/src/ECS/Core/ComponentStorage/ComponentRegistry.ts
Normal file
196
packages/core/src/ECS/Core/ComponentStorage/ComponentRegistry.ts
Normal file
@@ -0,0 +1,196 @@
|
||||
import { Component } from '../../Component';
|
||||
import { IBigIntLike, BigIntFactory } from '../../Utils/BigIntCompatibility';
|
||||
import { createLogger } from '../../../Utils/Logger';
|
||||
|
||||
/**
|
||||
* 组件类型定义
|
||||
*/
|
||||
export type ComponentType<T extends Component = Component> = new (...args: unknown[]) => T;
|
||||
|
||||
/**
|
||||
* 组件注册表
|
||||
* 管理组件类型的位掩码分配
|
||||
*/
|
||||
export class ComponentRegistry {
|
||||
protected static readonly _logger = createLogger('ComponentStorage');
|
||||
private static componentTypes = new Map<Function, number>();
|
||||
private static componentNameToType = new Map<string, Function>();
|
||||
private static componentNameToId = new Map<string, number>();
|
||||
private static maskCache = new Map<string, IBigIntLike>();
|
||||
private static nextBitIndex = 0;
|
||||
private static maxComponents = 64; // 支持最多64种组件类型
|
||||
|
||||
/**
|
||||
* 注册组件类型并分配位掩码
|
||||
* @param componentType 组件类型
|
||||
* @returns 分配的位索引
|
||||
*/
|
||||
public static register<T extends Component>(componentType: ComponentType<T>): 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(componentType.name, componentType);
|
||||
this.componentNameToId.set(componentType.name, bitIndex);
|
||||
return bitIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取组件类型的位掩码
|
||||
* @param componentType 组件类型
|
||||
* @returns 位掩码
|
||||
*/
|
||||
public static getBitMask<T extends Component>(componentType: ComponentType<T>): IBigIntLike {
|
||||
const bitIndex = this.componentTypes.get(componentType);
|
||||
if (bitIndex === undefined) {
|
||||
throw new Error(`Component type ${componentType.name} is not registered`);
|
||||
}
|
||||
return BigIntFactory.one().shiftLeft(bitIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取组件类型的位索引
|
||||
* @param componentType 组件类型
|
||||
* @returns 位索引
|
||||
*/
|
||||
public static getBitIndex<T extends Component>(componentType: ComponentType<T>): number {
|
||||
const bitIndex = this.componentTypes.get(componentType);
|
||||
if (bitIndex === undefined) {
|
||||
throw new Error(`Component type ${componentType.name} is not registered`);
|
||||
}
|
||||
return bitIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查组件类型是否已注册
|
||||
* @param componentType 组件类型
|
||||
* @returns 是否已注册
|
||||
*/
|
||||
public static isRegistered<T extends Component>(componentType: ComponentType<T>): 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<Function, number> {
|
||||
return new Map(this.componentTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有组件名称到类型的映射
|
||||
* @returns 名称到类型的映射
|
||||
*/
|
||||
public static getAllComponentNames(): Map<string, Function> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Entity } from '../Entity';
|
||||
import { Component } from '../Component';
|
||||
import { ComponentType } from './ComponentStorage';
|
||||
import { createLogger } from '../../Utils/Logger';
|
||||
|
||||
/**
|
||||
* 脏标记类型
|
||||
@@ -89,7 +90,7 @@ export interface DirtyStats {
|
||||
* dirtySystem.addListener({
|
||||
* flags: DirtyFlag.TRANSFORM_CHANGED,
|
||||
* callback: (data) => {
|
||||
* console.log('Entity position changed:', data.entity.name);
|
||||
* logger.debug('Entity position changed:', data.entity.name);
|
||||
* }
|
||||
* });
|
||||
*
|
||||
@@ -98,6 +99,7 @@ export interface DirtyStats {
|
||||
* ```
|
||||
*/
|
||||
export class DirtyTrackingSystem {
|
||||
private static readonly _logger = createLogger('DirtyTrackingSystem');
|
||||
/** 脏实体映射表 */
|
||||
private _dirtyEntities = new Map<Entity, DirtyData>();
|
||||
|
||||
@@ -329,7 +331,7 @@ export class DirtyTrackingSystem {
|
||||
try {
|
||||
listener.callback(dirtyData);
|
||||
} catch (error) {
|
||||
console.error('脏数据监听器错误:', error);
|
||||
DirtyTrackingSystem._logger.error('脏数据监听器错误:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -346,7 +348,7 @@ export class DirtyTrackingSystem {
|
||||
try {
|
||||
listener.callback(dirtyData);
|
||||
} catch (error) {
|
||||
console.error('脏数据监听器通知错误:', error);
|
||||
DirtyTrackingSystem._logger.error('脏数据监听器通知错误:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
ISceneEventData,
|
||||
IPerformanceEventData
|
||||
} from '../../Types';
|
||||
import { createLogger } from '../../Utils/Logger';
|
||||
import {
|
||||
TypeSafeEventSystem,
|
||||
EventListenerConfig,
|
||||
@@ -26,6 +27,7 @@ import {
|
||||
* 基于TypeSafeEventSystem,提供类型安全的事件发布订阅机制
|
||||
*/
|
||||
export class EventBus implements IEventBus {
|
||||
private static readonly _logger = createLogger('EventBus');
|
||||
private eventSystem: TypeSafeEventSystem;
|
||||
private eventIdCounter = 0;
|
||||
private isDebugMode = false;
|
||||
@@ -47,7 +49,7 @@ export class EventBus implements IEventBus {
|
||||
const enhancedData = this.enhanceEventData(eventType, data);
|
||||
|
||||
if (this.isDebugMode) {
|
||||
console.log(`[EventBus] 发射事件: ${eventType}`, enhancedData);
|
||||
EventBus._logger.info(`发射事件: ${eventType}`, enhancedData);
|
||||
}
|
||||
|
||||
this.eventSystem.emitSync(eventType, enhancedData);
|
||||
@@ -65,7 +67,7 @@ export class EventBus implements IEventBus {
|
||||
const enhancedData = this.enhanceEventData(eventType, data);
|
||||
|
||||
if (this.isDebugMode) {
|
||||
console.log(`[EventBus] 发射异步事件: ${eventType}`, enhancedData);
|
||||
EventBus._logger.info(`发射异步事件: ${eventType}`, enhancedData);
|
||||
}
|
||||
|
||||
await this.eventSystem.emit(eventType, enhancedData);
|
||||
@@ -93,7 +95,7 @@ export class EventBus implements IEventBus {
|
||||
};
|
||||
|
||||
if (this.isDebugMode) {
|
||||
console.log(`[EventBus] 添加监听器: ${eventType}`, eventConfig);
|
||||
EventBus._logger.info(`添加监听器: ${eventType}`, eventConfig);
|
||||
}
|
||||
|
||||
return this.eventSystem.on(eventType, handler, eventConfig);
|
||||
@@ -136,7 +138,7 @@ export class EventBus implements IEventBus {
|
||||
*/
|
||||
public off(eventType: string, listenerId: string): boolean {
|
||||
if (this.isDebugMode) {
|
||||
console.log(`[EventBus] 移除监听器: ${listenerId} 事件: ${eventType}`);
|
||||
EventBus._logger.info(`移除监听器: ${listenerId} 事件: ${eventType}`);
|
||||
}
|
||||
|
||||
return this.eventSystem.off(eventType, listenerId);
|
||||
@@ -148,7 +150,7 @@ export class EventBus implements IEventBus {
|
||||
*/
|
||||
public offAll(eventType: string): void {
|
||||
if (this.isDebugMode) {
|
||||
console.log(`[EventBus] 移除所有监听器: ${eventType}`);
|
||||
EventBus._logger.info(`移除所有监听器: ${eventType}`);
|
||||
}
|
||||
|
||||
this.eventSystem.offAll(eventType);
|
||||
@@ -186,7 +188,7 @@ export class EventBus implements IEventBus {
|
||||
*/
|
||||
public clear(): void {
|
||||
if (this.isDebugMode) {
|
||||
console.log('[EventBus] 清空所有监听器');
|
||||
EventBus._logger.info('清空所有监听器');
|
||||
}
|
||||
|
||||
this.eventSystem.clear();
|
||||
@@ -379,7 +381,7 @@ export class EventBus implements IEventBus {
|
||||
private validateEventType(eventType: string): void {
|
||||
if (!EventTypeValidator.isValid(eventType)) {
|
||||
if (this.isDebugMode) {
|
||||
console.warn(`[EventBus] 未知事件类型: ${eventType}`);
|
||||
EventBus._logger.warn(`未知事件类型: ${eventType}`);
|
||||
}
|
||||
// 在调试模式下添加自定义事件类型
|
||||
if (this.isDebugMode) {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { createLogger } from '../../Utils/Logger';
|
||||
|
||||
/**
|
||||
* 事件处理器函数类型
|
||||
*/
|
||||
@@ -66,6 +68,7 @@ export interface EventBatchConfig {
|
||||
* 支持同步/异步事件、优先级、批处理等功能
|
||||
*/
|
||||
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[]>();
|
||||
@@ -204,7 +207,7 @@ export class TypeSafeEventSystem {
|
||||
toRemove.push(listener.id);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`事件处理器执行错误 ${eventType}:`, error);
|
||||
TypeSafeEventSystem._logger.error(`事件处理器执行错误 ${eventType}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,7 +339,7 @@ export class TypeSafeEventSystem {
|
||||
|
||||
// 检查监听器数量限制
|
||||
if (listeners.length >= this.maxListeners) {
|
||||
console.warn(`事件类型 ${eventType} 的监听器数量超过最大限制 (${this.maxListeners})`);
|
||||
TypeSafeEventSystem._logger.warn(`事件类型 ${eventType} 的监听器数量超过最大限制 (${this.maxListeners})`);
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -392,7 +395,7 @@ export class TypeSafeEventSystem {
|
||||
toRemove.push(listener.id);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`同步事件处理器执行错误 ${eventType}:`, error);
|
||||
TypeSafeEventSystem._logger.error(`同步事件处理器执行错误 ${eventType}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,7 +412,7 @@ export class TypeSafeEventSystem {
|
||||
toRemove.push(listener.id);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`异步事件处理器执行错误 ${eventType}:`, error);
|
||||
TypeSafeEventSystem._logger.error(`异步事件处理器执行错误 ${eventType}:`, error);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,638 +1,11 @@
|
||||
import { Entity } from '../Entity';
|
||||
import { Component } from '../Component';
|
||||
import { Scene } from '../Scene';
|
||||
import { ComponentType, ComponentStorageManager } from './ComponentStorage';
|
||||
import { QuerySystem, QueryBuilder } from './QuerySystem';
|
||||
import { TypeSafeEventSystem } from './EventSystem';
|
||||
import { EntitySystem } from '../Systems/EntitySystem';
|
||||
|
||||
/**
|
||||
* 实体构建器 - 提供流式API创建和配置实体
|
||||
*/
|
||||
export class EntityBuilder {
|
||||
private entity: Entity;
|
||||
private scene: Scene;
|
||||
private storageManager: ComponentStorageManager;
|
||||
|
||||
constructor(scene: Scene, storageManager: ComponentStorageManager) {
|
||||
this.scene = scene;
|
||||
this.storageManager = storageManager;
|
||||
this.entity = new Entity("", scene.identifierPool.checkOut());
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置实体名称
|
||||
* @param name 实体名称
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public named(name: string): EntityBuilder {
|
||||
this.entity.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置实体标签
|
||||
* @param tag 标签
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public tagged(tag: number): EntityBuilder {
|
||||
this.entity.tag = tag;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加组件
|
||||
* @param component 组件实例
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public with<T extends Component>(component: T): EntityBuilder {
|
||||
this.entity.addComponent(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加多个组件
|
||||
* @param components 组件数组
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public withComponents(...components: Component[]): EntityBuilder {
|
||||
for (const component of components) {
|
||||
this.entity.addComponent(component);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件性添加组件
|
||||
* @param condition 条件
|
||||
* @param component 组件实例
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public withIf<T extends Component>(condition: boolean, component: T): EntityBuilder {
|
||||
if (condition) {
|
||||
this.entity.addComponent(component);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用工厂函数创建并添加组件
|
||||
* @param factory 组件工厂函数
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public withFactory<T extends Component>(factory: () => T): EntityBuilder {
|
||||
const component = factory();
|
||||
this.entity.addComponent(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置组件属性
|
||||
* @param componentType 组件类型
|
||||
* @param configurator 配置函数
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public configure<T extends Component>(
|
||||
componentType: ComponentType<T>,
|
||||
configurator: (component: T) => void
|
||||
): EntityBuilder {
|
||||
const component = this.entity.getComponent(componentType);
|
||||
if (component) {
|
||||
configurator(component);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置实体为启用状态
|
||||
* @param enabled 是否启用
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public enabled(enabled: boolean = true): EntityBuilder {
|
||||
this.entity.enabled = enabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置实体为活跃状态
|
||||
* @param active 是否活跃
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public active(active: boolean = true): EntityBuilder {
|
||||
this.entity.active = active;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加子实体
|
||||
* @param childBuilder 子实体构建器
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public withChild(childBuilder: EntityBuilder): EntityBuilder {
|
||||
const child = childBuilder.build();
|
||||
this.entity.addChild(child);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加子实体
|
||||
* @param childBuilders 子实体构建器数组
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public withChildren(...childBuilders: EntityBuilder[]): EntityBuilder {
|
||||
for (const childBuilder of childBuilders) {
|
||||
const child = childBuilder.build();
|
||||
this.entity.addChild(child);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用工厂函数创建子实体
|
||||
* @param childFactory 子实体工厂函数
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public withChildFactory(childFactory: (parent: Entity) => EntityBuilder): EntityBuilder {
|
||||
const childBuilder = childFactory(this.entity);
|
||||
const child = childBuilder.build();
|
||||
this.entity.addChild(child);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件性添加子实体
|
||||
* @param condition 条件
|
||||
* @param childBuilder 子实体构建器
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public withChildIf(condition: boolean, childBuilder: EntityBuilder): EntityBuilder {
|
||||
if (condition) {
|
||||
const child = childBuilder.build();
|
||||
this.entity.addChild(child);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建并返回实体
|
||||
* @returns 构建的实体
|
||||
*/
|
||||
public build(): Entity {
|
||||
return this.entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建实体并添加到场景
|
||||
* @returns 构建的实体
|
||||
*/
|
||||
public spawn(): Entity {
|
||||
this.scene.addEntity(this.entity);
|
||||
return this.entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 克隆当前构建器
|
||||
* @returns 新的实体构建器
|
||||
*/
|
||||
public clone(): EntityBuilder {
|
||||
const newBuilder = new EntityBuilder(this.scene, this.storageManager);
|
||||
// 这里需要深度克隆实体,简化实现
|
||||
newBuilder.entity = this.entity; // 实际应该是深度克隆
|
||||
return newBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 场景构建器 - 提供流式API创建和配置场景
|
||||
*/
|
||||
export class SceneBuilder {
|
||||
private scene: Scene;
|
||||
|
||||
constructor() {
|
||||
this.scene = new Scene();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置场景名称
|
||||
* @param name 场景名称
|
||||
* @returns 场景构建器
|
||||
*/
|
||||
public named(name: string): SceneBuilder {
|
||||
this.scene.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加实体
|
||||
* @param entity 实体
|
||||
* @returns 场景构建器
|
||||
*/
|
||||
public withEntity(entity: Entity): SceneBuilder {
|
||||
this.scene.addEntity(entity);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用实体构建器添加实体
|
||||
* @param builderFn 实体构建器函数
|
||||
* @returns 场景构建器
|
||||
*/
|
||||
public withEntityBuilder(builderFn: (builder: EntityBuilder) => EntityBuilder): SceneBuilder {
|
||||
const builder = new EntityBuilder(this.scene, this.scene.componentStorageManager);
|
||||
const configuredBuilder = builderFn(builder);
|
||||
const entity = configuredBuilder.build();
|
||||
this.scene.addEntity(entity);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加实体
|
||||
* @param entities 实体数组
|
||||
* @returns 场景构建器
|
||||
*/
|
||||
public withEntities(...entities: Entity[]): SceneBuilder {
|
||||
for (const entity of entities) {
|
||||
this.scene.addEntity(entity);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加系统
|
||||
* @param system 系统实例
|
||||
* @returns 场景构建器
|
||||
*/
|
||||
public withSystem(system: EntitySystem): SceneBuilder {
|
||||
this.scene.addSystem(system);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加系统
|
||||
* @param systems 系统数组
|
||||
* @returns 场景构建器
|
||||
*/
|
||||
public withSystems(...systems: EntitySystem[]): SceneBuilder {
|
||||
for (const system of systems) {
|
||||
this.scene.addSystem(system);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建并返回场景
|
||||
* @returns 构建的场景
|
||||
*/
|
||||
public build(): Scene {
|
||||
return this.scene;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 组件构建器 - 提供流式API创建组件
|
||||
*/
|
||||
export class ComponentBuilder<T extends Component> {
|
||||
private component: T;
|
||||
|
||||
constructor(componentClass: new (...args: unknown[]) => T, ...args: unknown[]) {
|
||||
this.component = new componentClass(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置组件属性
|
||||
* @param property 属性名
|
||||
* @param value 属性值
|
||||
* @returns 组件构建器
|
||||
*/
|
||||
public set<K extends keyof T>(property: K, value: T[K]): ComponentBuilder<T> {
|
||||
this.component[property] = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用配置函数设置组件
|
||||
* @param configurator 配置函数
|
||||
* @returns 组件构建器
|
||||
*/
|
||||
public configure(configurator: (component: T) => void): ComponentBuilder<T> {
|
||||
configurator(this.component);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件性设置属性
|
||||
* @param condition 条件
|
||||
* @param property 属性名
|
||||
* @param value 属性值
|
||||
* @returns 组件构建器
|
||||
*/
|
||||
public setIf<K extends keyof T>(condition: boolean, property: K, value: T[K]): ComponentBuilder<T> {
|
||||
if (condition) {
|
||||
this.component[property] = value;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建并返回组件
|
||||
* @returns 构建的组件
|
||||
*/
|
||||
public build(): T {
|
||||
return this.component;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ECS流式API主入口
|
||||
* 提供统一的流式接口
|
||||
*/
|
||||
export class ECSFluentAPI {
|
||||
private scene: Scene;
|
||||
private querySystem: QuerySystem;
|
||||
private eventSystem: TypeSafeEventSystem;
|
||||
|
||||
constructor(scene: Scene, querySystem: QuerySystem, eventSystem: TypeSafeEventSystem) {
|
||||
this.scene = scene;
|
||||
this.querySystem = querySystem;
|
||||
this.eventSystem = eventSystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建实体构建器
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public createEntity(): EntityBuilder {
|
||||
return new EntityBuilder(this.scene, this.scene.componentStorageManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建场景构建器
|
||||
* @returns 场景构建器
|
||||
*/
|
||||
public createScene(): SceneBuilder {
|
||||
return new SceneBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建组件构建器
|
||||
* @param componentClass 组件类
|
||||
* @param args 构造参数
|
||||
* @returns 组件构建器
|
||||
*/
|
||||
public createComponent<T extends Component>(
|
||||
componentClass: new (...args: unknown[]) => T,
|
||||
...args: unknown[]
|
||||
): ComponentBuilder<T> {
|
||||
return new ComponentBuilder(componentClass, ...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建查询构建器
|
||||
* @returns 查询构建器
|
||||
*/
|
||||
public query(): QueryBuilder {
|
||||
return new QueryBuilder(this.querySystem);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找实体(简化版)
|
||||
* @param componentTypes 组件类型
|
||||
* @returns 实体数组
|
||||
*/
|
||||
public find(...componentTypes: ComponentType[]): Entity[] {
|
||||
return this.querySystem.queryAll(...componentTypes).entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找第一个匹配的实体
|
||||
* @param componentTypes 组件类型
|
||||
* @returns 实体或null
|
||||
*/
|
||||
public findFirst(...componentTypes: ComponentType[]): Entity | null {
|
||||
const result = this.querySystem.queryAll(...componentTypes);
|
||||
return result.entities.length > 0 ? result.entities[0] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按名称查找实体
|
||||
* @param name 实体名称
|
||||
* @returns 实体或null
|
||||
*/
|
||||
public findByName(name: string): Entity | null {
|
||||
return this.scene.getEntityByName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按标签查找实体
|
||||
* @param tag 标签
|
||||
* @returns 实体数组
|
||||
*/
|
||||
public findByTag(tag: number): Entity[] {
|
||||
return this.scene.getEntitiesByTag(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* 触发事件
|
||||
* @param eventType 事件类型
|
||||
* @param event 事件数据
|
||||
*/
|
||||
public emit<T>(eventType: string, event: T): void {
|
||||
this.eventSystem.emitSync(eventType, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步触发事件
|
||||
* @param eventType 事件类型
|
||||
* @param event 事件数据
|
||||
*/
|
||||
public async emitAsync<T>(eventType: string, event: T): Promise<void> {
|
||||
await this.eventSystem.emit(eventType, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听事件
|
||||
* @param eventType 事件类型
|
||||
* @param handler 事件处理器
|
||||
* @returns 监听器ID
|
||||
*/
|
||||
public on<T>(eventType: string, handler: (event: T) => void): string {
|
||||
return this.eventSystem.on(eventType, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* 一次性监听事件
|
||||
* @param eventType 事件类型
|
||||
* @param handler 事件处理器
|
||||
* @returns 监听器ID
|
||||
*/
|
||||
public once<T>(eventType: string, handler: (event: T) => void): string {
|
||||
return this.eventSystem.once(eventType, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除事件监听器
|
||||
* @param eventType 事件类型
|
||||
* @param listenerId 监听器ID
|
||||
*/
|
||||
public off(eventType: string, listenerId: string): void {
|
||||
this.eventSystem.off(eventType, listenerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量操作实体
|
||||
* @param entities 实体数组
|
||||
* @returns 批量操作器
|
||||
*/
|
||||
public batch(entities: Entity[]): EntityBatchOperator {
|
||||
return new EntityBatchOperator(entities);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取场景统计信息
|
||||
* @returns 统计信息
|
||||
*/
|
||||
public getStats(): {
|
||||
entityCount: number;
|
||||
systemCount: number;
|
||||
componentStats: Map<string, any>;
|
||||
queryStats: unknown;
|
||||
eventStats: Map<string, any>;
|
||||
} {
|
||||
return {
|
||||
entityCount: this.scene.entities.count,
|
||||
systemCount: this.scene.systems.length,
|
||||
componentStats: this.scene.componentStorageManager.getAllStats(),
|
||||
queryStats: this.querySystem.getStats(),
|
||||
eventStats: this.eventSystem.getStats() as Map<string, any>
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 实体批量操作器
|
||||
* 提供对多个实体的批量操作
|
||||
*/
|
||||
export class EntityBatchOperator {
|
||||
private entities: Entity[];
|
||||
|
||||
constructor(entities: Entity[]) {
|
||||
this.entities = entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加组件
|
||||
* @param component 组件实例
|
||||
* @returns 批量操作器
|
||||
*/
|
||||
public addComponent<T extends Component>(component: T): EntityBatchOperator {
|
||||
for (const entity of this.entities) {
|
||||
entity.addComponent(component);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量移除组件
|
||||
* @param componentType 组件类型
|
||||
* @returns 批量操作器
|
||||
*/
|
||||
public removeComponent<T extends Component>(componentType: ComponentType<T>): EntityBatchOperator {
|
||||
for (const entity of this.entities) {
|
||||
entity.removeComponentByType(componentType);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量设置活跃状态
|
||||
* @param active 是否活跃
|
||||
* @returns 批量操作器
|
||||
*/
|
||||
public setActive(active: boolean): EntityBatchOperator {
|
||||
for (const entity of this.entities) {
|
||||
entity.active = active;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量设置标签
|
||||
* @param tag 标签
|
||||
* @returns 批量操作器
|
||||
*/
|
||||
public setTag(tag: number): EntityBatchOperator {
|
||||
for (const entity of this.entities) {
|
||||
entity.tag = tag;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量执行操作
|
||||
* @param operation 操作函数
|
||||
* @returns 批量操作器
|
||||
*/
|
||||
public forEach(operation: (entity: Entity, index: number) => void): EntityBatchOperator {
|
||||
this.entities.forEach(operation);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤实体
|
||||
* @param predicate 过滤条件
|
||||
* @returns 新的批量操作器
|
||||
*/
|
||||
public filter(predicate: (entity: Entity) => boolean): EntityBatchOperator {
|
||||
return new EntityBatchOperator(this.entities.filter(predicate));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取实体数组
|
||||
* @returns 实体数组
|
||||
*/
|
||||
public toArray(): Entity[] {
|
||||
return this.entities.slice();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取实体数量
|
||||
* @returns 实体数量
|
||||
*/
|
||||
public count(): number {
|
||||
return this.entities.length;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建ECS流式API实例
|
||||
* @param scene 场景
|
||||
* @param querySystem 查询系统
|
||||
* @param eventSystem 事件系统
|
||||
* @returns ECS流式API实例
|
||||
*/
|
||||
export function createECSAPI(
|
||||
scene: Scene,
|
||||
querySystem: QuerySystem,
|
||||
eventSystem: TypeSafeEventSystem
|
||||
): ECSFluentAPI {
|
||||
return new ECSFluentAPI(scene, querySystem, eventSystem);
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局ECS流式API实例(需要在使用前初始化)
|
||||
*/
|
||||
export let ECS: ECSFluentAPI;
|
||||
|
||||
/**
|
||||
* 初始化全局ECS API
|
||||
* @param scene 场景
|
||||
* @param querySystem 查询系统
|
||||
* @param eventSystem 事件系统
|
||||
*/
|
||||
export function initializeECS(
|
||||
scene: Scene,
|
||||
querySystem: QuerySystem,
|
||||
eventSystem: TypeSafeEventSystem
|
||||
): void {
|
||||
ECS = createECSAPI(scene, querySystem, eventSystem);
|
||||
}
|
||||
// 重新导出拆分后的模块以保持向后兼容性
|
||||
export {
|
||||
EntityBuilder,
|
||||
SceneBuilder,
|
||||
ComponentBuilder,
|
||||
EntityBatchOperator,
|
||||
ECSFluentAPI,
|
||||
createECSAPI,
|
||||
initializeECS,
|
||||
ECS
|
||||
} from './FluentAPI/index';
|
||||
55
packages/core/src/ECS/Core/FluentAPI/ComponentBuilder.ts
Normal file
55
packages/core/src/ECS/Core/FluentAPI/ComponentBuilder.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { Component } from '../../Component';
|
||||
|
||||
/**
|
||||
* 组件构建器 - 提供流式API创建组件
|
||||
*/
|
||||
export class ComponentBuilder<T extends Component> {
|
||||
private component: T;
|
||||
|
||||
constructor(componentClass: new (...args: unknown[]) => T, ...args: unknown[]) {
|
||||
this.component = new componentClass(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置组件属性
|
||||
* @param property 属性名
|
||||
* @param value 属性值
|
||||
* @returns 组件构建器
|
||||
*/
|
||||
public set<K extends keyof T>(property: K, value: T[K]): ComponentBuilder<T> {
|
||||
this.component[property] = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用配置函数设置组件
|
||||
* @param configurator 配置函数
|
||||
* @returns 组件构建器
|
||||
*/
|
||||
public configure(configurator: (component: T) => void): ComponentBuilder<T> {
|
||||
configurator(this.component);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件性设置属性
|
||||
* @param condition 条件
|
||||
* @param property 属性名
|
||||
* @param value 属性值
|
||||
* @returns 组件构建器
|
||||
*/
|
||||
public setIf<K extends keyof T>(condition: boolean, property: K, value: T[K]): ComponentBuilder<T> {
|
||||
if (condition) {
|
||||
this.component[property] = value;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建并返回组件
|
||||
* @returns 构建的组件
|
||||
*/
|
||||
public build(): T {
|
||||
return this.component;
|
||||
}
|
||||
}
|
||||
210
packages/core/src/ECS/Core/FluentAPI/ECSFluentAPI.ts
Normal file
210
packages/core/src/ECS/Core/FluentAPI/ECSFluentAPI.ts
Normal file
@@ -0,0 +1,210 @@
|
||||
import { Entity } from '../../Entity';
|
||||
import { Component } from '../../Component';
|
||||
import { Scene } from '../../Scene';
|
||||
import { ComponentType } from '../ComponentStorage';
|
||||
import { QuerySystem, QueryBuilder } from '../QuerySystem';
|
||||
import { TypeSafeEventSystem } from '../EventSystem';
|
||||
import { EntityBuilder } from './EntityBuilder';
|
||||
import { SceneBuilder } from './SceneBuilder';
|
||||
import { ComponentBuilder } from './ComponentBuilder';
|
||||
import { EntityBatchOperator } from './EntityBatchOperator';
|
||||
|
||||
/**
|
||||
* ECS流式API主入口
|
||||
* 提供统一的流式接口
|
||||
*/
|
||||
export class ECSFluentAPI {
|
||||
private scene: Scene;
|
||||
private querySystem: QuerySystem;
|
||||
private eventSystem: TypeSafeEventSystem;
|
||||
|
||||
constructor(scene: Scene, querySystem: QuerySystem, eventSystem: TypeSafeEventSystem) {
|
||||
this.scene = scene;
|
||||
this.querySystem = querySystem;
|
||||
this.eventSystem = eventSystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建实体构建器
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public createEntity(): EntityBuilder {
|
||||
return new EntityBuilder(this.scene, this.scene.componentStorageManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建场景构建器
|
||||
* @returns 场景构建器
|
||||
*/
|
||||
public createScene(): SceneBuilder {
|
||||
return new SceneBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建组件构建器
|
||||
* @param componentClass 组件类
|
||||
* @param args 构造参数
|
||||
* @returns 组件构建器
|
||||
*/
|
||||
public createComponent<T extends Component>(
|
||||
componentClass: new (...args: unknown[]) => T,
|
||||
...args: unknown[]
|
||||
): ComponentBuilder<T> {
|
||||
return new ComponentBuilder(componentClass, ...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建查询构建器
|
||||
* @returns 查询构建器
|
||||
*/
|
||||
public query(): QueryBuilder {
|
||||
return new QueryBuilder(this.querySystem);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找实体(简化版)
|
||||
* @param componentTypes 组件类型
|
||||
* @returns 实体数组
|
||||
*/
|
||||
public find(...componentTypes: ComponentType[]): Entity[] {
|
||||
return this.querySystem.queryAll(...componentTypes).entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找第一个匹配的实体
|
||||
* @param componentTypes 组件类型
|
||||
* @returns 实体或null
|
||||
*/
|
||||
public findFirst(...componentTypes: ComponentType[]): Entity | null {
|
||||
const result = this.querySystem.queryAll(...componentTypes);
|
||||
return result.entities.length > 0 ? result.entities[0] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按名称查找实体
|
||||
* @param name 实体名称
|
||||
* @returns 实体或null
|
||||
*/
|
||||
public findByName(name: string): Entity | null {
|
||||
return this.scene.getEntityByName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按标签查找实体
|
||||
* @param tag 标签
|
||||
* @returns 实体数组
|
||||
*/
|
||||
public findByTag(tag: number): Entity[] {
|
||||
return this.scene.getEntitiesByTag(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* 触发事件
|
||||
* @param eventType 事件类型
|
||||
* @param event 事件数据
|
||||
*/
|
||||
public emit<T>(eventType: string, event: T): void {
|
||||
this.eventSystem.emitSync(eventType, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步触发事件
|
||||
* @param eventType 事件类型
|
||||
* @param event 事件数据
|
||||
*/
|
||||
public async emitAsync<T>(eventType: string, event: T): Promise<void> {
|
||||
await this.eventSystem.emit(eventType, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听事件
|
||||
* @param eventType 事件类型
|
||||
* @param handler 事件处理器
|
||||
* @returns 监听器ID
|
||||
*/
|
||||
public on<T>(eventType: string, handler: (event: T) => void): string {
|
||||
return this.eventSystem.on(eventType, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* 一次性监听事件
|
||||
* @param eventType 事件类型
|
||||
* @param handler 事件处理器
|
||||
* @returns 监听器ID
|
||||
*/
|
||||
public once<T>(eventType: string, handler: (event: T) => void): string {
|
||||
return this.eventSystem.once(eventType, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除事件监听器
|
||||
* @param eventType 事件类型
|
||||
* @param listenerId 监听器ID
|
||||
*/
|
||||
public off(eventType: string, listenerId: string): void {
|
||||
this.eventSystem.off(eventType, listenerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量操作实体
|
||||
* @param entities 实体数组
|
||||
* @returns 批量操作器
|
||||
*/
|
||||
public batch(entities: Entity[]): EntityBatchOperator {
|
||||
return new EntityBatchOperator(entities);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取场景统计信息
|
||||
* @returns 统计信息
|
||||
*/
|
||||
public getStats(): {
|
||||
entityCount: number;
|
||||
systemCount: number;
|
||||
componentStats: Map<string, any>;
|
||||
queryStats: unknown;
|
||||
eventStats: Map<string, any>;
|
||||
} {
|
||||
return {
|
||||
entityCount: this.scene.entities.count,
|
||||
systemCount: this.scene.systems.length,
|
||||
componentStats: this.scene.componentStorageManager.getAllStats(),
|
||||
queryStats: this.querySystem.getStats(),
|
||||
eventStats: this.eventSystem.getStats() as Map<string, any>
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建ECS流式API实例
|
||||
* @param scene 场景
|
||||
* @param querySystem 查询系统
|
||||
* @param eventSystem 事件系统
|
||||
* @returns ECS流式API实例
|
||||
*/
|
||||
export function createECSAPI(
|
||||
scene: Scene,
|
||||
querySystem: QuerySystem,
|
||||
eventSystem: TypeSafeEventSystem
|
||||
): ECSFluentAPI {
|
||||
return new ECSFluentAPI(scene, querySystem, eventSystem);
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局ECS流式API实例(需要在使用前初始化)
|
||||
*/
|
||||
export let ECS: ECSFluentAPI;
|
||||
|
||||
/**
|
||||
* 初始化全局ECS API
|
||||
* @param scene 场景
|
||||
* @param querySystem 查询系统
|
||||
* @param eventSystem 事件系统
|
||||
*/
|
||||
export function initializeECS(
|
||||
scene: Scene,
|
||||
querySystem: QuerySystem,
|
||||
eventSystem: TypeSafeEventSystem
|
||||
): void {
|
||||
ECS = createECSAPI(scene, querySystem, eventSystem);
|
||||
}
|
||||
98
packages/core/src/ECS/Core/FluentAPI/EntityBatchOperator.ts
Normal file
98
packages/core/src/ECS/Core/FluentAPI/EntityBatchOperator.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import { Entity } from '../../Entity';
|
||||
import { Component } from '../../Component';
|
||||
import { ComponentType } from '../ComponentStorage';
|
||||
|
||||
/**
|
||||
* 实体批量操作器
|
||||
* 提供对多个实体的批量操作
|
||||
*/
|
||||
export class EntityBatchOperator {
|
||||
private entities: Entity[];
|
||||
|
||||
constructor(entities: Entity[]) {
|
||||
this.entities = entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加组件
|
||||
* @param component 组件实例
|
||||
* @returns 批量操作器
|
||||
*/
|
||||
public addComponent<T extends Component>(component: T): EntityBatchOperator {
|
||||
for (const entity of this.entities) {
|
||||
entity.addComponent(component);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量移除组件
|
||||
* @param componentType 组件类型
|
||||
* @returns 批量操作器
|
||||
*/
|
||||
public removeComponent<T extends Component>(componentType: ComponentType<T>): EntityBatchOperator {
|
||||
for (const entity of this.entities) {
|
||||
entity.removeComponentByType(componentType);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量设置活跃状态
|
||||
* @param active 是否活跃
|
||||
* @returns 批量操作器
|
||||
*/
|
||||
public setActive(active: boolean): EntityBatchOperator {
|
||||
for (const entity of this.entities) {
|
||||
entity.active = active;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量设置标签
|
||||
* @param tag 标签
|
||||
* @returns 批量操作器
|
||||
*/
|
||||
public setTag(tag: number): EntityBatchOperator {
|
||||
for (const entity of this.entities) {
|
||||
entity.tag = tag;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量执行操作
|
||||
* @param operation 操作函数
|
||||
* @returns 批量操作器
|
||||
*/
|
||||
public forEach(operation: (entity: Entity, index: number) => void): EntityBatchOperator {
|
||||
this.entities.forEach(operation);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤实体
|
||||
* @param predicate 过滤条件
|
||||
* @returns 新的批量操作器
|
||||
*/
|
||||
public filter(predicate: (entity: Entity) => boolean): EntityBatchOperator {
|
||||
return new EntityBatchOperator(this.entities.filter(predicate));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取实体数组
|
||||
* @returns 实体数组
|
||||
*/
|
||||
public toArray(): Entity[] {
|
||||
return this.entities.slice();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取实体数量
|
||||
* @returns 实体数量
|
||||
*/
|
||||
public count(): number {
|
||||
return this.entities.length;
|
||||
}
|
||||
}
|
||||
200
packages/core/src/ECS/Core/FluentAPI/EntityBuilder.ts
Normal file
200
packages/core/src/ECS/Core/FluentAPI/EntityBuilder.ts
Normal file
@@ -0,0 +1,200 @@
|
||||
import { Entity } from '../../Entity';
|
||||
import { Component } from '../../Component';
|
||||
import { Scene } from '../../Scene';
|
||||
import { ComponentType, ComponentStorageManager } from '../ComponentStorage';
|
||||
|
||||
/**
|
||||
* 实体构建器 - 提供流式API创建和配置实体
|
||||
*/
|
||||
export class EntityBuilder {
|
||||
private entity: Entity;
|
||||
private scene: Scene;
|
||||
private storageManager: ComponentStorageManager;
|
||||
|
||||
constructor(scene: Scene, storageManager: ComponentStorageManager) {
|
||||
this.scene = scene;
|
||||
this.storageManager = storageManager;
|
||||
this.entity = new Entity("", scene.identifierPool.checkOut());
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置实体名称
|
||||
* @param name 实体名称
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public named(name: string): EntityBuilder {
|
||||
this.entity.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置实体标签
|
||||
* @param tag 标签
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public tagged(tag: number): EntityBuilder {
|
||||
this.entity.tag = tag;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加组件
|
||||
* @param component 组件实例
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public with<T extends Component>(component: T): EntityBuilder {
|
||||
this.entity.addComponent(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加多个组件
|
||||
* @param components 组件数组
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public withComponents(...components: Component[]): EntityBuilder {
|
||||
for (const component of components) {
|
||||
this.entity.addComponent(component);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件性添加组件
|
||||
* @param condition 条件
|
||||
* @param component 组件实例
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public withIf<T extends Component>(condition: boolean, component: T): EntityBuilder {
|
||||
if (condition) {
|
||||
this.entity.addComponent(component);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用工厂函数创建并添加组件
|
||||
* @param factory 组件工厂函数
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public withFactory<T extends Component>(factory: () => T): EntityBuilder {
|
||||
const component = factory();
|
||||
this.entity.addComponent(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置组件属性
|
||||
* @param componentType 组件类型
|
||||
* @param configurator 配置函数
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public configure<T extends Component>(
|
||||
componentType: ComponentType<T>,
|
||||
configurator: (component: T) => void
|
||||
): EntityBuilder {
|
||||
const component = this.entity.getComponent(componentType);
|
||||
if (component) {
|
||||
configurator(component);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置实体为启用状态
|
||||
* @param enabled 是否启用
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public enabled(enabled: boolean = true): EntityBuilder {
|
||||
this.entity.enabled = enabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置实体为活跃状态
|
||||
* @param active 是否活跃
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public active(active: boolean = true): EntityBuilder {
|
||||
this.entity.active = active;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加子实体
|
||||
* @param childBuilder 子实体构建器
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public withChild(childBuilder: EntityBuilder): EntityBuilder {
|
||||
const child = childBuilder.build();
|
||||
this.entity.addChild(child);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加子实体
|
||||
* @param childBuilders 子实体构建器数组
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public withChildren(...childBuilders: EntityBuilder[]): EntityBuilder {
|
||||
for (const childBuilder of childBuilders) {
|
||||
const child = childBuilder.build();
|
||||
this.entity.addChild(child);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用工厂函数创建子实体
|
||||
* @param childFactory 子实体工厂函数
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public withChildFactory(childFactory: (parent: Entity) => EntityBuilder): EntityBuilder {
|
||||
const childBuilder = childFactory(this.entity);
|
||||
const child = childBuilder.build();
|
||||
this.entity.addChild(child);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件性添加子实体
|
||||
* @param condition 条件
|
||||
* @param childBuilder 子实体构建器
|
||||
* @returns 实体构建器
|
||||
*/
|
||||
public withChildIf(condition: boolean, childBuilder: EntityBuilder): EntityBuilder {
|
||||
if (condition) {
|
||||
const child = childBuilder.build();
|
||||
this.entity.addChild(child);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建并返回实体
|
||||
* @returns 构建的实体
|
||||
*/
|
||||
public build(): Entity {
|
||||
return this.entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建实体并添加到场景
|
||||
* @returns 构建的实体
|
||||
*/
|
||||
public spawn(): Entity {
|
||||
this.scene.addEntity(this.entity);
|
||||
return this.entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 克隆当前构建器
|
||||
* @returns 新的实体构建器
|
||||
*/
|
||||
public clone(): EntityBuilder {
|
||||
const newBuilder = new EntityBuilder(this.scene, this.storageManager);
|
||||
// 这里需要深度克隆实体,简化实现
|
||||
newBuilder.entity = this.entity; // 实际应该是深度克隆
|
||||
return newBuilder;
|
||||
}
|
||||
}
|
||||
90
packages/core/src/ECS/Core/FluentAPI/SceneBuilder.ts
Normal file
90
packages/core/src/ECS/Core/FluentAPI/SceneBuilder.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import { Entity } from '../../Entity';
|
||||
import { Scene } from '../../Scene';
|
||||
import { EntitySystem } from '../../Systems/EntitySystem';
|
||||
import { EntityBuilder } from './EntityBuilder';
|
||||
|
||||
/**
|
||||
* 场景构建器 - 提供流式API创建和配置场景
|
||||
*/
|
||||
export class SceneBuilder {
|
||||
private scene: Scene;
|
||||
|
||||
constructor() {
|
||||
this.scene = new Scene();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置场景名称
|
||||
* @param name 场景名称
|
||||
* @returns 场景构建器
|
||||
*/
|
||||
public named(name: string): SceneBuilder {
|
||||
this.scene.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加实体
|
||||
* @param entity 实体
|
||||
* @returns 场景构建器
|
||||
*/
|
||||
public withEntity(entity: Entity): SceneBuilder {
|
||||
this.scene.addEntity(entity);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用实体构建器添加实体
|
||||
* @param builderFn 实体构建器函数
|
||||
* @returns 场景构建器
|
||||
*/
|
||||
public withEntityBuilder(builderFn: (builder: EntityBuilder) => EntityBuilder): SceneBuilder {
|
||||
const builder = new EntityBuilder(this.scene, this.scene.componentStorageManager);
|
||||
const configuredBuilder = builderFn(builder);
|
||||
const entity = configuredBuilder.build();
|
||||
this.scene.addEntity(entity);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加实体
|
||||
* @param entities 实体数组
|
||||
* @returns 场景构建器
|
||||
*/
|
||||
public withEntities(...entities: Entity[]): SceneBuilder {
|
||||
for (const entity of entities) {
|
||||
this.scene.addEntity(entity);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加系统
|
||||
* @param system 系统实例
|
||||
* @returns 场景构建器
|
||||
*/
|
||||
public withSystem(system: EntitySystem): SceneBuilder {
|
||||
this.scene.addSystem(system);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加系统
|
||||
* @param systems 系统数组
|
||||
* @returns 场景构建器
|
||||
*/
|
||||
public withSystems(...systems: EntitySystem[]): SceneBuilder {
|
||||
for (const system of systems) {
|
||||
this.scene.addSystem(system);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建并返回场景
|
||||
* @returns 构建的场景
|
||||
*/
|
||||
public build(): Scene {
|
||||
return this.scene;
|
||||
}
|
||||
}
|
||||
5
packages/core/src/ECS/Core/FluentAPI/index.ts
Normal file
5
packages/core/src/ECS/Core/FluentAPI/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export { EntityBuilder } from './EntityBuilder';
|
||||
export { SceneBuilder } from './SceneBuilder';
|
||||
export { ComponentBuilder } from './ComponentBuilder';
|
||||
export { EntityBatchOperator } from './EntityBatchOperator';
|
||||
export { ECSFluentAPI, createECSAPI, initializeECS, ECS } from './ECSFluentAPI';
|
||||
@@ -2,6 +2,7 @@ import { Entity } from '../Entity';
|
||||
import { Component } from '../Component';
|
||||
import { ComponentRegistry, ComponentType } from './ComponentStorage';
|
||||
import { IBigIntLike, BigIntFactory } from '../Utils/BigIntCompatibility';
|
||||
import { createLogger } from '../../Utils/Logger';
|
||||
|
||||
import { ComponentPoolManager } from './ComponentPool';
|
||||
import { ComponentIndexManager, IndexType } from './ComponentIndex';
|
||||
@@ -82,6 +83,7 @@ interface QueryCacheEntry {
|
||||
* ```
|
||||
*/
|
||||
export class QuerySystem {
|
||||
private _logger = createLogger('QuerySystem');
|
||||
private entities: Entity[] = [];
|
||||
private entityIndex: EntityIndex;
|
||||
private indexDirty = true;
|
||||
@@ -390,7 +392,7 @@ export class QuerySystem {
|
||||
* ```typescript
|
||||
* // 查询同时具有位置和速度组件的实体
|
||||
* const result = querySystem.queryAll(PositionComponent, VelocityComponent);
|
||||
* console.log(`找到 ${result.count} 个移动实体`);
|
||||
* logger.info(`找到 ${result.count} 个移动实体`);
|
||||
* ```
|
||||
*/
|
||||
public queryAll(...componentTypes: ComponentType[]): QueryResult {
|
||||
@@ -502,7 +504,7 @@ export class QuerySystem {
|
||||
* ```typescript
|
||||
* // 查询具有武器或护甲组件的实体
|
||||
* const result = querySystem.queryAny(WeaponComponent, ArmorComponent);
|
||||
* console.log(`找到 ${result.count} 个装备实体`);
|
||||
* logger.info(`找到 ${result.count} 个装备实体`);
|
||||
* ```
|
||||
*/
|
||||
public queryAny(...componentTypes: ComponentType[]): QueryResult {
|
||||
@@ -560,7 +562,7 @@ export class QuerySystem {
|
||||
* ```typescript
|
||||
* // 查询不具有AI和玩家控制组件的实体(如静态物体)
|
||||
* const result = querySystem.queryNone(AIComponent, PlayerControlComponent);
|
||||
* console.log(`找到 ${result.count} 个静态实体`);
|
||||
* logger.info(`找到 ${result.count} 个静态实体`);
|
||||
* ```
|
||||
*/
|
||||
public queryNone(...componentTypes: ComponentType[]): QueryResult {
|
||||
@@ -878,7 +880,7 @@ export class QuerySystem {
|
||||
mask = mask.or(bitMask);
|
||||
hasValidComponents = true;
|
||||
} catch (error) {
|
||||
console.warn(`组件类型 ${type.name} 未注册,跳过`);
|
||||
this._logger.warn(`组件类型 ${type.name} 未注册,跳过`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1054,6 +1056,7 @@ export class QuerySystem {
|
||||
* ```
|
||||
*/
|
||||
export class QueryBuilder {
|
||||
private _logger = createLogger('QueryBuilder');
|
||||
private conditions: QueryCondition[] = [];
|
||||
private querySystem: QuerySystem;
|
||||
|
||||
@@ -1148,7 +1151,7 @@ export class QueryBuilder {
|
||||
const bitMask = ComponentRegistry.getBitMask(type);
|
||||
mask = mask.or(bitMask);
|
||||
} catch (error) {
|
||||
console.warn(`组件类型 ${type.name} 未注册,跳过`);
|
||||
this._logger.warn(`组件类型 ${type.name} 未注册,跳过`);
|
||||
}
|
||||
}
|
||||
return mask;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Component } from '../Component';
|
||||
import { ComponentType } from './ComponentStorage';
|
||||
import { createLogger } from '../../Utils/Logger';
|
||||
|
||||
/**
|
||||
* 启用SoA优化装饰器
|
||||
@@ -113,6 +114,7 @@ export function DeepCopy(target: any, propertyKey: string | symbol): void {
|
||||
* 使用Structure of Arrays存储模式,在大规模批量操作时提供优异性能
|
||||
*/
|
||||
export class SoAStorage<T extends Component> {
|
||||
private static readonly _logger = createLogger('SoAStorage');
|
||||
private fields = new Map<string, Float32Array | Float64Array | Int32Array>();
|
||||
private stringFields = new Map<string, string[]>(); // 专门存储字符串
|
||||
private serializedFields = new Map<string, string[]>(); // 序列化存储Map/Set/Array
|
||||
@@ -276,7 +278,7 @@ export class SoAStorage<T extends Component> {
|
||||
return JSON.stringify(value);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`SoA序列化字段 ${key} 失败:`, error);
|
||||
SoAStorage._logger.warn(`SoA序列化字段 ${key} 失败:`, error);
|
||||
return '{}';
|
||||
}
|
||||
}
|
||||
@@ -301,7 +303,7 @@ export class SoAStorage<T extends Component> {
|
||||
return parsed;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`SoA反序列化字段 ${key} 失败:`, error);
|
||||
SoAStorage._logger.warn(`SoA反序列化字段 ${key} 失败:`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Component } from './Component';
|
||||
import { ComponentRegistry, ComponentType } from './Core/ComponentStorage';
|
||||
import { EventBus } from './Core/EventBus';
|
||||
import { IBigIntLike, BigIntFactory } from './Utils/BigIntCompatibility';
|
||||
import { createLogger } from '../Utils/Logger';
|
||||
|
||||
// Forward declaration to avoid circular dependency
|
||||
interface IScene {
|
||||
@@ -65,6 +66,11 @@ export class EntityComparer {
|
||||
* ```
|
||||
*/
|
||||
export class Entity {
|
||||
/**
|
||||
* Entity专用日志器
|
||||
*/
|
||||
private static _logger = createLogger('Entity');
|
||||
|
||||
/**
|
||||
* 实体比较器实例
|
||||
*/
|
||||
@@ -630,7 +636,7 @@ export class Entity {
|
||||
addedComponents.push(this.addComponent(component));
|
||||
} catch (error) {
|
||||
// 如果某个组件添加失败,继续添加其他组件
|
||||
console.warn(`添加组件失败 ${component.constructor.name}:`, error);
|
||||
Entity._logger.warn(`添加组件失败 ${component.constructor.name}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { EntitySystem } from '../Systems/EntitySystem';
|
||||
import { createLogger } from '../../Utils/Logger';
|
||||
|
||||
/**
|
||||
* 实体处理器列表管理器
|
||||
* 管理场景中的所有实体系统
|
||||
*/
|
||||
export class EntityProcessorList {
|
||||
private static readonly _logger = createLogger('EntityProcessorList');
|
||||
private _processors: EntitySystem[] = [];
|
||||
private _isDirty = false;
|
||||
|
||||
@@ -73,7 +75,7 @@ export class EntityProcessorList {
|
||||
try {
|
||||
processor.update();
|
||||
} catch (error) {
|
||||
console.error(`Error in processor ${processor.constructor.name}:`, error);
|
||||
EntityProcessorList._logger.error(`Error in processor ${processor.constructor.name}:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,53 +41,100 @@ export interface LoggerConfig {
|
||||
* 默认控制台日志实现
|
||||
*/
|
||||
export class ConsoleLogger implements ILogger {
|
||||
private config: LoggerConfig;
|
||||
private _config: LoggerConfig;
|
||||
|
||||
constructor(config: Partial<LoggerConfig> = {}) {
|
||||
this.config = {
|
||||
this._config = {
|
||||
level: LogLevel.Info,
|
||||
enableTimestamp: true,
|
||||
enableColors: typeof window === 'undefined', // Node.js环境默认启用颜色
|
||||
enableColors: typeof window === 'undefined',
|
||||
...config
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出调试级别日志
|
||||
* @param message 日志消息
|
||||
* @param args 附加参数
|
||||
*/
|
||||
public debug(message: string, ...args: unknown[]): void {
|
||||
this.log(LogLevel.Debug, message, ...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出信息级别日志
|
||||
* @param message 日志消息
|
||||
* @param args 附加参数
|
||||
*/
|
||||
public info(message: string, ...args: unknown[]): void {
|
||||
this.log(LogLevel.Info, message, ...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出警告级别日志
|
||||
* @param message 日志消息
|
||||
* @param args 附加参数
|
||||
*/
|
||||
public warn(message: string, ...args: unknown[]): void {
|
||||
this.log(LogLevel.Warn, message, ...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出错误级别日志
|
||||
* @param message 日志消息
|
||||
* @param args 附加参数
|
||||
*/
|
||||
public error(message: string, ...args: unknown[]): void {
|
||||
this.log(LogLevel.Error, message, ...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出致命错误级别日志
|
||||
* @param message 日志消息
|
||||
* @param args 附加参数
|
||||
*/
|
||||
public fatal(message: string, ...args: unknown[]): void {
|
||||
this.log(LogLevel.Fatal, message, ...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置日志级别
|
||||
* @param level 日志级别
|
||||
*/
|
||||
public setLevel(level: LogLevel): void {
|
||||
this._config.level = level;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置日志前缀
|
||||
* @param prefix 前缀字符串
|
||||
*/
|
||||
public setPrefix(prefix: string): void {
|
||||
this._config.prefix = prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部日志输出方法
|
||||
* @param level 日志级别
|
||||
* @param message 日志消息
|
||||
* @param args 附加参数
|
||||
*/
|
||||
private log(level: LogLevel, message: string, ...args: unknown[]): void {
|
||||
if (level < this.config.level) {
|
||||
if (level < this._config.level) {
|
||||
return;
|
||||
}
|
||||
|
||||
let formattedMessage = message;
|
||||
|
||||
// 添加时间戳
|
||||
if (this.config.enableTimestamp) {
|
||||
if (this._config.enableTimestamp) {
|
||||
const timestamp = new Date().toISOString();
|
||||
formattedMessage = `[${timestamp}] ${formattedMessage}`;
|
||||
}
|
||||
|
||||
// 添加前缀
|
||||
if (this.config.prefix) {
|
||||
formattedMessage = `[${this.config.prefix}] ${formattedMessage}`;
|
||||
if (this._config.prefix) {
|
||||
formattedMessage = `[${this._config.prefix}] ${formattedMessage}`;
|
||||
}
|
||||
|
||||
// 添加日志级别
|
||||
@@ -95,15 +142,21 @@ export class ConsoleLogger implements ILogger {
|
||||
formattedMessage = `[${levelName}] ${formattedMessage}`;
|
||||
|
||||
// 使用自定义输出或默认控制台输出
|
||||
if (this.config.output) {
|
||||
this.config.output(level, formattedMessage);
|
||||
if (this._config.output) {
|
||||
this._config.output(level, formattedMessage);
|
||||
} else {
|
||||
this.outputToConsole(level, formattedMessage, ...args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出到控制台
|
||||
* @param level 日志级别
|
||||
* @param message 格式化后的消息
|
||||
* @param args 附加参数
|
||||
*/
|
||||
private outputToConsole(level: LogLevel, message: string, ...args: unknown[]): void {
|
||||
const colors = this.config.enableColors ? this.getColors() : null;
|
||||
const colors = this._config.enableColors ? this.getColors() : null;
|
||||
|
||||
switch (level) {
|
||||
case LogLevel.Debug:
|
||||
@@ -138,6 +191,10 @@ export class ConsoleLogger implements ILogger {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取控制台颜色配置
|
||||
* @returns 颜色配置对象
|
||||
*/
|
||||
private getColors() {
|
||||
return {
|
||||
reset: '\x1b[0m',
|
||||
@@ -147,14 +204,6 @@ export class ConsoleLogger implements ILogger {
|
||||
gray: '\x1b[90m'
|
||||
};
|
||||
}
|
||||
|
||||
public setLevel(level: LogLevel): void {
|
||||
this.config.level = level;
|
||||
}
|
||||
|
||||
public setPrefix(prefix: string): void {
|
||||
this.config.prefix = prefix;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,6 +218,10 @@ export class LoggerManager {
|
||||
this._defaultLogger = new ConsoleLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取日志管理器实例
|
||||
* @returns 日志管理器实例
|
||||
*/
|
||||
public static getInstance(): LoggerManager {
|
||||
if (!LoggerManager._instance) {
|
||||
LoggerManager._instance = new LoggerManager();
|
||||
@@ -178,6 +231,8 @@ export class LoggerManager {
|
||||
|
||||
/**
|
||||
* 获取或创建日志器
|
||||
* @param name 日志器名称
|
||||
* @returns 日志器实例
|
||||
*/
|
||||
public getLogger(name?: string): ILogger {
|
||||
if (!name) {
|
||||
@@ -197,6 +252,8 @@ export class LoggerManager {
|
||||
|
||||
/**
|
||||
* 设置日志器
|
||||
* @param name 日志器名称
|
||||
* @param logger 日志器实例
|
||||
*/
|
||||
public setLogger(name: string, logger: ILogger): void {
|
||||
this._loggers.set(name, logger);
|
||||
@@ -204,6 +261,7 @@ export class LoggerManager {
|
||||
|
||||
/**
|
||||
* 设置全局日志级别
|
||||
* @param level 日志级别
|
||||
*/
|
||||
public setGlobalLevel(level: LogLevel): void {
|
||||
if (this._defaultLogger instanceof ConsoleLogger) {
|
||||
@@ -219,6 +277,9 @@ export class LoggerManager {
|
||||
|
||||
/**
|
||||
* 创建子日志器
|
||||
* @param parentName 父日志器名称
|
||||
* @param childName 子日志器名称
|
||||
* @returns 子日志器实例
|
||||
*/
|
||||
public createChildLogger(parentName: string, childName: string): ILogger {
|
||||
const fullName = `${parentName}.${childName}`;
|
||||
@@ -233,6 +294,8 @@ export const Logger = LoggerManager.getInstance().getLogger();
|
||||
|
||||
/**
|
||||
* 创建命名日志器
|
||||
* @param name 日志器名称
|
||||
* @returns 日志器实例
|
||||
*/
|
||||
export function createLogger(name: string): ILogger {
|
||||
return LoggerManager.getInstance().getLogger(name);
|
||||
@@ -240,6 +303,7 @@ export function createLogger(name: string): ILogger {
|
||||
|
||||
/**
|
||||
* 设置全局日志级别
|
||||
* @param level 日志级别
|
||||
*/
|
||||
export function setGlobalLogLevel(level: LogLevel): void {
|
||||
LoggerManager.getInstance().setGlobalLevel(level);
|
||||
@@ -1,565 +0,0 @@
|
||||
/**
|
||||
* 可池化对象接口
|
||||
*/
|
||||
export interface IPoolable {
|
||||
/**
|
||||
* 重置对象状态,准备重用
|
||||
*/
|
||||
reset(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对象池统计信息
|
||||
*/
|
||||
export interface PoolStats {
|
||||
/** 池中对象数量 */
|
||||
size: number;
|
||||
/** 池的最大大小 */
|
||||
maxSize: number;
|
||||
/** 总共创建的对象数量 */
|
||||
totalCreated: number;
|
||||
/** 总共获取的次数 */
|
||||
totalObtained: number;
|
||||
/** 总共释放的次数 */
|
||||
totalReleased: number;
|
||||
/** 命中率(从池中获取的比例) */
|
||||
hitRate: number;
|
||||
/** 内存使用估算(字节) */
|
||||
estimatedMemoryUsage: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 高性能通用对象池
|
||||
* 支持任意类型的对象池化,包含详细的统计信息
|
||||
*/
|
||||
export class Pool<T extends IPoolable> {
|
||||
private static _pools = new Map<Function, Pool<any>>();
|
||||
|
||||
private _objects: T[] = [];
|
||||
private _createFn: () => T;
|
||||
private _maxSize: number;
|
||||
private _stats: PoolStats;
|
||||
private _objectSize: number; // 估算的单个对象大小
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param createFn 创建对象的函数
|
||||
* @param maxSize 池的最大大小,默认100
|
||||
* @param estimatedObjectSize 估算的单个对象大小(字节),默认1024
|
||||
*/
|
||||
constructor(createFn: () => T, maxSize: number = 100, estimatedObjectSize: number = 1024) {
|
||||
this._createFn = createFn;
|
||||
this._maxSize = maxSize;
|
||||
this._objectSize = estimatedObjectSize;
|
||||
this._stats = {
|
||||
size: 0,
|
||||
maxSize,
|
||||
totalCreated: 0,
|
||||
totalObtained: 0,
|
||||
totalReleased: 0,
|
||||
hitRate: 0,
|
||||
estimatedMemoryUsage: 0
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定类型的对象池
|
||||
* @param type 对象类型
|
||||
* @param maxSize 池的最大大小
|
||||
* @param estimatedObjectSize 估算的单个对象大小
|
||||
* @returns 对象池实例
|
||||
*/
|
||||
public static getPool<T extends IPoolable>(
|
||||
type: new (...args: unknown[]) => T,
|
||||
maxSize: number = 100,
|
||||
estimatedObjectSize: number = 1024
|
||||
): Pool<T> {
|
||||
let pool = this._pools.get(type);
|
||||
|
||||
if (!pool) {
|
||||
pool = new Pool<T>(() => new type(), maxSize, estimatedObjectSize);
|
||||
this._pools.set(type, pool);
|
||||
}
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从池中获取对象
|
||||
* @returns 对象实例
|
||||
*/
|
||||
public obtain(): T {
|
||||
this._stats.totalObtained++;
|
||||
|
||||
if (this._objects.length > 0) {
|
||||
const obj = this._objects.pop()!;
|
||||
this._stats.size--;
|
||||
this._updateHitRate();
|
||||
this._updateMemoryUsage();
|
||||
return obj;
|
||||
}
|
||||
|
||||
// 池中没有对象,创建新的
|
||||
const obj = this._createFn();
|
||||
this._stats.totalCreated++;
|
||||
this._updateHitRate();
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象归还到池中
|
||||
* @param obj 要归还的对象
|
||||
*/
|
||||
public free(obj: T): void {
|
||||
if (this._objects.length < this._maxSize) {
|
||||
obj.reset();
|
||||
this._objects.push(obj);
|
||||
this._stats.size++;
|
||||
this._stats.totalReleased++;
|
||||
this._updateMemoryUsage();
|
||||
}
|
||||
// 如果池已满,对象会被丢弃(由GC回收)
|
||||
}
|
||||
|
||||
/**
|
||||
* 预热池,创建指定数量的对象
|
||||
* @param count 要创建的对象数量
|
||||
*/
|
||||
public warmUp(count: number): void {
|
||||
const targetSize = Math.min(count, this._maxSize);
|
||||
|
||||
while (this._objects.length < targetSize) {
|
||||
const obj = this._createFn();
|
||||
this._stats.totalCreated++;
|
||||
this._objects.push(obj);
|
||||
this._stats.size++;
|
||||
}
|
||||
|
||||
this._updateMemoryUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空池
|
||||
*/
|
||||
public clear(): void {
|
||||
this._objects.length = 0;
|
||||
this._stats.size = 0;
|
||||
this._updateMemoryUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取池中对象数量
|
||||
*/
|
||||
public get size(): number {
|
||||
return this._objects.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取池的最大大小
|
||||
*/
|
||||
public get maxSize(): number {
|
||||
return this._maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置池的最大大小
|
||||
*/
|
||||
public set maxSize(value: number) {
|
||||
this._maxSize = value;
|
||||
this._stats.maxSize = value;
|
||||
|
||||
// 如果当前池大小超过新的最大值,则移除多余的对象
|
||||
while (this._objects.length > this._maxSize) {
|
||||
this._objects.pop();
|
||||
this._stats.size--;
|
||||
}
|
||||
|
||||
this._updateMemoryUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取池的统计信息
|
||||
*/
|
||||
public getStats(): PoolStats {
|
||||
return { ...this._stats };
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置统计信息
|
||||
*/
|
||||
public resetStats(): void {
|
||||
this._stats.totalCreated = 0;
|
||||
this._stats.totalObtained = 0;
|
||||
this._stats.totalReleased = 0;
|
||||
this._stats.hitRate = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新命中率
|
||||
*/
|
||||
private _updateHitRate(): void {
|
||||
if (this._stats.totalObtained > 0) {
|
||||
const hits = this._stats.totalObtained - this._stats.totalCreated;
|
||||
this._stats.hitRate = hits / this._stats.totalObtained;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新内存使用估算
|
||||
*/
|
||||
private _updateMemoryUsage(): void {
|
||||
this._stats.estimatedMemoryUsage = this._stats.size * this._objectSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态方法:从指定类型的池中获取对象
|
||||
* @param type 对象类型
|
||||
* @returns 对象实例
|
||||
*/
|
||||
public static obtain<T extends IPoolable>(type: new (...args: unknown[]) => T): T {
|
||||
return this.getPool(type).obtain();
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态方法:将对象归还到对应类型的池中
|
||||
* @param type 对象类型
|
||||
* @param obj 要归还的对象
|
||||
*/
|
||||
public static free<T extends IPoolable>(type: new (...args: unknown[]) => T, obj: T): void {
|
||||
this.getPool(type).free(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态方法:预热指定类型的池
|
||||
* @param type 对象类型
|
||||
* @param count 要创建的对象数量
|
||||
*/
|
||||
public static warmUp<T extends IPoolable>(type: new (...args: unknown[]) => T, count: number): void {
|
||||
this.getPool(type).warmUp(count);
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态方法:清空指定类型的池
|
||||
* @param type 对象类型
|
||||
*/
|
||||
public static clearPool<T extends IPoolable>(type: new (...args: unknown[]) => T): void {
|
||||
const pool = this._pools.get(type);
|
||||
if (pool) {
|
||||
pool.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态方法:清空所有池
|
||||
*/
|
||||
public static clearAllPools(): void {
|
||||
for (const pool of this._pools.values()) {
|
||||
pool.clear();
|
||||
}
|
||||
this._pools.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态方法:获取池的统计信息
|
||||
* @returns 池的统计信息
|
||||
*/
|
||||
public static getStats(): { [typeName: string]: PoolStats } {
|
||||
const stats: { [typeName: string]: PoolStats } = {};
|
||||
|
||||
for (const [type, pool] of this._pools.entries()) {
|
||||
const typeName = (type as any).name || 'Unknown';
|
||||
stats[typeName] = pool.getStats();
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态方法:获取所有池的总内存使用量
|
||||
* @returns 总内存使用量(字节)
|
||||
*/
|
||||
public static getTotalMemoryUsage(): number {
|
||||
let total = 0;
|
||||
for (const pool of this._pools.values()) {
|
||||
total += pool.getStats().estimatedMemoryUsage;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态方法:获取性能报告
|
||||
* @returns 格式化的性能报告
|
||||
*/
|
||||
public static getPerformanceReport(): string {
|
||||
const stats = this.getStats();
|
||||
const lines: string[] = [];
|
||||
|
||||
lines.push('=== Object Pool Performance Report ===');
|
||||
lines.push(`Total Memory Usage: ${(this.getTotalMemoryUsage() / 1024 / 1024).toFixed(2)} MB`);
|
||||
lines.push('');
|
||||
|
||||
for (const [typeName, stat] of Object.entries(stats)) {
|
||||
lines.push(`${typeName}:`);
|
||||
lines.push(` Size: ${stat.size}/${stat.maxSize}`);
|
||||
lines.push(` Hit Rate: ${(stat.hitRate * 100).toFixed(1)}%`);
|
||||
lines.push(` Total Created: ${stat.totalCreated}`);
|
||||
lines.push(` Total Obtained: ${stat.totalObtained}`);
|
||||
lines.push(` Memory: ${(stat.estimatedMemoryUsage / 1024).toFixed(1)} KB`);
|
||||
lines.push('');
|
||||
}
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分层对象池
|
||||
* 使用多个不同大小的池来优化内存使用
|
||||
*/
|
||||
export class TieredObjectPool<T extends IPoolable> {
|
||||
private pools: Pool<T>[] = [];
|
||||
private createFn: () => T;
|
||||
private resetFn: (obj: T) => void;
|
||||
private tierSizes: number[];
|
||||
private totalObtained = 0;
|
||||
private totalReleased = 0;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param createFn 创建对象的函数
|
||||
* @param resetFn 重置对象的函数
|
||||
* @param tierSizes 各层级的大小,默认[10, 50, 200]
|
||||
* @param estimatedObjectSize 估算的单个对象大小
|
||||
*/
|
||||
constructor(
|
||||
createFn: () => T,
|
||||
resetFn: (obj: T) => void,
|
||||
tierSizes: number[] = [10, 50, 200],
|
||||
estimatedObjectSize: number = 1024
|
||||
) {
|
||||
this.createFn = createFn;
|
||||
this.resetFn = resetFn;
|
||||
this.tierSizes = tierSizes;
|
||||
|
||||
// 初始化不同层级的池
|
||||
for (const size of tierSizes) {
|
||||
this.pools.push(new Pool(createFn, size, estimatedObjectSize));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对象
|
||||
* @returns 对象实例
|
||||
*/
|
||||
public obtain(): T {
|
||||
this.totalObtained++;
|
||||
|
||||
// 从最小的池开始尝试获取
|
||||
for (const pool of this.pools) {
|
||||
if (pool.size > 0) {
|
||||
return pool.obtain();
|
||||
}
|
||||
}
|
||||
|
||||
// 所有池都空了,创建新对象
|
||||
return this.createFn();
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放对象
|
||||
* @param obj 要释放的对象
|
||||
*/
|
||||
public release(obj: T): void {
|
||||
this.totalReleased++;
|
||||
this.resetFn(obj);
|
||||
|
||||
// 放入第一个有空间的池
|
||||
for (const pool of this.pools) {
|
||||
if (pool.size < pool.maxSize) {
|
||||
pool.free(obj);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 所有池都满了,直接丢弃
|
||||
}
|
||||
|
||||
/**
|
||||
* 预热所有池
|
||||
* @param totalCount 总预热数量
|
||||
*/
|
||||
public warmUp(totalCount: number): void {
|
||||
let remaining = totalCount;
|
||||
|
||||
for (const pool of this.pools) {
|
||||
const warmUpCount = Math.min(remaining, pool.maxSize);
|
||||
pool.warmUp(warmUpCount);
|
||||
remaining -= warmUpCount;
|
||||
|
||||
if (remaining <= 0) break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空所有池
|
||||
*/
|
||||
public clear(): void {
|
||||
for (const pool of this.pools) {
|
||||
pool.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取统计信息
|
||||
*/
|
||||
public getStats(): {
|
||||
totalSize: number;
|
||||
totalMaxSize: number;
|
||||
totalMemoryUsage: number;
|
||||
tierStats: PoolStats[];
|
||||
hitRate: number;
|
||||
} {
|
||||
let totalSize = 0;
|
||||
let totalMaxSize = 0;
|
||||
let totalMemoryUsage = 0;
|
||||
const tierStats: PoolStats[] = [];
|
||||
|
||||
for (const pool of this.pools) {
|
||||
const stats = pool.getStats();
|
||||
tierStats.push(stats);
|
||||
totalSize += stats.size;
|
||||
totalMaxSize += stats.maxSize;
|
||||
totalMemoryUsage += stats.estimatedMemoryUsage;
|
||||
}
|
||||
|
||||
const hitRate = this.totalObtained > 0 ?
|
||||
(this.totalObtained - this.getTotalCreated()) / this.totalObtained : 0;
|
||||
|
||||
return {
|
||||
totalSize,
|
||||
totalMaxSize,
|
||||
totalMemoryUsage,
|
||||
tierStats,
|
||||
hitRate
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取总创建数量
|
||||
*/
|
||||
private getTotalCreated(): number {
|
||||
return this.pools.reduce((total, pool) => total + pool.getStats().totalCreated, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 池管理器
|
||||
* 统一管理所有对象池
|
||||
*/
|
||||
export class PoolManager {
|
||||
private static instance: PoolManager;
|
||||
private pools = new Map<string, Pool<any> | TieredObjectPool<any>>();
|
||||
private autoCompactInterval = 60000; // 60秒
|
||||
private lastCompactTime = 0;
|
||||
|
||||
public static getInstance(): PoolManager {
|
||||
if (!PoolManager.instance) {
|
||||
PoolManager.instance = new PoolManager();
|
||||
}
|
||||
return PoolManager.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册池
|
||||
* @param name 池名称
|
||||
* @param pool 池实例
|
||||
*/
|
||||
public registerPool<T extends IPoolable>(name: string, pool: Pool<T> | TieredObjectPool<T>): void {
|
||||
this.pools.set(name, pool);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取池
|
||||
* @param name 池名称
|
||||
* @returns 池实例
|
||||
*/
|
||||
public getPool<T extends IPoolable>(name: string): Pool<T> | TieredObjectPool<T> | null {
|
||||
return this.pools.get(name) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新池管理器(应在游戏循环中调用)
|
||||
*/
|
||||
public update(): void {
|
||||
const now = Date.now();
|
||||
|
||||
if (now - this.lastCompactTime > this.autoCompactInterval) {
|
||||
this.compactAllPools();
|
||||
this.lastCompactTime = now;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 压缩所有池(清理碎片)
|
||||
*/
|
||||
public compactAllPools(): void {
|
||||
// 对于标准池,可以考虑清理一些长时间未使用的对象
|
||||
// 这里简单实现为重置统计信息
|
||||
for (const pool of this.pools.values()) {
|
||||
if (pool instanceof Pool) {
|
||||
pool.resetStats();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有池的统计信息
|
||||
*/
|
||||
public getAllStats(): Map<string, any> {
|
||||
const stats = new Map<string, any>();
|
||||
|
||||
for (const [name, pool] of this.pools.entries()) {
|
||||
if (pool instanceof Pool) {
|
||||
stats.set(name, pool.getStats());
|
||||
} else if (pool instanceof TieredObjectPool) {
|
||||
stats.set(name, pool.getStats());
|
||||
}
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成性能报告
|
||||
*/
|
||||
public generateReport(): string {
|
||||
const lines: string[] = [];
|
||||
lines.push('=== Pool Manager Report ===');
|
||||
|
||||
let totalMemory = 0;
|
||||
|
||||
for (const [name, pool] of this.pools.entries()) {
|
||||
lines.push(`\n${name}:`);
|
||||
|
||||
if (pool instanceof Pool) {
|
||||
const stats = pool.getStats();
|
||||
lines.push(` Type: Standard Pool`);
|
||||
lines.push(` Size: ${stats.size}/${stats.maxSize}`);
|
||||
lines.push(` Hit Rate: ${(stats.hitRate * 100).toFixed(1)}%`);
|
||||
lines.push(` Memory: ${(stats.estimatedMemoryUsage / 1024).toFixed(1)} KB`);
|
||||
totalMemory += stats.estimatedMemoryUsage;
|
||||
} else if (pool instanceof TieredObjectPool) {
|
||||
const stats = pool.getStats();
|
||||
lines.push(` Type: Tiered Pool`);
|
||||
lines.push(` Total Size: ${stats.totalSize}/${stats.totalMaxSize}`);
|
||||
lines.push(` Hit Rate: ${(stats.hitRate * 100).toFixed(1)}%`);
|
||||
lines.push(` Memory: ${(stats.totalMemoryUsage / 1024).toFixed(1)} KB`);
|
||||
totalMemory += stats.totalMemoryUsage;
|
||||
}
|
||||
}
|
||||
|
||||
lines.push(`\nTotal Memory Usage: ${(totalMemory / 1024 / 1024).toFixed(2)} MB`);
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
}
|
||||
29
packages/core/src/Utils/Pool/IPoolable.ts
Normal file
29
packages/core/src/Utils/Pool/IPoolable.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 可池化对象接口
|
||||
*/
|
||||
export interface IPoolable {
|
||||
/**
|
||||
* 重置对象状态,准备重用
|
||||
*/
|
||||
reset(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对象池统计信息
|
||||
*/
|
||||
export interface PoolStats {
|
||||
/** 池中对象数量 */
|
||||
size: number;
|
||||
/** 池的最大大小 */
|
||||
maxSize: number;
|
||||
/** 总共创建的对象数量 */
|
||||
totalCreated: number;
|
||||
/** 总共获取的次数 */
|
||||
totalObtained: number;
|
||||
/** 总共释放的次数 */
|
||||
totalReleased: number;
|
||||
/** 命中率(从池中获取的比例) */
|
||||
hitRate: number;
|
||||
/** 内存使用估算(字节) */
|
||||
estimatedMemoryUsage: number;
|
||||
}
|
||||
282
packages/core/src/Utils/Pool/Pool.ts
Normal file
282
packages/core/src/Utils/Pool/Pool.ts
Normal file
@@ -0,0 +1,282 @@
|
||||
import { IPoolable, PoolStats } from './IPoolable';
|
||||
|
||||
/**
|
||||
* 高性能通用对象池
|
||||
* 支持任意类型的对象池化,包含详细的统计信息
|
||||
*/
|
||||
export class Pool<T extends IPoolable> {
|
||||
private static _pools = new Map<Function, Pool<any>>();
|
||||
|
||||
private _objects: T[] = [];
|
||||
private _createFn: () => T;
|
||||
private _maxSize: number;
|
||||
private _stats: PoolStats;
|
||||
private _objectSize: number; // 估算的单个对象大小
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param createFn 创建对象的函数
|
||||
* @param maxSize 池的最大大小,默认100
|
||||
* @param estimatedObjectSize 估算的单个对象大小(字节),默认1024
|
||||
*/
|
||||
constructor(createFn: () => T, maxSize: number = 100, estimatedObjectSize: number = 1024) {
|
||||
this._createFn = createFn;
|
||||
this._maxSize = maxSize;
|
||||
this._objectSize = estimatedObjectSize;
|
||||
this._stats = {
|
||||
size: 0,
|
||||
maxSize,
|
||||
totalCreated: 0,
|
||||
totalObtained: 0,
|
||||
totalReleased: 0,
|
||||
hitRate: 0,
|
||||
estimatedMemoryUsage: 0
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定类型的对象池
|
||||
* @param type 对象类型
|
||||
* @param maxSize 池的最大大小
|
||||
* @param estimatedObjectSize 估算的单个对象大小
|
||||
* @returns 对象池实例
|
||||
*/
|
||||
public static getPool<T extends IPoolable>(
|
||||
type: new (...args: unknown[]) => T,
|
||||
maxSize: number = 100,
|
||||
estimatedObjectSize: number = 1024
|
||||
): Pool<T> {
|
||||
let pool = this._pools.get(type);
|
||||
|
||||
if (!pool) {
|
||||
pool = new Pool<T>(() => new type(), maxSize, estimatedObjectSize);
|
||||
this._pools.set(type, pool);
|
||||
}
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从池中获取对象
|
||||
* @returns 对象实例
|
||||
*/
|
||||
public obtain(): T {
|
||||
this._stats.totalObtained++;
|
||||
|
||||
if (this._objects.length > 0) {
|
||||
const obj = this._objects.pop()!;
|
||||
this._stats.size--;
|
||||
this._updateHitRate();
|
||||
this._updateMemoryUsage();
|
||||
return obj;
|
||||
}
|
||||
|
||||
// 池中没有可用对象,创建新对象
|
||||
this._stats.totalCreated++;
|
||||
this._updateHitRate();
|
||||
return this._createFn();
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放对象回池中
|
||||
* @param obj 要释放的对象
|
||||
*/
|
||||
public release(obj: T): void {
|
||||
if (!obj) return;
|
||||
|
||||
this._stats.totalReleased++;
|
||||
|
||||
// 如果池未满,将对象放回池中
|
||||
if (this._stats.size < this._maxSize) {
|
||||
// 重置对象状态
|
||||
obj.reset();
|
||||
this._objects.push(obj);
|
||||
this._stats.size++;
|
||||
this._updateMemoryUsage();
|
||||
}
|
||||
// 如果池已满,让对象被垃圾回收
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取池统计信息
|
||||
* @returns 统计信息对象
|
||||
*/
|
||||
public getStats(): Readonly<PoolStats> {
|
||||
return { ...this._stats };
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空池
|
||||
*/
|
||||
public clear(): void {
|
||||
// 重置所有对象
|
||||
for (const obj of this._objects) {
|
||||
obj.reset();
|
||||
}
|
||||
|
||||
this._objects.length = 0;
|
||||
this._stats.size = 0;
|
||||
this._updateMemoryUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
* 压缩池(移除多余的对象)
|
||||
* @param targetSize 目标大小,默认为当前大小的一半
|
||||
*/
|
||||
public compact(targetSize?: number): void {
|
||||
const target = targetSize ?? Math.floor(this._objects.length / 2);
|
||||
|
||||
while (this._objects.length > target) {
|
||||
const obj = this._objects.pop();
|
||||
if (obj) {
|
||||
obj.reset();
|
||||
this._stats.size--;
|
||||
}
|
||||
}
|
||||
|
||||
this._updateMemoryUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
* 预填充池
|
||||
* @param count 预填充的对象数量
|
||||
*/
|
||||
public prewarm(count: number): void {
|
||||
const actualCount = Math.min(count, this._maxSize - this._objects.length);
|
||||
|
||||
for (let i = 0; i < actualCount; i++) {
|
||||
const obj = this._createFn();
|
||||
obj.reset();
|
||||
this._objects.push(obj);
|
||||
this._stats.totalCreated++;
|
||||
this._stats.size++;
|
||||
}
|
||||
|
||||
this._updateMemoryUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置最大池大小
|
||||
* @param maxSize 新的最大大小
|
||||
*/
|
||||
public setMaxSize(maxSize: number): void {
|
||||
this._maxSize = maxSize;
|
||||
this._stats.maxSize = maxSize;
|
||||
|
||||
// 如果当前池大小超过新的最大值,进行压缩
|
||||
if (this._objects.length > maxSize) {
|
||||
this.compact(maxSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取池中可用对象数量
|
||||
* @returns 可用对象数量
|
||||
*/
|
||||
public getAvailableCount(): number {
|
||||
return this._objects.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查池是否为空
|
||||
* @returns 如果池为空返回true
|
||||
*/
|
||||
public isEmpty(): boolean {
|
||||
return this._objects.length === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查池是否已满
|
||||
* @returns 如果池已满返回true
|
||||
*/
|
||||
public isFull(): boolean {
|
||||
return this._objects.length >= this._maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有已注册的池类型
|
||||
* @returns 所有池类型的数组
|
||||
*/
|
||||
public static getAllPoolTypes(): Function[] {
|
||||
return Array.from(this._pools.keys());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有池的统计信息
|
||||
* @returns 包含所有池统计信息的对象
|
||||
*/
|
||||
public static getAllPoolStats(): Record<string, PoolStats> {
|
||||
const stats: Record<string, PoolStats> = {};
|
||||
|
||||
for (const [type, pool] of this._pools) {
|
||||
const typeName = type.name || type.toString();
|
||||
stats[typeName] = pool.getStats();
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* 压缩所有池
|
||||
*/
|
||||
public static compactAllPools(): void {
|
||||
for (const pool of this._pools.values()) {
|
||||
pool.compact();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空所有池
|
||||
*/
|
||||
public static clearAllPools(): void {
|
||||
for (const pool of this._pools.values()) {
|
||||
pool.clear();
|
||||
}
|
||||
this._pools.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全局池统计信息的格式化字符串
|
||||
* @returns 格式化的统计信息字符串
|
||||
*/
|
||||
public static getGlobalStatsString(): string {
|
||||
const stats = this.getAllPoolStats();
|
||||
const lines: string[] = ['=== Object Pool Global Statistics ===', ''];
|
||||
|
||||
if (Object.keys(stats).length === 0) {
|
||||
lines.push('No pools registered');
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
for (const [typeName, stat] of Object.entries(stats)) {
|
||||
lines.push(`${typeName}:`);
|
||||
lines.push(` Size: ${stat.size}/${stat.maxSize}`);
|
||||
lines.push(` Hit Rate: ${(stat.hitRate * 100).toFixed(1)}%`);
|
||||
lines.push(` Total Created: ${stat.totalCreated}`);
|
||||
lines.push(` Total Obtained: ${stat.totalObtained}`);
|
||||
lines.push(` Memory: ${(stat.estimatedMemoryUsage / 1024).toFixed(1)} KB`);
|
||||
lines.push('');
|
||||
}
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新命中率
|
||||
*/
|
||||
private _updateHitRate(): void {
|
||||
if (this._stats.totalObtained === 0) {
|
||||
this._stats.hitRate = 0;
|
||||
} else {
|
||||
const hits = this._stats.totalObtained - this._stats.totalCreated;
|
||||
this._stats.hitRate = hits / this._stats.totalObtained;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新内存使用估算
|
||||
*/
|
||||
private _updateMemoryUsage(): void {
|
||||
this._stats.estimatedMemoryUsage = this._stats.size * this._objectSize;
|
||||
}
|
||||
}
|
||||
231
packages/core/src/Utils/Pool/PoolManager.ts
Normal file
231
packages/core/src/Utils/Pool/PoolManager.ts
Normal file
@@ -0,0 +1,231 @@
|
||||
import { IPoolable, PoolStats } from './IPoolable';
|
||||
import { Pool } from './Pool';
|
||||
|
||||
/**
|
||||
* 池管理器
|
||||
* 统一管理所有对象池
|
||||
*/
|
||||
export class PoolManager {
|
||||
private static instance: PoolManager;
|
||||
private pools = new Map<string, Pool<any>>();
|
||||
private autoCompactInterval = 60000; // 60秒
|
||||
private lastCompactTime = 0;
|
||||
|
||||
public static getInstance(): PoolManager {
|
||||
if (!PoolManager.instance) {
|
||||
PoolManager.instance = new PoolManager();
|
||||
}
|
||||
return PoolManager.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册池
|
||||
* @param name 池名称
|
||||
* @param pool 池实例
|
||||
*/
|
||||
public registerPool<T extends IPoolable>(name: string, pool: Pool<T>): void {
|
||||
this.pools.set(name, pool);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取池
|
||||
* @param name 池名称
|
||||
* @returns 池实例
|
||||
*/
|
||||
public getPool<T extends IPoolable>(name: string): Pool<T> | null {
|
||||
return this.pools.get(name) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新池管理器(应在游戏循环中调用)
|
||||
*/
|
||||
public update(): void {
|
||||
const now = Date.now();
|
||||
|
||||
if (now - this.lastCompactTime > this.autoCompactInterval) {
|
||||
this.compactAllPools();
|
||||
this.lastCompactTime = now;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建或获取标准池
|
||||
* @param name 池名称
|
||||
* @param createFn 创建函数
|
||||
* @param maxSize 最大大小
|
||||
* @param estimatedObjectSize 估算对象大小
|
||||
* @returns 池实例
|
||||
*/
|
||||
public createPool<T extends IPoolable>(
|
||||
name: string,
|
||||
createFn: () => T,
|
||||
maxSize: number = 100,
|
||||
estimatedObjectSize: number = 1024
|
||||
): Pool<T> {
|
||||
let pool = this.pools.get(name) as Pool<T>;
|
||||
|
||||
if (!pool) {
|
||||
pool = new Pool(createFn, maxSize, estimatedObjectSize);
|
||||
this.pools.set(name, pool);
|
||||
}
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 移除池
|
||||
* @param name 池名称
|
||||
* @returns 是否成功移除
|
||||
*/
|
||||
public removePool(name: string): boolean {
|
||||
const pool = this.pools.get(name);
|
||||
if (pool) {
|
||||
pool.clear();
|
||||
this.pools.delete(name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有池名称
|
||||
* @returns 池名称数组
|
||||
*/
|
||||
public getPoolNames(): string[] {
|
||||
return Array.from(this.pools.keys());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取池数量
|
||||
* @returns 池数量
|
||||
*/
|
||||
public getPoolCount(): number {
|
||||
return this.pools.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* 压缩所有池
|
||||
*/
|
||||
public compactAllPools(): void {
|
||||
for (const pool of this.pools.values()) {
|
||||
pool.compact();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空所有池
|
||||
*/
|
||||
public clearAllPools(): void {
|
||||
for (const pool of this.pools.values()) {
|
||||
pool.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有池的统计信息
|
||||
* @returns 统计信息映射
|
||||
*/
|
||||
public getAllStats(): Map<string, PoolStats> {
|
||||
const stats = new Map<string, PoolStats>();
|
||||
|
||||
for (const [name, pool] of this.pools) {
|
||||
stats.set(name, pool.getStats());
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取总体统计信息
|
||||
* @returns 总体统计信息
|
||||
*/
|
||||
public getGlobalStats(): PoolStats {
|
||||
let totalSize = 0;
|
||||
let totalMaxSize = 0;
|
||||
let totalCreated = 0;
|
||||
let totalObtained = 0;
|
||||
let totalReleased = 0;
|
||||
let totalMemoryUsage = 0;
|
||||
|
||||
for (const pool of this.pools.values()) {
|
||||
const stats = pool.getStats();
|
||||
totalSize += stats.size;
|
||||
totalMaxSize += stats.maxSize;
|
||||
totalCreated += stats.totalCreated;
|
||||
totalObtained += stats.totalObtained;
|
||||
totalReleased += stats.totalReleased;
|
||||
totalMemoryUsage += stats.estimatedMemoryUsage;
|
||||
}
|
||||
|
||||
const hitRate = totalObtained === 0 ? 0 : (totalObtained - totalCreated) / totalObtained;
|
||||
|
||||
return {
|
||||
size: totalSize,
|
||||
maxSize: totalMaxSize,
|
||||
totalCreated,
|
||||
totalObtained,
|
||||
totalReleased,
|
||||
hitRate,
|
||||
estimatedMemoryUsage: totalMemoryUsage
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取格式化的统计信息字符串
|
||||
* @returns 格式化字符串
|
||||
*/
|
||||
public getStatsString(): string {
|
||||
const lines: string[] = ['=== Pool Manager Statistics ===', ''];
|
||||
|
||||
if (this.pools.size === 0) {
|
||||
lines.push('No pools registered');
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
const globalStats = this.getGlobalStats();
|
||||
lines.push(`Total Pools: ${this.pools.size}`);
|
||||
lines.push(`Global Hit Rate: ${(globalStats.hitRate * 100).toFixed(1)}%`);
|
||||
lines.push(`Global Memory Usage: ${(globalStats.estimatedMemoryUsage / 1024).toFixed(1)} KB`);
|
||||
lines.push('');
|
||||
|
||||
for (const [name, pool] of this.pools) {
|
||||
const stats = pool.getStats();
|
||||
lines.push(`${name}:`);
|
||||
lines.push(` Size: ${stats.size}/${stats.maxSize}`);
|
||||
lines.push(` Hit Rate: ${(stats.hitRate * 100).toFixed(1)}%`);
|
||||
lines.push(` Memory: ${(stats.estimatedMemoryUsage / 1024).toFixed(1)} KB`);
|
||||
lines.push('');
|
||||
}
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置自动压缩间隔
|
||||
* @param intervalMs 间隔毫秒数
|
||||
*/
|
||||
public setAutoCompactInterval(intervalMs: number): void {
|
||||
this.autoCompactInterval = intervalMs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 预填充所有池
|
||||
*/
|
||||
public prewarmAllPools(): void {
|
||||
for (const pool of this.pools.values()) {
|
||||
const stats = pool.getStats();
|
||||
const prewarmCount = Math.floor(stats.maxSize * 0.2); // 预填充20%
|
||||
pool.prewarm(prewarmCount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置池管理器
|
||||
*/
|
||||
public reset(): void {
|
||||
this.clearAllPools();
|
||||
this.pools.clear();
|
||||
this.lastCompactTime = 0;
|
||||
}
|
||||
}
|
||||
3
packages/core/src/Utils/Pool/index.ts
Normal file
3
packages/core/src/Utils/Pool/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './IPoolable';
|
||||
export * from './Pool';
|
||||
export * from './PoolManager';
|
||||
@@ -5,3 +5,4 @@ export * from './GlobalManager';
|
||||
export * from './PerformanceMonitor';
|
||||
export { Time } from './Time';
|
||||
export * from './Debug';
|
||||
export * from './Logger';
|
||||
@@ -13,6 +13,17 @@ export { TimerManager } from './Utils/Timers/TimerManager';
|
||||
export { ITimer } from './Utils/Timers/ITimer';
|
||||
export { Timer } from './Utils/Timers/Timer';
|
||||
|
||||
// 日志系统
|
||||
export {
|
||||
LoggerManager,
|
||||
ConsoleLogger,
|
||||
Logger,
|
||||
createLogger,
|
||||
setGlobalLogLevel,
|
||||
LogLevel
|
||||
} from './Utils/Logger';
|
||||
export type { ILogger, LoggerConfig } from './Utils/Logger';
|
||||
|
||||
// ECS核心组件
|
||||
export * from './ECS';
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
"@esengine/ecs-framework": ">=2.1.29"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@esengine/ecs-framework": "file:../core",
|
||||
"@esengine/ecs-framework": "*",
|
||||
"@rollup/plugin-commonjs": "^28.0.3",
|
||||
"@rollup/plugin-node-resolve": "^16.0.1",
|
||||
"@rollup/plugin-terser": "^0.4.4",
|
||||
|
||||
@@ -4,6 +4,7 @@ import { SyncVarUpdateMessage } from '../Messaging/MessageTypes';
|
||||
import { SyncVarMessageHandler } from '../SyncVar/SyncVarMessageHandler';
|
||||
import { MessageHandler } from '../Messaging/MessageHandler';
|
||||
import { NetworkPerformanceMonitor } from './NetworkPerformanceMonitor';
|
||||
import { createLogger } from '@esengine/ecs-framework';
|
||||
|
||||
/**
|
||||
* 客户端事件接口
|
||||
@@ -24,6 +25,7 @@ export interface NetworkClientEvents {
|
||||
* 提供消息发送和接收功能
|
||||
*/
|
||||
export class NetworkClient {
|
||||
private static readonly logger = createLogger('NetworkClient');
|
||||
private _connection: NetworkConnection | null = null;
|
||||
private _url: string = '';
|
||||
private _isConnected: boolean = false;
|
||||
@@ -129,7 +131,7 @@ export class NetworkClient {
|
||||
|
||||
// 设置连接事件监听
|
||||
this._connection.on('connected', () => {
|
||||
console.log(`[NetworkClient] 连接成功: ${this._url}`);
|
||||
NetworkClient.logger.info(`连接成功: ${this._url}`);
|
||||
this.emit('connected');
|
||||
|
||||
// 如果这是重连,触发重连成功事件
|
||||
@@ -139,7 +141,7 @@ export class NetworkClient {
|
||||
});
|
||||
|
||||
this._connection.on('disconnected', (reason) => {
|
||||
console.log(`[NetworkClient] 连接断开: ${reason}`);
|
||||
NetworkClient.logger.info(`连接断开: ${reason}`);
|
||||
this.handleDisconnection(reason);
|
||||
});
|
||||
|
||||
@@ -153,7 +155,7 @@ export class NetworkClient {
|
||||
});
|
||||
|
||||
this._connection.on('error', (error) => {
|
||||
console.error('[NetworkClient] 连接错误:', error);
|
||||
NetworkClient.logger.error('连接错误:', error);
|
||||
this.emit('error', error);
|
||||
});
|
||||
|
||||
@@ -214,7 +216,7 @@ export class NetworkClient {
|
||||
this._maxReconnectDelay
|
||||
);
|
||||
|
||||
console.log(`[NetworkClient] ${delay}ms后尝试重连 (${this._reconnectAttempts}/${this._maxReconnectAttempts})`);
|
||||
NetworkClient.logger.info(`${delay}ms后尝试重连 (${this._reconnectAttempts}/${this._maxReconnectAttempts})`);
|
||||
this.emit('reconnecting', this._reconnectAttempts);
|
||||
|
||||
this._reconnectTimer = setTimeout(async () => {
|
||||
@@ -266,7 +268,7 @@ export class NetworkClient {
|
||||
*/
|
||||
public send(data: Uint8Array): boolean {
|
||||
if (!this._connection || !this._isConnected) {
|
||||
console.warn('[NetworkClient] 未连接,无法发送数据');
|
||||
NetworkClient.logger.warn('未连接,无法发送数据');
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -364,7 +366,7 @@ export class NetworkClient {
|
||||
try {
|
||||
handler(...args);
|
||||
} catch (error) {
|
||||
console.error(`[NetworkClient] 事件处理器错误 (${event}):`, error);
|
||||
NetworkClient.logger.error(`事件处理器错误 (${event}):`, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -449,14 +451,14 @@ export class NetworkClient {
|
||||
const success = this.send(serializedMessage);
|
||||
|
||||
if (success) {
|
||||
console.log(`[NetworkClient] 发送SyncVar消息: ${message.networkId}.${message.componentType}`);
|
||||
NetworkClient.logger.debug(`发送SyncVar消息: ${message.networkId}.${message.componentType}`);
|
||||
} else {
|
||||
console.warn(`[NetworkClient] SyncVar消息发送失败: ${message.networkId}.${message.componentType}`);
|
||||
NetworkClient.logger.warn(`SyncVar消息发送失败: ${message.networkId}.${message.componentType}`);
|
||||
}
|
||||
|
||||
return success;
|
||||
} catch (error) {
|
||||
console.error('[NetworkClient] 发送SyncVar消息失败:', error);
|
||||
NetworkClient.logger.error('发送SyncVar消息失赅:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -476,7 +478,7 @@ export class NetworkClient {
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`[NetworkClient] 批量发送SyncVar消息: ${successCount}/${messages.length} 成功`);
|
||||
NetworkClient.logger.debug(`批量发送SyncVar消息: ${successCount}/${messages.length} 成功`);
|
||||
return successCount;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import WebSocket from 'isomorphic-ws';
|
||||
import { createLogger } from '@esengine/ecs-framework';
|
||||
|
||||
/**
|
||||
* 网络连接状态
|
||||
@@ -27,6 +28,7 @@ export interface NetworkConnectionEvents {
|
||||
* 支持二进制消息传输,集成心跳检测
|
||||
*/
|
||||
export class NetworkConnection {
|
||||
private static readonly logger = createLogger('NetworkConnection');
|
||||
private _ws: WebSocket | null = null;
|
||||
private _state: ConnectionState = ConnectionState.Disconnected;
|
||||
private _connectionId: string = '';
|
||||
@@ -96,13 +98,13 @@ export class NetworkConnection {
|
||||
// 将字符串转换为Uint8Array
|
||||
data = new TextEncoder().encode(event.data);
|
||||
} else {
|
||||
console.warn('[NetworkConnection] 收到未知类型的消息:', typeof event.data);
|
||||
NetworkConnection.logger.warn(' 收到未知类型的消息:', typeof event.data);
|
||||
return;
|
||||
}
|
||||
|
||||
this.emit('message', data);
|
||||
} catch (error) {
|
||||
console.error('[NetworkConnection] 消息处理错误:', error);
|
||||
NetworkConnection.logger.error(' 消息处理错误:', error);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -136,7 +138,7 @@ export class NetworkConnection {
|
||||
try {
|
||||
this._ws.send('ping');
|
||||
} catch (error) {
|
||||
console.error('[NetworkConnection] 心跳发送失败:', error);
|
||||
NetworkConnection.logger.error(' 心跳发送失败:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,7 +151,7 @@ export class NetworkConnection {
|
||||
*/
|
||||
public send(data: Uint8Array): boolean {
|
||||
if (!this._ws || this._state !== ConnectionState.Connected) {
|
||||
console.warn('[NetworkConnection] 连接未就绪,无法发送数据');
|
||||
NetworkConnection.logger.warn(' 连接未就绪,无法发送数据');
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -157,7 +159,7 @@ export class NetworkConnection {
|
||||
this._ws.send(data);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('[NetworkConnection] 数据发送失败:', error);
|
||||
NetworkConnection.logger.error(' 数据发送失败:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -179,7 +181,7 @@ export class NetworkConnection {
|
||||
try {
|
||||
this._ws.close(1000, reason);
|
||||
} catch (error) {
|
||||
console.error('[NetworkConnection] 连接关闭失败:', error);
|
||||
NetworkConnection.logger.error(' 连接关闭失败:', error);
|
||||
}
|
||||
this._ws = null;
|
||||
}
|
||||
@@ -236,7 +238,7 @@ export class NetworkConnection {
|
||||
try {
|
||||
handler(...args);
|
||||
} catch (error) {
|
||||
console.error(`[NetworkConnection] 事件处理器错误 (${event}):`, error);
|
||||
NetworkConnection.logger.error(`事件处理器错误 (${event}):`, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { NetworkRole } from '../NetworkRole';
|
||||
import { createLogger } from '@esengine/ecs-framework';
|
||||
|
||||
/**
|
||||
* 网络环境状态
|
||||
@@ -21,6 +22,7 @@ export enum NetworkEnvironmentState {
|
||||
* 避免在构造函数中传递角色参数,保持与核心ECS框架的兼容性
|
||||
*/
|
||||
export class NetworkEnvironment {
|
||||
private static readonly logger = createLogger('NetworkEnvironment');
|
||||
private static _instance: NetworkEnvironment | null = null;
|
||||
private _state: NetworkEnvironmentState = NetworkEnvironmentState.None;
|
||||
private _serverStartTime: number = 0;
|
||||
@@ -52,7 +54,7 @@ export class NetworkEnvironment {
|
||||
}
|
||||
|
||||
instance._serverStartTime = Date.now();
|
||||
console.log(`[NetworkEnvironment] 环境设置为: ${instance._state}`);
|
||||
NetworkEnvironment.logger.info(`环境设置为: ${instance._state}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,7 +71,7 @@ export class NetworkEnvironment {
|
||||
}
|
||||
|
||||
instance._clientConnectTime = Date.now();
|
||||
console.log(`[NetworkEnvironment] 环境设置为: ${instance._state}`);
|
||||
NetworkEnvironment.logger.info(`环境设置为: ${instance._state}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,7 +87,7 @@ export class NetworkEnvironment {
|
||||
}
|
||||
|
||||
instance._serverStartTime = 0;
|
||||
console.log(`[NetworkEnvironment] 服务端模式已清除,当前状态: ${instance._state}`);
|
||||
NetworkEnvironment.logger.info(`服务端模式已清除,当前状态: ${instance._state}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,7 +103,7 @@ export class NetworkEnvironment {
|
||||
}
|
||||
|
||||
instance._clientConnectTime = 0;
|
||||
console.log(`[NetworkEnvironment] 客户端模式已清除,当前状态: ${instance._state}`);
|
||||
NetworkEnvironment.logger.info(`客户端模式已清除,当前状态: ${instance._state}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,7 +114,7 @@ export class NetworkEnvironment {
|
||||
instance._state = NetworkEnvironmentState.None;
|
||||
instance._serverStartTime = 0;
|
||||
instance._clientConnectTime = 0;
|
||||
console.log('[NetworkEnvironment] 环境状态已重置');
|
||||
NetworkEnvironment.logger.info('环境状态已重置');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,6 +243,6 @@ export class NetworkEnvironment {
|
||||
instance._clientConnectTime = clientConnectTime;
|
||||
}
|
||||
|
||||
console.log(`[NetworkEnvironment] 强制设置环境状态为: ${state}`);
|
||||
NetworkEnvironment.logger.debug(`强制设置环境状态为: ${state}`);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component } from '@esengine/ecs-framework';
|
||||
import { Component, createLogger } from '@esengine/ecs-framework';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
/**
|
||||
@@ -8,6 +8,8 @@ import { v4 as uuidv4 } from 'uuid';
|
||||
* 每个需要网络同步的实体都必须拥有此组件
|
||||
*/
|
||||
export class NetworkIdentity extends Component {
|
||||
private static readonly logger = createLogger('NetworkIdentity');
|
||||
|
||||
/**
|
||||
* 网络对象唯一ID
|
||||
*/
|
||||
@@ -74,7 +76,7 @@ export class NetworkIdentity extends Component {
|
||||
// 自动注册到NetworkIdentityRegistry
|
||||
NetworkIdentityRegistry.Instance.register(this);
|
||||
|
||||
console.log(`[NetworkIdentity] 创建网络对象: ${this.networkId}, 权威: ${hasAuthority}`);
|
||||
NetworkIdentity.logger.debug(` 创建网络对象: ${this.networkId}, 权威: ${hasAuthority}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,7 +88,7 @@ export class NetworkIdentity extends Component {
|
||||
const oldOwnerId = this.ownerId;
|
||||
this.ownerId = ownerId;
|
||||
|
||||
console.log(`[NetworkIdentity] 对象 ${this.networkId} 拥有者变更: ${oldOwnerId} -> ${ownerId}`);
|
||||
NetworkIdentity.logger.debug(` 对象 ${this.networkId} 拥有者变更: ${oldOwnerId} -> ${ownerId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,7 +99,7 @@ export class NetworkIdentity extends Component {
|
||||
public setAuthority(hasAuthority: boolean): void {
|
||||
if (this.hasAuthority !== hasAuthority) {
|
||||
this.hasAuthority = hasAuthority;
|
||||
console.log(`[NetworkIdentity] 对象 ${this.networkId} 权威状态变更: ${hasAuthority}`);
|
||||
NetworkIdentity.logger.debug(` 对象 ${this.networkId} 权威状态变更: ${hasAuthority}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +109,7 @@ export class NetworkIdentity extends Component {
|
||||
public activate(): void {
|
||||
if (!this.isNetworkActive) {
|
||||
this.isNetworkActive = true;
|
||||
console.log(`[NetworkIdentity] 激活网络对象: ${this.networkId}`);
|
||||
NetworkIdentity.logger.debug(` 激活网络对象: ${this.networkId}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +119,7 @@ export class NetworkIdentity extends Component {
|
||||
public deactivate(): void {
|
||||
if (this.isNetworkActive) {
|
||||
this.isNetworkActive = false;
|
||||
console.log(`[NetworkIdentity] 停用网络对象: ${this.networkId}`);
|
||||
NetworkIdentity.logger.debug(` 停用网络对象: ${this.networkId}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +180,7 @@ export class NetworkIdentity extends Component {
|
||||
public cleanup(): void {
|
||||
NetworkIdentityRegistry.Instance.unregister(this.networkId);
|
||||
this.deactivate();
|
||||
console.log(`[NetworkIdentity] 清理网络对象: ${this.networkId}`);
|
||||
NetworkIdentity.logger.debug(` 清理网络对象: ${this.networkId}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,6 +190,7 @@ export class NetworkIdentity extends Component {
|
||||
* 管理所有网络对象的注册和查找
|
||||
*/
|
||||
export class NetworkIdentityRegistry {
|
||||
private static readonly logger = createLogger('NetworkIdentityRegistry');
|
||||
private static _instance: NetworkIdentityRegistry | null = null;
|
||||
|
||||
/**
|
||||
@@ -226,7 +229,7 @@ export class NetworkIdentityRegistry {
|
||||
*/
|
||||
public register(identity: NetworkIdentity): void {
|
||||
if (this._identities.has(identity.networkId)) {
|
||||
console.warn(`[NetworkIdentityRegistry] 网络对象ID重复: ${identity.networkId}`);
|
||||
NetworkIdentityRegistry.logger.warn(` 网络对象ID重复: ${identity.networkId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -242,7 +245,7 @@ export class NetworkIdentityRegistry {
|
||||
this._authorityObjects.add(identity);
|
||||
}
|
||||
|
||||
console.log(`[NetworkIdentityRegistry] 注册网络对象: ${identity.networkId}`);
|
||||
NetworkIdentityRegistry.logger.debug(` 注册网络对象: ${identity.networkId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -266,7 +269,7 @@ export class NetworkIdentityRegistry {
|
||||
// 从权威对象集合中移除
|
||||
this._authorityObjects.delete(identity);
|
||||
|
||||
console.log(`[NetworkIdentityRegistry] 注销网络对象: ${networkId}`);
|
||||
NetworkIdentityRegistry.logger.debug(` 注销网络对象: ${networkId}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -386,7 +389,7 @@ export class NetworkIdentityRegistry {
|
||||
identity.setAuthority(false);
|
||||
}
|
||||
|
||||
console.log(`[NetworkIdentityRegistry] 清理断开连接客户端 ${disconnectedOwnerId} 的 ${ownerObjects.length} 个对象`);
|
||||
NetworkIdentityRegistry.logger.debug(` 清理断开连接客户端 ${disconnectedOwnerId} 的 ${ownerObjects.length} 个对象`);
|
||||
return ownerObjects;
|
||||
}
|
||||
|
||||
@@ -473,6 +476,6 @@ export class NetworkIdentityRegistry {
|
||||
this._identities.clear();
|
||||
this._ownerObjects.clear();
|
||||
this._authorityObjects.clear();
|
||||
console.log('[NetworkIdentityRegistry] 已清空注册表');
|
||||
NetworkIdentityRegistry.logger.info(' 已清空注册表');
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NetworkServer } from './NetworkServer';
|
||||
import { NetworkClient } from './NetworkClient';
|
||||
import { NetworkEnvironment } from './NetworkEnvironment';
|
||||
import { createLogger } from '@esengine/ecs-framework';
|
||||
|
||||
/**
|
||||
* 网络管理器 - 网络框架的核心入口
|
||||
@@ -9,6 +10,7 @@ import { NetworkEnvironment } from './NetworkEnvironment';
|
||||
* 支持启动服务端、客户端,管理连接状态
|
||||
*/
|
||||
export class NetworkManager {
|
||||
private static readonly _logger = createLogger('NetworkManager');
|
||||
private static _instance: NetworkManager | null = null;
|
||||
private _server: NetworkServer | null = null;
|
||||
private _client: NetworkClient | null = null;
|
||||
@@ -38,7 +40,7 @@ export class NetworkManager {
|
||||
const instance = NetworkManager.Instance;
|
||||
|
||||
if (instance._isServer) {
|
||||
console.warn('[NetworkManager] 服务端已经在运行');
|
||||
NetworkManager._logger.warn('服务端已经在运行');
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -50,10 +52,10 @@ export class NetworkManager {
|
||||
// 自动设置网络环境为服务端模式
|
||||
NetworkEnvironment.SetServerMode();
|
||||
|
||||
console.log(`[NetworkManager] 服务端启动成功,监听 ${host}:${port}`);
|
||||
NetworkManager._logger.info(`服务端启动成功,监听 ${host}:${port}`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('[NetworkManager] 服务端启动失败:', error);
|
||||
NetworkManager._logger.error('服务端启动失败:', error);
|
||||
instance._server = null;
|
||||
return false;
|
||||
}
|
||||
@@ -69,7 +71,7 @@ export class NetworkManager {
|
||||
const instance = NetworkManager.Instance;
|
||||
|
||||
if (instance._isClient) {
|
||||
console.warn('[NetworkManager] 客户端已经在运行');
|
||||
NetworkManager._logger.warn('客户端已经在运行');
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -81,10 +83,10 @@ export class NetworkManager {
|
||||
// 自动设置网络环境为客户端模式
|
||||
NetworkEnvironment.SetClientMode();
|
||||
|
||||
console.log(`[NetworkManager] 客户端连接成功: ${url}`);
|
||||
NetworkManager._logger.info(`客户端连接成功: ${url}`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('[NetworkManager] 客户端连接失败:', error);
|
||||
NetworkManager._logger.error('客户端连接失败:', error);
|
||||
instance._client = null;
|
||||
return false;
|
||||
}
|
||||
@@ -104,7 +106,7 @@ export class NetworkManager {
|
||||
// 清除服务端环境模式
|
||||
NetworkEnvironment.ClearServerMode();
|
||||
|
||||
console.log('[NetworkManager] 服务端已停止');
|
||||
NetworkManager._logger.info('服务端已停止');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +124,7 @@ export class NetworkManager {
|
||||
// 清除客户端环境模式
|
||||
NetworkEnvironment.ClearClientMode();
|
||||
|
||||
console.log('[NetworkManager] 客户端已断开连接');
|
||||
NetworkManager._logger.info('客户端已断开连接');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*
|
||||
* 监控网络连接的性能指标,包括延迟、吞吐量、包丢失率等
|
||||
*/
|
||||
import { createLogger } from '@esengine/ecs-framework';
|
||||
|
||||
export interface NetworkMetrics {
|
||||
/** 往返时延 (ms) */
|
||||
@@ -56,6 +57,7 @@ export interface PerformanceSnapshot {
|
||||
* 网络性能监控器
|
||||
*/
|
||||
export class NetworkPerformanceMonitor {
|
||||
private static readonly logger = createLogger('NetworkPerformanceMonitor');
|
||||
private static _instance: NetworkPerformanceMonitor | null = null;
|
||||
|
||||
/** 性能快照历史 */
|
||||
@@ -117,7 +119,7 @@ export class NetworkPerformanceMonitor {
|
||||
*/
|
||||
public startMonitoring(interval: number = 1000): void {
|
||||
if (this._isMonitoring) {
|
||||
console.warn('[NetworkPerformanceMonitor] 监控已在运行');
|
||||
NetworkPerformanceMonitor.logger.warn('监控已在运行');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -128,7 +130,7 @@ export class NetworkPerformanceMonitor {
|
||||
this.collectMetrics();
|
||||
}, this._monitoringInterval);
|
||||
|
||||
console.log(`[NetworkPerformanceMonitor] 开始性能监控,间隔: ${interval}ms`);
|
||||
NetworkPerformanceMonitor.logger.info(`开始性能监控,间隔: ${interval}ms`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,7 +147,7 @@ export class NetworkPerformanceMonitor {
|
||||
}
|
||||
|
||||
this._isMonitoring = false;
|
||||
console.log('[NetworkPerformanceMonitor] 停止性能监控');
|
||||
NetworkPerformanceMonitor.logger.info('停止性能监控');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -308,7 +310,7 @@ export class NetworkPerformanceMonitor {
|
||||
syncDataSize: stats.totalDataSize || 0
|
||||
};
|
||||
} catch (error) {
|
||||
console.warn('[NetworkPerformanceMonitor] 获取SyncVar统计失败:', error);
|
||||
NetworkPerformanceMonitor.logger.warn('获取SyncVar统计失败:', error);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -337,7 +339,7 @@ export class NetworkPerformanceMonitor {
|
||||
|
||||
if (warnings.length > 0) {
|
||||
this.emit('performanceWarning', warnings);
|
||||
console.warn('[NetworkPerformanceMonitor] 性能警告:', warnings.join(', '));
|
||||
NetworkPerformanceMonitor.logger.warn('性能警告:', warnings.join(', '));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,7 +420,7 @@ export class NetworkPerformanceMonitor {
|
||||
this._snapshots = [];
|
||||
this._rttHistory = [];
|
||||
this._bandwidthWindow = [];
|
||||
console.log('[NetworkPerformanceMonitor] 清除历史数据');
|
||||
NetworkPerformanceMonitor.logger.debug('清除历史数据');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -504,7 +506,7 @@ export class NetworkPerformanceMonitor {
|
||||
try {
|
||||
listener(...args);
|
||||
} catch (error) {
|
||||
console.error(`[NetworkPerformanceMonitor] 事件处理器错误 (${event}):`, error);
|
||||
NetworkPerformanceMonitor.logger.error(`事件处理器错误 (${event}):`, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -530,7 +532,7 @@ export class NetworkPerformanceMonitor {
|
||||
this._bandwidthWindowSize = options.bandwidthWindowSize;
|
||||
}
|
||||
|
||||
console.log('[NetworkPerformanceMonitor] 配置已更新:', options);
|
||||
NetworkPerformanceMonitor.logger.info('配置已更新:', options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,7 @@ import { SyncVarMessageHandler } from '../SyncVar/SyncVarMessageHandler';
|
||||
import { SyncVarSyncScheduler } from '../SyncVar/SyncVarSyncScheduler';
|
||||
import { MessageHandler } from '../Messaging/MessageHandler';
|
||||
import { NetworkPerformanceMonitor } from './NetworkPerformanceMonitor';
|
||||
import { createLogger } from '@esengine/ecs-framework';
|
||||
|
||||
/**
|
||||
* 服务端事件接口
|
||||
@@ -26,6 +27,7 @@ export interface NetworkServerEvents {
|
||||
* 支持多客户端连接,提供广播和单播功能
|
||||
*/
|
||||
export class NetworkServer {
|
||||
private static readonly _logger = createLogger('NetworkServer');
|
||||
private _wss: WebSocketServer | null = null;
|
||||
private _connections: Map<string, NetworkConnection> = new Map();
|
||||
private _isRunning: boolean = false;
|
||||
@@ -104,13 +106,13 @@ export class NetworkServer {
|
||||
// 启动性能监控
|
||||
this.startPerformanceMonitoring();
|
||||
|
||||
console.log(`[NetworkServer] 服务器启动成功: ${host}:${port}`);
|
||||
NetworkServer._logger.info(`服务器启动成功: ${host}:${port}`);
|
||||
this.emit('serverStarted', port, host);
|
||||
resolve();
|
||||
});
|
||||
|
||||
this._wss.on('error', (error) => {
|
||||
console.error('[NetworkServer] 服务器错误:', error);
|
||||
NetworkServer._logger.error('服务器错误:', error);
|
||||
this.emit('error', error);
|
||||
|
||||
if (!this._isRunning) {
|
||||
@@ -154,7 +156,7 @@ export class NetworkServer {
|
||||
this._host = '';
|
||||
this._startTime = 0;
|
||||
|
||||
console.log('[NetworkServer] 服务器已停止');
|
||||
NetworkServer._logger.info('服务器已停止');
|
||||
this.emit('serverStopped');
|
||||
resolve();
|
||||
});
|
||||
@@ -170,7 +172,7 @@ export class NetworkServer {
|
||||
private handleNewConnection(ws: WebSocket, request: any): void {
|
||||
// 检查连接数限制
|
||||
if (this._connections.size >= NetworkServer.MAX_CONNECTIONS) {
|
||||
console.warn('[NetworkServer] 达到最大连接数限制,拒绝新连接');
|
||||
NetworkServer._logger.warn('达到最大连接数限制,拒绝新连接');
|
||||
ws.close(1013, 'Server full');
|
||||
return;
|
||||
}
|
||||
@@ -185,13 +187,13 @@ export class NetworkServer {
|
||||
// 设置连接事件监听
|
||||
connection.on('connected', () => {
|
||||
this._connections.set(connectionId, connection);
|
||||
console.log(`[NetworkServer] 客户端连接: ${connectionId} (${clientAddress})`);
|
||||
NetworkServer._logger.info(`客户端连接: ${connectionId} (${clientAddress})`);
|
||||
this.emit('clientConnected', connection);
|
||||
});
|
||||
|
||||
connection.on('disconnected', (reason) => {
|
||||
this._connections.delete(connectionId);
|
||||
console.log(`[NetworkServer] 客户端断开: ${connectionId} (${reason})`);
|
||||
NetworkServer._logger.info(`客户端断开: ${connectionId} (${reason})`);
|
||||
this.emit('clientDisconnected', connection, reason);
|
||||
});
|
||||
|
||||
@@ -205,7 +207,7 @@ export class NetworkServer {
|
||||
});
|
||||
|
||||
connection.on('error', (error) => {
|
||||
console.error(`[NetworkServer] 连接错误 ${connectionId}:`, error);
|
||||
NetworkServer._logger.error(`连接错误 ${connectionId}:`, error);
|
||||
this.emit('error', error);
|
||||
});
|
||||
}
|
||||
@@ -220,7 +222,7 @@ export class NetworkServer {
|
||||
public sendToClient(connectionId: string, data: Uint8Array): boolean {
|
||||
const connection = this._connections.get(connectionId);
|
||||
if (!connection) {
|
||||
console.warn(`[NetworkServer] 连接不存在: ${connectionId}`);
|
||||
NetworkServer._logger.warn(`连接不存在: ${connectionId}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -370,7 +372,7 @@ export class NetworkServer {
|
||||
try {
|
||||
handler(...args);
|
||||
} catch (error) {
|
||||
console.error(`[NetworkServer] 事件处理器错误 (${event}):`, error);
|
||||
NetworkServer._logger.error(`事件处理器错误 (${event}):`, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -417,9 +419,9 @@ export class NetworkServer {
|
||||
private startSyncVarScheduler(): void {
|
||||
try {
|
||||
this._syncScheduler.start();
|
||||
console.log('[NetworkServer] SyncVar同步调度器已启动');
|
||||
NetworkServer._logger.info('SyncVar同步调度器已启动');
|
||||
} catch (error) {
|
||||
console.error('[NetworkServer] 启动SyncVar调度器失败:', error);
|
||||
NetworkServer._logger.error('启动SyncVar调度器失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -429,9 +431,9 @@ export class NetworkServer {
|
||||
private stopSyncVarScheduler(): void {
|
||||
try {
|
||||
this._syncScheduler.stop();
|
||||
console.log('[NetworkServer] SyncVar同步调度器已停止');
|
||||
NetworkServer._logger.info('SyncVar同步调度器已停止');
|
||||
} catch (error) {
|
||||
console.error('[NetworkServer] 停止SyncVar调度器失败:', error);
|
||||
NetworkServer._logger.error('停止SyncVar调度器失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,9 +447,9 @@ export class NetworkServer {
|
||||
const serializedMessage = message.serialize();
|
||||
const successCount = this.broadcast(serializedMessage);
|
||||
|
||||
console.log(`[NetworkServer] 广播SyncVar消息: ${message.networkId}.${message.componentType}, 成功发送到 ${successCount} 个客户端`);
|
||||
NetworkServer._logger.info(`广播SyncVar消息: ${message.networkId}.${message.componentType}, 成功发送到 ${successCount} 个客户端`);
|
||||
} catch (error) {
|
||||
console.error('[NetworkServer] 广播SyncVar消息失败:', error);
|
||||
NetworkServer._logger.error('广播SyncVar消息失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,7 +464,7 @@ export class NetworkServer {
|
||||
const serializedMessage = message.serialize();
|
||||
return this.sendToClient(connectionId, serializedMessage);
|
||||
} catch (error) {
|
||||
console.error(`[NetworkServer] 发送SyncVar消息到客户端 ${connectionId} 失败:`, error);
|
||||
NetworkServer._logger.error(`发送SyncVar消息到客户端 ${connectionId} 失败:`, error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -481,7 +483,7 @@ export class NetworkServer {
|
||||
|
||||
return this.sendToMultipleClients(targetConnections, serializedMessage);
|
||||
} catch (error) {
|
||||
console.error('[NetworkServer] 广播SyncVar消息(排除指定客户端)失败:', error);
|
||||
NetworkServer._logger.error('广播SyncVar消息(排除指定客户端)失败:', error);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -506,9 +508,9 @@ export class NetworkServer {
|
||||
private startPerformanceMonitoring(): void {
|
||||
try {
|
||||
this._performanceMonitor.startMonitoring();
|
||||
console.log('[NetworkServer] 性能监控已启动');
|
||||
NetworkServer._logger.info('性能监控已启动');
|
||||
} catch (error) {
|
||||
console.error('[NetworkServer] 启动性能监控失败:', error);
|
||||
NetworkServer._logger.error('启动性能监控失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,9 +520,9 @@ export class NetworkServer {
|
||||
private stopPerformanceMonitoring(): void {
|
||||
try {
|
||||
this._performanceMonitor.stopMonitoring();
|
||||
console.log('[NetworkServer] 性能监控已停止');
|
||||
NetworkServer._logger.info('性能监控已停止');
|
||||
} catch (error) {
|
||||
console.error('[NetworkServer] 停止性能监控失败:', error);
|
||||
NetworkServer._logger.error('停止性能监控失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,15 +11,6 @@ export { NetworkConnection, ConnectionState } from './NetworkConnection';
|
||||
export { NetworkEnvironment, NetworkEnvironmentState } from './NetworkEnvironment';
|
||||
export { NetworkIdentity, NetworkIdentityRegistry } from './NetworkIdentity';
|
||||
export { NetworkPerformanceMonitor } from './NetworkPerformanceMonitor';
|
||||
export {
|
||||
LoggerManager,
|
||||
ConsoleLogger,
|
||||
Logger,
|
||||
createLogger,
|
||||
setGlobalLogLevel,
|
||||
LogLevel
|
||||
} from './Logger';
|
||||
|
||||
// 事件接口导出
|
||||
export type { NetworkServerEvents } from './NetworkServer';
|
||||
export type { NetworkClientEvents } from './NetworkClient';
|
||||
@@ -27,6 +18,3 @@ export type { NetworkConnectionEvents } from './NetworkConnection';
|
||||
|
||||
// 性能监控类型导出
|
||||
export type { NetworkMetrics, PerformanceSnapshot } from './NetworkPerformanceMonitor';
|
||||
|
||||
// 日志类型导出
|
||||
export type { ILogger, LoggerConfig } from './Logger';
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NetworkMessage } from './NetworkMessage';
|
||||
import { NetworkConnection } from '../Core/NetworkConnection';
|
||||
import { INetworkMessage, MessageData } from '../types/NetworkTypes';
|
||||
import { createLogger } from '@esengine/ecs-framework';
|
||||
|
||||
/**
|
||||
* 消息处理器接口
|
||||
@@ -31,6 +32,7 @@ interface MessageHandlerInfo<T extends MessageData = MessageData> {
|
||||
* 支持消息优先级和类型匹配
|
||||
*/
|
||||
export class MessageHandler {
|
||||
private static readonly logger = createLogger('MessageHandler');
|
||||
private static _instance: MessageHandler | null = null;
|
||||
private _handlers: Map<number, MessageHandlerInfo[]> = new Map();
|
||||
private _messageClasses: Map<number, new (...args: any[]) => INetworkMessage> = new Map();
|
||||
@@ -74,7 +76,7 @@ export class MessageHandler {
|
||||
// 检查是否已经注册了相同的处理器
|
||||
const existingIndex = handlers.findIndex(h => h.handler === handler);
|
||||
if (existingIndex !== -1) {
|
||||
console.warn(`[MessageHandler] 消息类型 ${messageType} 的处理器已存在,将替换优先级`);
|
||||
MessageHandler.logger.warn(`消息类型 ${messageType} 的处理器已存在,将替换优先级`);
|
||||
handlers[existingIndex].priority = priority;
|
||||
} else {
|
||||
// 添加新处理器
|
||||
@@ -88,7 +90,7 @@ export class MessageHandler {
|
||||
// 按优先级排序(数字越小优先级越高)
|
||||
handlers.sort((a, b) => a.priority - b.priority);
|
||||
|
||||
console.log(`[MessageHandler] 注册消息处理器: 类型=${messageType}, 优先级=${priority}`);
|
||||
MessageHandler.logger.debug(`注册消息处理器: 类型=${messageType}, 优先级=${priority}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +108,7 @@ export class MessageHandler {
|
||||
const index = handlers.findIndex(h => h.handler === handler);
|
||||
if (index !== -1) {
|
||||
handlers.splice(index, 1);
|
||||
console.log(`[MessageHandler] 注销消息处理器: 类型=${messageType}`);
|
||||
MessageHandler.logger.debug(`注销消息处理器: 类型=${messageType}`);
|
||||
}
|
||||
|
||||
// 如果没有处理器了,清理映射
|
||||
@@ -125,7 +127,7 @@ export class MessageHandler {
|
||||
*/
|
||||
public async handleRawMessage(data: Uint8Array, connection?: NetworkConnection): Promise<boolean> {
|
||||
if (data.length < 4) {
|
||||
console.error('[MessageHandler] 消息数据长度不足,至少需要4字节消息类型');
|
||||
MessageHandler.logger.error('消息数据长度不足,至少需要4字节消息类型');
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -136,7 +138,7 @@ export class MessageHandler {
|
||||
// 查找消息类
|
||||
const MessageClass = this._messageClasses.get(messageType);
|
||||
if (!MessageClass) {
|
||||
console.warn(`[MessageHandler] 未知的消息类型: ${messageType}`);
|
||||
MessageHandler.logger.warn(`未知的消息类型: ${messageType}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -147,7 +149,7 @@ export class MessageHandler {
|
||||
|
||||
return await this.handleMessage(message, connection);
|
||||
} catch (error) {
|
||||
console.error(`[MessageHandler] 消息反序列化失败 (类型=${messageType}):`, error);
|
||||
MessageHandler.logger.error(`消息反序列化失败 (类型=${messageType}):`, error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -164,7 +166,7 @@ export class MessageHandler {
|
||||
const handlers = this._handlers.get(messageType);
|
||||
|
||||
if (!handlers || handlers.length === 0) {
|
||||
console.warn(`[MessageHandler] 没有找到消息类型 ${messageType} 的处理器`);
|
||||
MessageHandler.logger.warn(`没有找到消息类型 ${messageType} 的处理器`);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -182,7 +184,7 @@ export class MessageHandler {
|
||||
|
||||
handledCount++;
|
||||
} catch (error) {
|
||||
console.error(`[MessageHandler] 处理器执行错误 (类型=${messageType}, 优先级=${handlerInfo.priority}):`, error);
|
||||
MessageHandler.logger.error(`处理器执行错误 (类型=${messageType}, 优先级=${handlerInfo.priority}):`, error);
|
||||
// 继续执行其他处理器
|
||||
}
|
||||
}
|
||||
@@ -226,7 +228,7 @@ export class MessageHandler {
|
||||
public clear(): void {
|
||||
this._handlers.clear();
|
||||
this._messageClasses.clear();
|
||||
console.log('[MessageHandler] 已清除所有消息处理器');
|
||||
MessageHandler.logger.info('已清除所有消息处理器');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NetworkEnvironment } from './Core/NetworkEnvironment';
|
||||
import { createSyncVarProxy, isSyncVarProxied, destroySyncVarProxy } from './SyncVar/SyncVarProxy';
|
||||
import { SyncVarManager } from './SyncVar/SyncVarManager';
|
||||
import { getSyncVarMetadata } from './SyncVar/SyncVarDecorator';
|
||||
import { createLogger } from '@esengine/ecs-framework';
|
||||
|
||||
/**
|
||||
* 网络组件基类
|
||||
@@ -92,10 +93,12 @@ export abstract class NetworkComponent extends Component implements INetworkSync
|
||||
if (!ComponentRegistry.isRegistered(this.constructor)) {
|
||||
// 如果未注册,自动注册
|
||||
ComponentRegistry.register(this.constructor);
|
||||
console.log(`[NetworkComponent] 自动注册组件类型: ${this.constructor.name}`);
|
||||
const logger = createLogger('NetworkComponent');
|
||||
logger.debug(`自动注册组件类型: ${this.constructor.name}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`[NetworkComponent] 无法注册组件类型 ${this.constructor.name}:`, error);
|
||||
const logger = createLogger('NetworkComponent');
|
||||
logger.warn(`无法注册组件类型 ${this.constructor.name}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +110,8 @@ export abstract class NetworkComponent extends Component implements INetworkSync
|
||||
private initializeSyncVar(): void {
|
||||
const metadata = getSyncVarMetadata(this.constructor);
|
||||
if (metadata.length > 0) {
|
||||
console.log(`[NetworkComponent] ${this.constructor.name} 发现 ${metadata.length} 个SyncVar字段,将启用代理监听`);
|
||||
const logger = createLogger('NetworkComponent');
|
||||
logger.debug(`${this.constructor.name} 发现 ${metadata.length} 个SyncVar字段,将启用代理监听`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
getProtoName
|
||||
} from './ProtobufDecorators';
|
||||
import { SerializedData } from './SerializationTypes';
|
||||
import { createLogger } from '@esengine/ecs-framework';
|
||||
|
||||
/**
|
||||
* 可序列化组件接口
|
||||
@@ -28,6 +29,7 @@ interface SerializableComponent extends Component {
|
||||
export class ProtobufSerializer {
|
||||
private registry: ProtobufRegistry;
|
||||
private static instance: ProtobufSerializer;
|
||||
private static readonly logger = createLogger('ProtobufSerializer');
|
||||
|
||||
/** protobuf.js根对象 */
|
||||
private root: protobuf.Root | null = null;
|
||||
@@ -104,7 +106,7 @@ export class ProtobufSerializer {
|
||||
private async initializeProtobuf(): Promise<void> {
|
||||
try {
|
||||
this.buildProtoDefinitions();
|
||||
console.log('[ProtobufSerializer] Protobuf支持已启用');
|
||||
ProtobufSerializer.logger.info('Protobuf支持已启用');
|
||||
} catch (error) {
|
||||
throw new Error('[ProtobufSerializer] 初始化protobuf失败: ' + error);
|
||||
}
|
||||
@@ -127,7 +129,7 @@ export class ProtobufSerializer {
|
||||
} else {
|
||||
this.buildProtoDefinitions();
|
||||
}
|
||||
console.log('[ProtobufSerializer] Protobuf支持已手动启用');
|
||||
ProtobufSerializer.logger.info('Protobuf支持已手动启用');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,7 +249,7 @@ export class ProtobufSerializer {
|
||||
|
||||
// 记录错误统计
|
||||
if (errors.length > 0) {
|
||||
console.warn(`[ProtobufSerializer] 批量序列化完成,${results.length} 成功,${errors.length} 失败`);
|
||||
ProtobufSerializer.logger.warn(`批量序列化完成,${results.length} 成功,${errors.length} 失败`);
|
||||
}
|
||||
|
||||
return results;
|
||||
@@ -382,7 +384,7 @@ export class ProtobufSerializer {
|
||||
this.componentDataCache.delete(key);
|
||||
}
|
||||
|
||||
console.log(`[ProtobufSerializer] 清理了 ${entries.length} 个缓存项`);
|
||||
ProtobufSerializer.logger.debug(`清理了 ${entries.length} 个缓存项`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -434,7 +436,7 @@ export class ProtobufSerializer {
|
||||
this.messageTypeCache.clear();
|
||||
this.cacheAccessCount.clear();
|
||||
} catch (error) {
|
||||
console.error('[ProtobufSerializer] 构建protobuf定义失败:', error);
|
||||
ProtobufSerializer.logger.error('构建protobuf定义失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,7 +465,7 @@ export class ProtobufSerializer {
|
||||
}
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.warn(`[ProtobufSerializer] 未找到消息类型: ${fullTypeName}`);
|
||||
ProtobufSerializer.logger.warn(`未找到消息类型: ${fullTypeName}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Entity, Component, ComponentType } from '@esengine/ecs-framework';
|
||||
import { Entity, Component, ComponentType, createLogger } from '@esengine/ecs-framework';
|
||||
import { ISnapshotable, SceneSnapshot, EntitySnapshot, ComponentSnapshot, SnapshotConfig } from './ISnapshotable';
|
||||
import { ProtobufSerializer } from '../Serialization/ProtobufSerializer';
|
||||
import { SerializedData } from '../Serialization/SerializationTypes';
|
||||
@@ -103,6 +103,8 @@ class ComponentTypeRegistry implements IComponentFactory {
|
||||
* 使用protobuf序列化
|
||||
*/
|
||||
export class SnapshotManager {
|
||||
private static readonly logger = createLogger('SnapshotManager');
|
||||
|
||||
/** 默认快照配置 */
|
||||
private static readonly DEFAULT_CONFIG: SnapshotConfig = {
|
||||
includeInSnapshot: true,
|
||||
@@ -240,7 +242,7 @@ export class SnapshotManager {
|
||||
|
||||
return entity;
|
||||
} catch (error) {
|
||||
console.error(`[SnapshotManager] 创建实体失败: ${entitySnapshot.name}`, error);
|
||||
SnapshotManager.logger.error(`创建实体失败: ${entitySnapshot.name}`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -253,7 +255,7 @@ export class SnapshotManager {
|
||||
// 尝试获取组件构造函数
|
||||
const componentType = this.getComponentType(componentSnapshot.type);
|
||||
if (!componentType) {
|
||||
console.warn(`[SnapshotManager] 未知组件类型: ${componentSnapshot.type}`);
|
||||
SnapshotManager.logger.warn(`未知组件类型: ${componentSnapshot.type}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -272,7 +274,7 @@ export class SnapshotManager {
|
||||
|
||||
this.protobufSerializer.deserialize(component, serializedData);
|
||||
} catch (error) {
|
||||
console.error(`[SnapshotManager] 创建组件失败: ${componentSnapshot.type}`, error);
|
||||
SnapshotManager.logger.error(`创建组件失败: ${componentSnapshot.type}`, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,7 +284,7 @@ export class SnapshotManager {
|
||||
private getComponentType(typeName: string): NetworkComponentType | null {
|
||||
const componentType = this.componentRegistry.get(typeName);
|
||||
if (!componentType) {
|
||||
console.warn(`[SnapshotManager] 组件类型 ${typeName} 未注册,请先调用 registerComponentType() 注册`);
|
||||
SnapshotManager.logger.warn(`组件类型 ${typeName} 未注册,请先调用 registerComponentType() 注册`);
|
||||
return null;
|
||||
}
|
||||
return componentType;
|
||||
@@ -414,7 +416,7 @@ export class SnapshotManager {
|
||||
public initializeProtobuf(protobufJs: any): void {
|
||||
if (this.protobufSerializer) {
|
||||
this.protobufSerializer.initialize(protobufJs);
|
||||
console.log('[SnapshotManager] Protobuf支持已手动启用');
|
||||
SnapshotManager.logger.info('Protobuf支持已手动启用');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,7 +427,7 @@ export class SnapshotManager {
|
||||
*/
|
||||
public registerComponentType<T extends Component & INetworkSyncable>(constructor: NetworkComponentType<T>): void {
|
||||
this.componentRegistry.autoRegister(constructor);
|
||||
console.log(`[SnapshotManager] 已注册组件类型: ${constructor.name}`);
|
||||
SnapshotManager.logger.debug(`已注册组件类型: ${constructor.name}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -597,7 +599,7 @@ export class SnapshotManager {
|
||||
// 查找现有组件
|
||||
const componentType = this.getComponentType(componentSnapshot.type);
|
||||
if (!componentType) {
|
||||
console.warn(`[SnapshotManager] 组件类型 ${componentSnapshot.type} 未注册,无法恢复`);
|
||||
SnapshotManager.logger.warn(`组件类型 ${componentSnapshot.type} 未注册,无法恢复`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -605,7 +607,7 @@ export class SnapshotManager {
|
||||
|
||||
if (!component) {
|
||||
// 组件不存在,需要创建
|
||||
console.warn(`[SnapshotManager] 组件 ${componentSnapshot.type} 不存在于实体 ${entity.name},无法恢复`);
|
||||
SnapshotManager.logger.warn(`组件 ${componentSnapshot.type} 不存在于实体 ${entity.name},无法恢复`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import 'reflect-metadata';
|
||||
import { createLogger } from '@esengine/ecs-framework';
|
||||
|
||||
const logger = createLogger('SyncVarDecorator');
|
||||
|
||||
/**
|
||||
* SyncVar配置选项
|
||||
@@ -151,7 +154,8 @@ export function getSyncVarMetadataForProperty(target: any, propertyKey: string):
|
||||
* public isReady: boolean = false;
|
||||
*
|
||||
* onNameChanged(oldName: string, newName: string) {
|
||||
* console.log(`Name changed: ${oldName} -> ${newName}`);
|
||||
* const logger = createLogger('PlayerComponent');
|
||||
* logger.info(`Name changed: ${oldName} -> ${newName}`);
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
@@ -165,7 +169,7 @@ export function SyncVar(options: SyncVarOptions = {}): PropertyDecorator {
|
||||
// 获取属性类型
|
||||
const type = Reflect.getMetadata('design:type', target, propertyKey);
|
||||
if (!type) {
|
||||
console.warn(`[SyncVar] 无法获取属性 ${propertyKey} 的类型信息`);
|
||||
logger.warn(`无法获取属性 ${propertyKey} 的类型信息`);
|
||||
}
|
||||
|
||||
// 获取现有元数据
|
||||
@@ -174,7 +178,7 @@ export function SyncVar(options: SyncVarOptions = {}): PropertyDecorator {
|
||||
// 检查是否已经存在
|
||||
const existingIndex = existingMetadata.findIndex(m => m.propertyKey === propertyKey);
|
||||
if (existingIndex !== -1) {
|
||||
console.warn(`[SyncVar] 属性 ${propertyKey} 已经被标记为SyncVar,将覆盖配置`);
|
||||
logger.warn(`属性 ${propertyKey} 已经被标记为SyncVar,将覆盖配置`);
|
||||
existingMetadata[existingIndex].options = options;
|
||||
existingMetadata[existingIndex].type = type;
|
||||
} else {
|
||||
@@ -194,7 +198,7 @@ export function SyncVar(options: SyncVarOptions = {}): PropertyDecorator {
|
||||
// 保存元数据
|
||||
setSyncVarMetadata(target.constructor, existingMetadata);
|
||||
|
||||
console.log(`[SyncVar] 注册同步变量: ${target.constructor.name}.${propertyKey}, 字段编号: ${existingMetadata.find(m => m.propertyKey === propertyKey)?.fieldNumber}`);
|
||||
logger.debug(`注册同步变量: ${target.constructor.name}.${propertyKey}, 字段编号: ${existingMetadata.find(m => m.propertyKey === propertyKey)?.fieldNumber}`);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { createSyncVarProxy } from './SyncVarProxy';
|
||||
import { getSyncVarMetadata } from './SyncVarDecorator';
|
||||
import { INetworkSyncable } from '../types/NetworkTypes';
|
||||
import { createLogger } from '@esengine/ecs-framework';
|
||||
|
||||
/**
|
||||
* SyncVar工厂函数
|
||||
@@ -16,6 +17,8 @@ import { INetworkSyncable } from '../types/NetworkTypes';
|
||||
* @param args - 构造函数参数
|
||||
* @returns 带代理的组件实例
|
||||
*/
|
||||
const logger = createLogger('SyncVarFactory');
|
||||
|
||||
export function createNetworkComponent<T extends INetworkSyncable>(
|
||||
ComponentClass: new (...args: any[]) => T,
|
||||
...args: any[]
|
||||
@@ -36,7 +39,7 @@ export function createNetworkComponent<T extends INetworkSyncable>(
|
||||
debugLog: false // 可以根据需要启用调试
|
||||
});
|
||||
|
||||
console.log(`[SyncVarFactory] 为 ${ComponentClass.name} 创建了SyncVar代理,包含 ${metadata.length} 个同步字段`);
|
||||
logger.debug(`为 ${ComponentClass.name} 创建了SyncVar代理,包含 ${metadata.length} 个同步字段`);
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
NetworkComponentType,
|
||||
TypeGuards
|
||||
} from '../types/NetworkTypes';
|
||||
import { createLogger } from '@esengine/ecs-framework';
|
||||
|
||||
/**
|
||||
* SyncVar变化记录
|
||||
@@ -83,6 +84,7 @@ export interface SyncVarSyncData {
|
||||
*/
|
||||
export class SyncVarManager {
|
||||
private static _instance: SyncVarManager | null = null;
|
||||
private static readonly logger = createLogger('SyncVarManager');
|
||||
|
||||
/**
|
||||
* 组件实例的SyncVar变化监听器
|
||||
@@ -133,7 +135,7 @@ export class SyncVarManager {
|
||||
}
|
||||
|
||||
if (validationErrors.length > 0) {
|
||||
console.error(`[SyncVarManager] 组件 ${component.constructor.name} 的SyncVar配置错误:`, validationErrors);
|
||||
SyncVarManager.logger.error(`组件 ${component.constructor.name} 的SyncVar配置错误:`, validationErrors);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -141,7 +143,7 @@ export class SyncVarManager {
|
||||
this._componentChanges.set(componentId, []);
|
||||
this._lastSyncTimes.set(componentId, new Map());
|
||||
|
||||
console.log(`[SyncVarManager] 初始化组件 ${component.constructor.name} 的SyncVar系统,共 ${metadata.length} 个同步变量`);
|
||||
SyncVarManager.logger.info(`初始化组件 ${component.constructor.name} 的SyncVar系统,共 ${metadata.length} 个同步变量`);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -174,13 +176,13 @@ export class SyncVarManager {
|
||||
const metadata = getSyncVarMetadataForProperty(component, propertyKey);
|
||||
|
||||
if (!metadata) {
|
||||
console.warn(`[SyncVarManager] 属性 ${propertyKey} 不是SyncVar`);
|
||||
SyncVarManager.logger.warn(`属性 ${propertyKey} 不是SyncVar`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查值是否真的发生了变化
|
||||
if (!TypeGuards.isSyncVarValue(oldValue) || !TypeGuards.isSyncVarValue(newValue)) {
|
||||
console.warn(`[SyncVarManager] 无效的SyncVar值类型: ${typeof oldValue}, ${typeof newValue}`);
|
||||
SyncVarManager.logger.warn(`无效的SyncVar值类型: ${typeof oldValue}, ${typeof newValue}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -195,14 +197,14 @@ export class SyncVarManager {
|
||||
|
||||
if (metadata.options.throttleMs && metadata.options.throttleMs > 0) {
|
||||
if (now - lastSyncTime < metadata.options.throttleMs) {
|
||||
console.log(`[SyncVarManager] 属性 ${propertyKey} 变化过于频繁,跳过同步`);
|
||||
SyncVarManager.logger.debug(`属性 ${propertyKey} 变化过于频繁,跳过同步`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查权限
|
||||
if (metadata.options.authorityOnly && !this.hasAuthority(component)) {
|
||||
console.warn(`[SyncVarManager] 属性 ${propertyKey} 需要权限才能修改,但当前没有权限`);
|
||||
SyncVarManager.logger.warn(`属性 ${propertyKey} 需要权限才能修改,但当前没有权限`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -229,7 +231,7 @@ export class SyncVarManager {
|
||||
lastSyncTimes.set(propertyKey, now);
|
||||
}
|
||||
|
||||
console.log(`[SyncVarManager] 记录变化: ${component.constructor.name}.${propertyKey} = ${newValue} (was ${oldValue})`);
|
||||
SyncVarManager.logger.debug(`记录变化: ${component.constructor.name}.${propertyKey} = ${newValue} (was ${oldValue})`);
|
||||
|
||||
// 触发hook回调
|
||||
this.triggerHook(component, metadata, oldValue, newValue);
|
||||
@@ -294,7 +296,7 @@ export class SyncVarManager {
|
||||
data: serializedData
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`[SyncVarManager] 序列化失败 ${change.propertyKey}:`, error);
|
||||
SyncVarManager.logger.error(`序列化失败 ${change.propertyKey}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,7 +324,7 @@ export class SyncVarManager {
|
||||
for (const update of syncData.fieldUpdates) {
|
||||
const meta = metadataMap.get(update.fieldNumber);
|
||||
if (!meta) {
|
||||
console.warn(`[SyncVarManager] 未找到字段编号 ${update.fieldNumber} 的元数据`);
|
||||
SyncVarManager.logger.warn(`未找到字段编号 ${update.fieldNumber} 的元数据`);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -336,9 +338,9 @@ export class SyncVarManager {
|
||||
// 触发hook回调
|
||||
this.triggerHook(component, meta, oldValue, newValue);
|
||||
|
||||
console.log(`[SyncVarManager] 应用同步: ${component.constructor.name}.${meta.propertyKey} = ${newValue}`);
|
||||
SyncVarManager.logger.debug(`应用同步: ${component.constructor.name}.${meta.propertyKey} = ${newValue}`);
|
||||
} catch (error) {
|
||||
console.error(`[SyncVarManager] 反序列化失败 ${meta.propertyKey}:`, error);
|
||||
SyncVarManager.logger.error(`反序列化失败 ${meta.propertyKey}:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -421,7 +423,7 @@ export class SyncVarManager {
|
||||
private shouldSync(component: any, metadata: SyncVarMetadata): boolean {
|
||||
// 权限检查:权威字段只有在有权限时才同步
|
||||
if (metadata.options.authorityOnly && !this.hasAuthority(component)) {
|
||||
console.log(`[SyncVarManager] 字段 ${metadata.propertyKey} 是权威字段,但当前没有权限,跳过同步`);
|
||||
SyncVarManager.logger.debug(`字段 ${metadata.propertyKey} 是权威字段,但当前没有权限,跳过同步`);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -457,7 +459,7 @@ export class SyncVarManager {
|
||||
try {
|
||||
hookFunction.call(component, oldValue, newValue);
|
||||
} catch (error) {
|
||||
console.error(`[SyncVarManager] Hook函数执行失败 ${metadata.options.hook}:`, error);
|
||||
SyncVarManager.logger.error(`Hook函数执行失败 ${metadata.options.hook}:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -641,7 +643,7 @@ export class SyncVarManager {
|
||||
syncSequence
|
||||
);
|
||||
|
||||
console.log(`[SyncVarManager] 创建SyncVar更新消息: ${component.constructor.name}, ${fieldUpdates.length} 个字段`);
|
||||
SyncVarManager.logger.debug(`创建SyncVar更新消息: ${component.constructor.name}, ${fieldUpdates.length} 个字段`);
|
||||
return message;
|
||||
}
|
||||
|
||||
@@ -653,7 +655,7 @@ export class SyncVarManager {
|
||||
*/
|
||||
public applySyncVarUpdateMessage(component: any, message: SyncVarUpdateMessage): void {
|
||||
if (message.componentType !== component.constructor.name) {
|
||||
console.warn(`[SyncVarManager] 组件类型不匹配: 期望 ${component.constructor.name}, 收到 ${message.componentType}`);
|
||||
SyncVarManager.logger.warn(`组件类型不匹配: 期望 ${component.constructor.name}, 收到 ${message.componentType}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -663,7 +665,7 @@ export class SyncVarManager {
|
||||
for (const fieldUpdate of message.fieldUpdates) {
|
||||
const meta = metadataMap.get(fieldUpdate.fieldNumber);
|
||||
if (!meta) {
|
||||
console.warn(`[SyncVarManager] 未找到字段编号 ${fieldUpdate.fieldNumber} 的元数据`);
|
||||
SyncVarManager.logger.warn(`未找到字段编号 ${fieldUpdate.fieldNumber} 的元数据`);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -672,7 +674,7 @@ export class SyncVarManager {
|
||||
if (fieldUpdate.authorityOnly && NetworkEnvironment.isClient && !this.hasAuthority(component)) {
|
||||
// 如果这是来自服务端的更新,则允许应用
|
||||
// 这里简单实现:客户端接受所有权威字段的更新
|
||||
console.log(`[SyncVarManager] 客户端接受权威字段更新: ${fieldUpdate.propertyKey}`);
|
||||
SyncVarManager.logger.debug(`客户端接受权威字段更新: ${fieldUpdate.propertyKey}`);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -684,9 +686,9 @@ export class SyncVarManager {
|
||||
// 触发hook回调
|
||||
this.triggerHook(component, meta, oldValue, fieldUpdate.newValue);
|
||||
|
||||
console.log(`[SyncVarManager] 应用SyncVar消息更新: ${component.constructor.name}.${meta.propertyKey} = ${fieldUpdate.newValue}`);
|
||||
SyncVarManager.logger.debug(`应用SyncVar消息更新: ${component.constructor.name}.${meta.propertyKey} = ${fieldUpdate.newValue}`);
|
||||
} catch (error) {
|
||||
console.error(`[SyncVarManager] 应用SyncVar更新失败 ${meta.propertyKey}:`, error);
|
||||
SyncVarManager.logger.error(`应用SyncVar更新失败 ${meta.propertyKey}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { NetworkConnection } from '../Core/NetworkConnection';
|
||||
import { NetworkIdentityRegistry } from '../Core/NetworkIdentity';
|
||||
import { SyncVarManager } from './SyncVarManager';
|
||||
import { NetworkEnvironment } from '../Core/NetworkEnvironment';
|
||||
import { ComponentRegistry } from '@esengine/ecs-framework';
|
||||
import { ComponentRegistry, createLogger } from '@esengine/ecs-framework';
|
||||
import { NetworkManager } from '../Core/NetworkManager';
|
||||
|
||||
/**
|
||||
@@ -13,6 +13,7 @@ import { NetworkManager } from '../Core/NetworkManager';
|
||||
* 处理接收到的SyncVar更新消息,自动查找目标网络对象并应用更新
|
||||
*/
|
||||
export class SyncVarMessageHandler implements IMessageHandler<SyncVarUpdateMessage> {
|
||||
private static readonly logger = createLogger('SyncVarMessageHandler');
|
||||
private _processedMessages: Set<string> = new Set();
|
||||
private _maxProcessedCache: number = 1000;
|
||||
|
||||
@@ -27,7 +28,7 @@ export class SyncVarMessageHandler implements IMessageHandler<SyncVarUpdateMessa
|
||||
// 生成消息唯一标识符用于去重
|
||||
const messageKey = this.generateMessageKey(message);
|
||||
if (this._processedMessages.has(messageKey)) {
|
||||
console.log(`[SyncVarMessageHandler] 跳过重复消息: ${messageKey}`);
|
||||
SyncVarMessageHandler.logger.debug(` 跳过重复消息: ${messageKey}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -36,27 +37,27 @@ export class SyncVarMessageHandler implements IMessageHandler<SyncVarUpdateMessa
|
||||
|
||||
// 验证消息基本有效性
|
||||
if (!this.validateMessage(message)) {
|
||||
console.error('[SyncVarMessageHandler] 消息验证失败');
|
||||
SyncVarMessageHandler.logger.error(' 消息验证失败');
|
||||
return;
|
||||
}
|
||||
|
||||
// 查找目标网络对象
|
||||
const targetIdentity = NetworkIdentityRegistry.Instance.find(message.networkId);
|
||||
if (!targetIdentity) {
|
||||
console.warn(`[SyncVarMessageHandler] 未找到网络对象: ${message.networkId}`);
|
||||
SyncVarMessageHandler.logger.warn(` 未找到网络对象: ${message.networkId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 权限检查
|
||||
if (!this.checkAuthority(message, connection, targetIdentity)) {
|
||||
console.warn(`[SyncVarMessageHandler] 权限检查失败: ${message.networkId}`);
|
||||
SyncVarMessageHandler.logger.warn(` 权限检查失败: ${message.networkId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 查找目标组件
|
||||
const targetComponent = this.findTargetComponent(targetIdentity, message.componentType);
|
||||
if (!targetComponent) {
|
||||
console.warn(`[SyncVarMessageHandler] 未找到目标组件: ${message.componentType} on ${message.networkId}`);
|
||||
SyncVarMessageHandler.logger.warn(` 未找到目标组件: ${message.componentType} on ${message.networkId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -74,10 +75,10 @@ export class SyncVarMessageHandler implements IMessageHandler<SyncVarUpdateMessa
|
||||
await this.forwardToOtherClients(message, connection);
|
||||
}
|
||||
|
||||
console.log(`[SyncVarMessageHandler] 成功处理SyncVar更新: ${message.networkId}.${message.componentType}, ${message.fieldUpdates.length}个字段`);
|
||||
SyncVarMessageHandler.logger.debug(` 成功处理SyncVar更新: ${message.networkId}.${message.componentType}, ${message.fieldUpdates.length}个字段`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('[SyncVarMessageHandler] 处理SyncVar更新失败:', error);
|
||||
SyncVarMessageHandler.logger.error(' 处理SyncVar更新失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,12 +107,12 @@ export class SyncVarMessageHandler implements IMessageHandler<SyncVarUpdateMessa
|
||||
*/
|
||||
private validateMessage(message: SyncVarUpdateMessage): boolean {
|
||||
if (!message.networkId || !message.componentType) {
|
||||
console.error('[SyncVarMessageHandler] 消息缺少必要字段');
|
||||
SyncVarMessageHandler.logger.error(' 消息缺少必要字段');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!message.fieldUpdates || message.fieldUpdates.length === 0) {
|
||||
console.error('[SyncVarMessageHandler] 消息没有字段更新');
|
||||
SyncVarMessageHandler.logger.error(' 消息没有字段更新');
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -119,7 +120,7 @@ export class SyncVarMessageHandler implements IMessageHandler<SyncVarUpdateMessa
|
||||
const now = Date.now();
|
||||
const maxAge = 60000; // 1分钟
|
||||
if (message.timestamp > now + 5000 || message.timestamp < now - maxAge) {
|
||||
console.warn(`[SyncVarMessageHandler] 消息时间戳异常: ${message.timestamp}, 当前: ${now}`);
|
||||
SyncVarMessageHandler.logger.warn(` 消息时间戳异常: ${message.timestamp}, 当前: ${now}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -143,7 +144,7 @@ export class SyncVarMessageHandler implements IMessageHandler<SyncVarUpdateMessa
|
||||
// 非拥有者只能发送非权威字段更新
|
||||
const hasAuthorityOnlyUpdates = message.fieldUpdates.some(update => update.authorityOnly);
|
||||
if (hasAuthorityOnlyUpdates) {
|
||||
console.warn(`[SyncVarMessageHandler] 非拥有者 ${connection.connectionId} 尝试修改权威字段`);
|
||||
SyncVarMessageHandler.logger.warn(` 非拥有者 ${connection.connectionId} 尝试修改权威字段`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -165,7 +166,7 @@ export class SyncVarMessageHandler implements IMessageHandler<SyncVarUpdateMessa
|
||||
private findTargetComponent(targetIdentity: any, componentType: string): any {
|
||||
const entity = targetIdentity.entity;
|
||||
if (!entity || typeof entity.getComponent !== 'function') {
|
||||
console.error('[SyncVarMessageHandler] NetworkIdentity缺少有效的Entity引用');
|
||||
SyncVarMessageHandler.logger.error(' NetworkIdentity缺少有效的Entity引用');
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -179,13 +180,13 @@ export class SyncVarMessageHandler implements IMessageHandler<SyncVarUpdateMessa
|
||||
// 使用Entity的getComponent方法查找组件
|
||||
const component = entity.getComponent(ComponentClass);
|
||||
if (!component) {
|
||||
console.warn(`[SyncVarMessageHandler] Entity ${entity.id} 上未找到组件: ${componentType}`);
|
||||
SyncVarMessageHandler.logger.warn(` Entity ${entity.id} 上未找到组件: ${componentType}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
return component;
|
||||
} catch (error) {
|
||||
console.error(`[SyncVarMessageHandler] 查找组件失败: ${componentType}`, error);
|
||||
SyncVarMessageHandler.logger.error(`查找组件失败: ${componentType}`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -197,7 +198,7 @@ export class SyncVarMessageHandler implements IMessageHandler<SyncVarUpdateMessa
|
||||
const componentClass = ComponentRegistry.getComponentType(componentType);
|
||||
|
||||
if (!componentClass) {
|
||||
console.warn(`[SyncVarMessageHandler] 未找到组件类型: ${componentType}`);
|
||||
SyncVarMessageHandler.logger.warn(` 未找到组件类型: ${componentType}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -213,7 +214,7 @@ export class SyncVarMessageHandler implements IMessageHandler<SyncVarUpdateMessa
|
||||
try {
|
||||
syncVarManager.applySyncVarUpdateMessage(targetComponent, message);
|
||||
} catch (error) {
|
||||
console.error('[SyncVarMessageHandler] 应用SyncVar更新失败:', error);
|
||||
SyncVarMessageHandler.logger.error(' 应用SyncVar更新失败:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -230,7 +231,7 @@ export class SyncVarMessageHandler implements IMessageHandler<SyncVarUpdateMessa
|
||||
const server = NetworkManager.GetServer();
|
||||
|
||||
if (!server || !server.isRunning) {
|
||||
console.warn('[SyncVarMessageHandler] NetworkServer未运行,无法转发消息');
|
||||
SyncVarMessageHandler.logger.warn(' NetworkServer未运行,无法转发消息');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -238,12 +239,12 @@ export class SyncVarMessageHandler implements IMessageHandler<SyncVarUpdateMessa
|
||||
const successCount = await server.broadcastSyncVarMessageExcept(message, senderConnection.connectionId);
|
||||
|
||||
if (successCount > 0) {
|
||||
console.log(`[SyncVarMessageHandler] 成功转发消息给 ${successCount} 个其他客户端 (发送者: ${senderConnection.connectionId})`);
|
||||
SyncVarMessageHandler.logger.debug(` 成功转发消息给 ${successCount} 个其他客户端 (发送者: ${senderConnection.connectionId})`);
|
||||
} else {
|
||||
console.log(`[SyncVarMessageHandler] 没有其他客户端需要转发消息 (发送者: ${senderConnection.connectionId})`);
|
||||
SyncVarMessageHandler.logger.debug(` 没有其他客户端需要转发消息 (发送者: ${senderConnection.connectionId})`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[SyncVarMessageHandler] 转发消息失败 (发送者: ${senderConnection.connectionId}):`, error);
|
||||
SyncVarMessageHandler.logger.error(`转发消息失败 (发送者: ${senderConnection.connectionId}):`, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,7 +268,7 @@ export class SyncVarMessageHandler implements IMessageHandler<SyncVarUpdateMessa
|
||||
*/
|
||||
public clearProcessedCache(): void {
|
||||
this._processedMessages.clear();
|
||||
console.log('[SyncVarMessageHandler] 已清理消息处理缓存');
|
||||
SyncVarMessageHandler.logger.info('已清理消息处理缓存');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { SyncVarUpdateMessage, SyncVarFieldUpdate } from '../Messaging/MessageTypes';
|
||||
import { createLogger } from '@esengine/ecs-framework';
|
||||
|
||||
/**
|
||||
* SyncVar优化配置
|
||||
@@ -325,6 +326,7 @@ export class SyncVarDistanceCuller {
|
||||
* SyncVar性能优化器
|
||||
*/
|
||||
export class SyncVarOptimizer {
|
||||
private static readonly logger = createLogger('SyncVarOptimizer');
|
||||
private _config: SyncVarOptimizationConfig;
|
||||
private _messageMerger: SyncVarMessageMerger;
|
||||
private _rateLimiter: SyncVarRateLimiter;
|
||||
@@ -376,7 +378,7 @@ export class SyncVarOptimizer {
|
||||
// 频率限制检查
|
||||
if (!this._rateLimiter.canSend(message.networkId)) {
|
||||
this._stats.messagesBlocked++;
|
||||
console.log(`[SyncVarOptimizer] 消息被频率限制阻止: ${message.networkId}`);
|
||||
SyncVarOptimizer.logger.debug(` 消息被频率限制阻止: ${message.networkId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -385,7 +387,7 @@ export class SyncVarOptimizer {
|
||||
|
||||
if (validObservers.length === 0 && targetObservers.length > 0) {
|
||||
this._stats.messagesBlocked++;
|
||||
console.log(`[SyncVarOptimizer] 消息被距离剔除阻止: ${message.networkId}`);
|
||||
SyncVarOptimizer.logger.debug(` 消息被距离剔除阻止: ${message.networkId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -393,7 +395,7 @@ export class SyncVarOptimizer {
|
||||
this._messageMerger.addMessage(message, (mergedMessage) => {
|
||||
if (mergedMessage !== message) {
|
||||
this._stats.messagesMerged++;
|
||||
console.log(`[SyncVarOptimizer] 消息已合并: ${message.networkId}`);
|
||||
SyncVarOptimizer.logger.debug(` 消息已合并: ${message.networkId}`);
|
||||
}
|
||||
|
||||
onOptimized([mergedMessage], validObservers);
|
||||
@@ -412,7 +414,7 @@ export class SyncVarOptimizer {
|
||||
*/
|
||||
public configure(config: Partial<SyncVarOptimizationConfig>): void {
|
||||
this._config = { ...this._config, ...config };
|
||||
console.log('[SyncVarOptimizer] 配置已更新:', this._config);
|
||||
SyncVarOptimizer.logger.info(' 配置已更新:', this._config);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { getSyncVarMetadata, isSyncVar } from './SyncVarDecorator';
|
||||
import { SyncVarManager } from './SyncVarManager';
|
||||
import { INetworkSyncable, SyncVarValue, TypeGuards } from '../types/NetworkTypes';
|
||||
import { createLogger } from '@esengine/ecs-framework';
|
||||
|
||||
/**
|
||||
* SyncVar代理配置
|
||||
@@ -36,9 +37,11 @@ export function createSyncVarProxy<T extends INetworkSyncable>(
|
||||
|
||||
// 检查目标是否有SyncVar
|
||||
const metadata = getSyncVarMetadata(target.constructor);
|
||||
const logger = createLogger('SyncVarProxy');
|
||||
|
||||
if (metadata.length === 0) {
|
||||
if (debugLog) {
|
||||
console.log(`[SyncVarProxy] 对象 ${target.constructor.name} 没有SyncVar,返回原对象`);
|
||||
logger.debug(`对象 ${target.constructor.name} 没有SyncVar,返回原对象`);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
@@ -47,7 +50,7 @@ export function createSyncVarProxy<T extends INetworkSyncable>(
|
||||
syncVarManager.initializeComponent(target);
|
||||
|
||||
if (debugLog) {
|
||||
console.log(`[SyncVarProxy] 为 ${target.constructor.name} 创建代理,SyncVar字段:`,
|
||||
logger.debug(`为 ${target.constructor.name} 创建代理,SyncVar字段:`,
|
||||
metadata.map(m => m.propertyKey));
|
||||
}
|
||||
|
||||
@@ -81,7 +84,7 @@ export function createSyncVarProxy<T extends INetworkSyncable>(
|
||||
const value = Reflect.get(obj, prop);
|
||||
|
||||
if (debugLog && isSyncVar(obj, propertyKey)) {
|
||||
console.log(`[SyncVarProxy] GET ${obj.constructor.name}.${propertyKey} = ${value}`);
|
||||
logger.debug(`GET ${obj.constructor.name}.${propertyKey} = ${value}`);
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -117,7 +120,7 @@ export function createSyncVarProxy<T extends INetworkSyncable>(
|
||||
const oldValue = originalValues.get(propertyKey);
|
||||
|
||||
if (debugLog) {
|
||||
console.log(`[SyncVarProxy] SET ${obj.constructor.name}.${propertyKey} = ${newValue} (was ${oldValue})`);
|
||||
logger.debug(`SET ${obj.constructor.name}.${propertyKey} = ${newValue} (was ${oldValue})`);
|
||||
}
|
||||
|
||||
// 设置新值
|
||||
@@ -133,7 +136,7 @@ export function createSyncVarProxy<T extends INetworkSyncable>(
|
||||
syncVarManager.recordChange(obj, propertyKey, oldValue, newValue);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[SyncVarProxy] 记录SyncVar变化失败:`, error);
|
||||
logger.error(`记录SyncVar变化失败:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +150,7 @@ export function createSyncVarProxy<T extends INetworkSyncable>(
|
||||
const propertyKey = prop as string;
|
||||
|
||||
if (typeof prop === 'string' && isSyncVar(obj, propertyKey)) {
|
||||
console.warn(`[SyncVarProxy] 尝试删除SyncVar属性 ${propertyKey},这可能会导致同步问题`);
|
||||
logger.warn(`尝试删除SyncVar属性 ${propertyKey},这可能会导致同步问题`);
|
||||
}
|
||||
|
||||
return Reflect.deleteProperty(obj, prop);
|
||||
@@ -180,7 +183,7 @@ export function createSyncVarProxy<T extends INetworkSyncable>(
|
||||
(proxy as T & { _syncVarProxied: boolean; _syncVarOptions: SyncVarProxyOptions })._syncVarOptions = options;
|
||||
|
||||
if (debugLog) {
|
||||
console.log(`[SyncVarProxy] ${target.constructor.name} 代理创建完成`);
|
||||
logger.debug(`${target.constructor.name} 代理创建完成`);
|
||||
}
|
||||
|
||||
return proxy;
|
||||
@@ -229,7 +232,8 @@ export function destroySyncVarProxy(proxy: INetworkSyncable & { _syncVarProxied?
|
||||
proxy._syncVarProxied = false;
|
||||
proxy._syncVarDestroyed = true;
|
||||
|
||||
console.log(`[SyncVarProxy] ${proxy.constructor?.name || 'Unknown'} 代理已销毁`);
|
||||
const logger = createLogger('SyncVarProxy');
|
||||
logger.debug(`${proxy.constructor?.name || 'Unknown'} 代理已销毁`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,7 @@ import { SyncVarManager } from './SyncVarManager';
|
||||
import { NetworkIdentityRegistry, NetworkIdentity } from '../Core/NetworkIdentity';
|
||||
import { SyncVarUpdateMessage } from '../Messaging/MessageTypes';
|
||||
import { NetworkEnvironment } from '../Core/NetworkEnvironment';
|
||||
import { ComponentRegistry } from '@esengine/ecs-framework';
|
||||
import { ComponentRegistry, createLogger } from '@esengine/ecs-framework';
|
||||
import { NetworkComponent } from '../NetworkComponent';
|
||||
|
||||
/**
|
||||
@@ -69,6 +69,7 @@ export class DefaultSyncPriorityCalculator implements ISyncPriorityCalculator {
|
||||
* 支持批处理、优先级排序和性能优化
|
||||
*/
|
||||
export class SyncVarSyncScheduler {
|
||||
private static readonly logger = createLogger('SyncVarSyncScheduler');
|
||||
private static _instance: SyncVarSyncScheduler | null = null;
|
||||
|
||||
private _config: SyncVarSyncConfig;
|
||||
@@ -130,7 +131,7 @@ export class SyncVarSyncScheduler {
|
||||
this.start();
|
||||
}
|
||||
|
||||
console.log('[SyncVarSyncScheduler] 调度器配置已更新:', this._config);
|
||||
SyncVarSyncScheduler.logger.debug('调度器配置已更新:', this._config);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,7 +141,7 @@ export class SyncVarSyncScheduler {
|
||||
*/
|
||||
public setPriorityCalculator(calculator: ISyncPriorityCalculator): void {
|
||||
this._priorityCalculator = calculator;
|
||||
console.log('[SyncVarSyncScheduler] 优先级计算器已更新');
|
||||
SyncVarSyncScheduler.logger.debug('优先级计算器已更新');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,7 +151,7 @@ export class SyncVarSyncScheduler {
|
||||
*/
|
||||
public setMessageSendCallback(callback: (message: SyncVarUpdateMessage) => Promise<void>): void {
|
||||
this._messageSendCallback = callback;
|
||||
console.log('[SyncVarSyncScheduler] 消息发送回调已设置');
|
||||
SyncVarSyncScheduler.logger.debug('消息发送回调已设置');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,7 +159,7 @@ export class SyncVarSyncScheduler {
|
||||
*/
|
||||
public start(): void {
|
||||
if (this._isRunning) {
|
||||
console.warn('[SyncVarSyncScheduler] 调度器已经在运行');
|
||||
SyncVarSyncScheduler.logger.warn('调度器已经在运行');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -170,7 +171,7 @@ export class SyncVarSyncScheduler {
|
||||
this.performSyncCycle();
|
||||
}, this._config.syncInterval);
|
||||
|
||||
console.log(`[SyncVarSyncScheduler] 调度器已启动,同步间隔: ${this._config.syncInterval}ms`);
|
||||
SyncVarSyncScheduler.logger.info(`调度器已启动,同步间隔: ${this._config.syncInterval}ms`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,7 +189,7 @@ export class SyncVarSyncScheduler {
|
||||
this._syncTimer = null;
|
||||
}
|
||||
|
||||
console.log('[SyncVarSyncScheduler] 调度器已停止');
|
||||
SyncVarSyncScheduler.logger.info('调度器已停止');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -235,7 +236,7 @@ export class SyncVarSyncScheduler {
|
||||
|
||||
} catch (error) {
|
||||
this._stats.errors++;
|
||||
console.error('[SyncVarSyncScheduler] 同步周期执行失败:', error);
|
||||
SyncVarSyncScheduler.logger.error('同步周期执行失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,7 +286,7 @@ export class SyncVarSyncScheduler {
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[SyncVarSyncScheduler] 处理网络对象失败: ${identity.networkId}`, error);
|
||||
SyncVarSyncScheduler.logger.error(`处理网络对象失败: ${identity.networkId}`, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,7 +299,7 @@ export class SyncVarSyncScheduler {
|
||||
private getNetworkComponents(identity: NetworkIdentity): NetworkComponent[] {
|
||||
const entity = identity.entity;
|
||||
if (!entity) {
|
||||
console.warn(`[SyncVarSyncScheduler] NetworkIdentity ${identity.networkId} 缺少Entity引用`);
|
||||
SyncVarSyncScheduler.logger.warn(`NetworkIdentity ${identity.networkId} 缺少Entity引用`);
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -318,7 +319,7 @@ export class SyncVarSyncScheduler {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[SyncVarSyncScheduler] 获取网络组件失败 (${identity.networkId}):`, error);
|
||||
SyncVarSyncScheduler.logger.error(`获取网络组件失败 (${identity.networkId}):`, error);
|
||||
}
|
||||
|
||||
return networkComponents;
|
||||
@@ -383,7 +384,7 @@ export class SyncVarSyncScheduler {
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(`[SyncVarSyncScheduler] 处理同步候选对象失败: ${candidate.identity.networkId}`, error);
|
||||
SyncVarSyncScheduler.logger.error(`处理同步候选对象失败: ${candidate.identity.networkId}`, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -398,7 +399,7 @@ export class SyncVarSyncScheduler {
|
||||
*/
|
||||
private async sendMessageBatch(messages: SyncVarUpdateMessage[]): Promise<void> {
|
||||
if (!this._messageSendCallback) {
|
||||
console.warn('[SyncVarSyncScheduler] 没有设置消息发送回调,消息被丢弃');
|
||||
SyncVarSyncScheduler.logger.warn('没有设置消息发送回调,消息被丢弃');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -407,7 +408,7 @@ export class SyncVarSyncScheduler {
|
||||
await this._messageSendCallback(message);
|
||||
this._stats.totalMessagesSent++;
|
||||
} catch (error) {
|
||||
console.error('[SyncVarSyncScheduler] 发送SyncVar消息失败:', error);
|
||||
SyncVarSyncScheduler.logger.error('发送SyncVar消息失败:', error);
|
||||
this._stats.errors++;
|
||||
}
|
||||
}
|
||||
@@ -458,7 +459,7 @@ export class SyncVarSyncScheduler {
|
||||
lastCycleTime: 0,
|
||||
errors: 0
|
||||
};
|
||||
console.log('[SyncVarSyncScheduler] 统计信息已重置');
|
||||
SyncVarSyncScheduler.logger.debug('统计信息已重置');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
52
packages/network/src/types/global.d.ts
vendored
52
packages/network/src/types/global.d.ts
vendored
@@ -1,49 +1,11 @@
|
||||
/**
|
||||
* 全局宏定义类型声明
|
||||
*
|
||||
* 这些宏变量由构建工具在编译时定义,用于条件编译
|
||||
* 支持在客户端构建时移除服务端代码,在服务端构建时移除客户端代码
|
||||
* 网络库编译时宏定义
|
||||
* 这些宏在构建时会被具体的布尔值替换,用于实现客户端/服务端代码的编译时过滤
|
||||
*/
|
||||
|
||||
/**
|
||||
* 客户端构建标志
|
||||
*
|
||||
* 当构建客户端版本时为true,服务端版本时为false
|
||||
* 使用示例:
|
||||
* ```typescript
|
||||
* if (__CLIENT__) {
|
||||
* // 只在客户端构建中包含的代码
|
||||
* this.renderUI();
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
declare const __CLIENT__: boolean;
|
||||
declare global {
|
||||
const __CLIENT__: boolean;
|
||||
const __SERVER__: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务端构建标志
|
||||
*
|
||||
* 当构建服务端版本时为true,客户端版本时为false
|
||||
* 使用示例:
|
||||
* ```typescript
|
||||
* if (__SERVER__) {
|
||||
* // 只在服务端构建中包含的代码
|
||||
* this.validateInput();
|
||||
* this.saveToDatabase();
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
declare const __SERVER__: boolean;
|
||||
|
||||
/**
|
||||
* 开发环境标志(可选)
|
||||
*
|
||||
* 当在开发环境时为true,生产环境时为false
|
||||
*/
|
||||
declare const __DEV__: boolean;
|
||||
|
||||
/**
|
||||
* 生产环境标志(可选)
|
||||
*
|
||||
* 当在生产环境时为true,开发环境时为false
|
||||
*/
|
||||
declare const __PROD__: boolean;
|
||||
export {};
|
||||
@@ -30,11 +30,20 @@
|
||||
"downlevelIteration": true,
|
||||
"isolatedModules": false,
|
||||
"allowJs": true,
|
||||
"resolveJsonModule": true
|
||||
"resolveJsonModule": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@esengine/ecs-framework": ["../core/src"],
|
||||
"@esengine/ecs-framework/*": ["../core/src/*"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
],
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"./src/types"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"bin",
|
||||
|
||||
Reference in New Issue
Block a user