Merge remote-tracking branch 'origin/master' into issue-94-响应式查询(Reactive_Query_System)/_Event-driven_Query

This commit is contained in:
YHH
2025-10-13 23:29:56 +08:00
16 changed files with 360 additions and 213 deletions

View File

@@ -13,7 +13,6 @@ import { ServiceContainer } from './Core/ServiceContainer';
import { PluginManager } from './Core/PluginManager';
import { IPlugin } from './Core/Plugin';
import { WorldManager } from './ECS/WorldManager';
import { registerInjectable } from './Core/DI';
/**
* 游戏引擎核心类
@@ -178,14 +177,9 @@ export class Core {
this._poolManager = new PoolManager();
this._serviceContainer.registerInstance(PoolManager, this._poolManager);
// 使用依赖注入自动注册WorldManager和SceneManager
// WorldManager会在构造时创建默认World
registerInjectable(this._serviceContainer, WorldManager);
this._worldManager = this._serviceContainer.resolve(WorldManager);
// SceneManager会通过@Inject自动获取WorldManager
registerInjectable(this._serviceContainer, SceneManager);
this._sceneManager = this._serviceContainer.resolve(SceneManager);
// 初始化场景管理器
this._sceneManager = new SceneManager();
this._serviceContainer.registerInstance(SceneManager, this._sceneManager);
// 设置场景切换回调,通知调试管理器
this._sceneManager.setSceneChangedCallback(() => {
@@ -194,6 +188,10 @@ export class Core {
}
});
// 初始化World管理器
this._worldManager = new WorldManager();
this._serviceContainer.registerInstance(WorldManager, this._worldManager);
// 初始化插件管理器
this._pluginManager = new PluginManager();
this._pluginManager.initialize(this, this._serviceContainer);
@@ -647,7 +645,7 @@ export class Core {
this._performanceMonitor.updateFPS(Time.deltaTime);
}
// 更新所有@Updatable服务(包括TimerManager, WorldManager, SceneManager等)
// 更新所有可更新的服务
const servicesStartTime = this._performanceMonitor.startMonitoring('Services.update');
this._serviceContainer.updateAll(deltaTime);
this._performanceMonitor.endMonitoring('Services.update', servicesStartTime, this._serviceContainer.getUpdatableCount());
@@ -655,6 +653,12 @@ export class Core {
// 更新对象池管理器
this._poolManager.update();
// 更新默认场景(通过 SceneManager
this._sceneManager.update();
// 更新额外的 WorldManager
this._worldManager.updateAll();
// 更新调试管理器基于FPS的数据发送
if (this._debugManager) {
this._debugManager.onFrameUpdate(deltaTime);

View File

@@ -35,6 +35,12 @@ export interface InjectableMetadata {
* 依赖列表
*/
dependencies: Array<ServiceType<any> | string | symbol>;
/**
* 属性注入映射
* key: 属性名, value: 服务类型
*/
properties?: Map<string | symbol, ServiceType<any>>;
}
/**
@@ -77,10 +83,12 @@ export interface UpdatableMetadata {
*/
export function Injectable(): ClassDecorator {
return function <T extends Function>(target: T): T {
// 标记为可注入
const existing = injectableMetadata.get(target);
injectableMetadata.set(target, {
injectable: true,
dependencies: []
dependencies: [],
properties: existing?.properties
});
return target;
@@ -142,20 +150,7 @@ export function Updatable(priority: number = 0): ClassDecorator {
*
* 标记构造函数参数需要注入的服务类型
*
* @param serviceType 服务类型标识符类、字符串或Symbol
*
* @example
* ```typescript
* @Injectable()
* class MySystem extends EntitySystem {
* constructor(
* @Inject(TimeService) private timeService: TimeService,
* @Inject(PhysicsService) private physics: PhysicsService
* ) {
* super();
* }
* }
* ```
* @param serviceType 服务类型标识符
*/
export function Inject(serviceType: ServiceType<any> | string | symbol): ParameterDecorator {
return function (target: Object, propertyKey: string | symbol | undefined, parameterIndex: number) {
@@ -171,6 +166,35 @@ export function Inject(serviceType: ServiceType<any> | string | symbol): Paramet
};
}
/**
* @InjectProperty() 装饰器
*
* 通过属性装饰器注入依赖
*
* 注入时机在构造函数执行后、onInitialize() 调用前完成
*
* @param serviceType 服务类型
*/
export function InjectProperty(serviceType: ServiceType<any>): PropertyDecorator {
return function (target: any, propertyKey: string | symbol) {
let metadata = injectableMetadata.get(target.constructor);
if (!metadata) {
metadata = {
injectable: true,
dependencies: []
};
injectableMetadata.set(target.constructor, metadata);
}
if (!metadata.properties) {
metadata.properties = new Map();
}
metadata.properties.set(propertyKey, serviceType);
};
}
/**
* 检查类是否标记为可注入
*
@@ -252,6 +276,29 @@ export function createInstance<T>(
return new constructor(...dependencies);
}
/**
* 为实例注入属性依赖
*
* @param instance 目标实例
* @param container 服务容器
*/
export function injectProperties<T>(instance: T, container: ServiceContainer): void {
const constructor = (instance as any).constructor;
const metadata = getInjectableMetadata(constructor);
if (!metadata?.properties || metadata.properties.size === 0) {
return;
}
for (const [propertyKey, serviceType] of metadata.properties) {
const service = container.resolve(serviceType);
if (service !== null) {
(instance as any)[propertyKey] = service;
}
}
}
/**
* 检查类是否标记为可更新
*

View File

@@ -7,6 +7,7 @@
export {
Injectable,
Inject,
InjectProperty,
Updatable,
isInjectable,
getInjectableMetadata,
@@ -14,6 +15,7 @@ export {
isUpdatable,
getUpdatableMetadata,
createInstance,
injectProperties,
registerInjectable
} from './Decorators';

View File

@@ -15,7 +15,7 @@ import { IncrementalSerializer, IncrementalSnapshot, IncrementalSerializationOpt
import { ComponentPoolManager } from './Core/ComponentPool';
import { PerformanceMonitor } from '../Utils/PerformanceMonitor';
import { ServiceContainer, type ServiceType } from '../Core/ServiceContainer';
import { createInstance, isInjectable } from '../Core/DI';
import { createInstance, isInjectable, injectProperties } from '../Core/DI';
import { isUpdatable, getUpdatableMetadata } from '../Core/DI/Decorators';
import { createLogger } from '../Utils/Logger';
@@ -578,6 +578,8 @@ export class Scene implements IScene {
this._services.registerInstance(constructor, system);
injectProperties(system, this._services);
system.initialize();
return system;
@@ -742,10 +744,10 @@ export class Scene implements IScene {
/**
* 序列化场景
*
* 将场景及其所有实体、组件序列化为JSON字符串或二进制Buffer
* 将场景及其所有实体、组件序列化为JSON字符串或二进制Uint8Array
*
* @param options 序列化选项
* @returns 序列化后的数据JSON字符串或二进制Buffer
* @returns 序列化后的数据JSON字符串或二进制Uint8Array
*
* @example
* ```typescript
@@ -761,7 +763,7 @@ export class Scene implements IScene {
* });
* ```
*/
public serialize(options?: SceneSerializationOptions): string | Buffer {
public serialize(options?: SceneSerializationOptions): string | Uint8Array {
return SceneSerializer.serialize(this, options);
}
@@ -770,7 +772,7 @@ export class Scene implements IScene {
*
* 从序列化数据恢复场景状态
*
* @param saveData 序列化的数据JSON字符串或二进制Buffer
* @param saveData 序列化的数据JSON字符串或二进制Uint8Array
* @param options 反序列化选项
*
* @example
@@ -786,7 +788,7 @@ export class Scene implements IScene {
* });
* ```
*/
public deserialize(saveData: string | Buffer, options?: SceneDeserializationOptions): void {
public deserialize(saveData: string | Uint8Array, options?: SceneDeserializationOptions): void {
SceneSerializer.deserialize(this, saveData, options);
}
@@ -858,7 +860,7 @@ export class Scene implements IScene {
/**
* 应用增量变更到场景
*
* @param incremental 增量快照数据IncrementalSnapshot对象、JSON字符串或二进制Buffer
* @param incremental 增量快照数据IncrementalSnapshot对象、JSON字符串或二进制Uint8Array
* @param componentRegistry 组件类型注册表(可选,默认使用全局注册表)
*
* @example
@@ -870,21 +872,20 @@ export class Scene implements IScene {
* const jsonData = IncrementalSerializer.serializeIncremental(snapshot, { format: 'json' });
* scene.applyIncremental(jsonData);
*
* // 从二进制Buffer应用
* // 从二进制Uint8Array应用
* const binaryData = IncrementalSerializer.serializeIncremental(snapshot, { format: 'binary' });
* scene.applyIncremental(binaryData);
* ```
*/
public applyIncremental(
incremental: IncrementalSnapshot | string | Buffer,
incremental: IncrementalSnapshot | string | Uint8Array,
componentRegistry?: Map<string, any>
): void {
const isSerializedData = typeof incremental === 'string' ||
(typeof Buffer !== 'undefined' && Buffer.isBuffer(incremental)) ||
incremental instanceof Uint8Array;
const snapshot = isSerializedData
? IncrementalSerializer.deserializeIncremental(incremental as string | Buffer)
? IncrementalSerializer.deserializeIncremental(incremental as string | Uint8Array)
: incremental as IncrementalSnapshot;
const registry = componentRegistry || ComponentRegistry.getAllComponentNames() as Map<string, any>;

View File

@@ -3,10 +3,7 @@ import { ECSFluentAPI, createECSAPI } from './Core/FluentAPI';
import { Time } from '../Utils/Time';
import { createLogger } from '../Utils/Logger';
import type { IService } from '../Core/ServiceContainer';
import type { IUpdatable } from '../Types/IUpdatable';
import { World } from './World';
import { WorldManager } from './WorldManager';
import { Injectable, Inject, Updatable } from '../Core/DI';
/**
* 单场景管理器
@@ -21,13 +18,15 @@ import { Injectable, Inject, Updatable } from '../Core/DI';
* - 简单直观的API
* - 支持延迟场景切换
* - 自动管理ECS API
* - 通过依赖注入获取WorldManager的默认World
*
* @example
* ```typescript
* // 初始化Core
* Core.create({ debug: true });
*
* // 创建场景管理器
* const sceneManager = new SceneManager();
*
* // 设置场景
* class GameScene extends Scene {
* initialize() {
@@ -36,22 +35,21 @@ import { Injectable, Inject, Updatable } from '../Core/DI';
* }
* }
*
* Core.setScene(new GameScene());
* sceneManager.setScene(new GameScene());
*
* // 游戏循环
* function gameLoop(deltaTime: number) {
* Core.update(deltaTime); // 自动更新所有服务(包括SceneManager)
* Core.update(deltaTime); // 更新全局服务
* sceneManager.update(); // 更新场景
* }
*
* // 延迟切换场景(下一帧生效)
* Core.loadScene(new MenuScene());
* sceneManager.loadScene(new MenuScene());
* ```
*/
@Injectable()
@Updatable(10)
export class SceneManager implements IService, IUpdatable {
export class SceneManager implements IService {
/**
* 内部默认World(从WorldManager获取)
* 内部默认World
*/
private _defaultWorld: World;
@@ -80,18 +78,9 @@ export class SceneManager implements IService, IUpdatable {
*/
private static readonly DEFAULT_SCENE_ID = '__main__';
/**
* 构造函数
*
* WorldManager通过依赖注入自动传入
*
* @param worldManager WorldManager实例,用于获取默认World
*/
constructor(
@Inject(WorldManager) worldManager: WorldManager
) {
// 使用WorldManager管理的默认World
this._defaultWorld = worldManager.getDefaultWorld();
constructor() {
this._defaultWorld = new World({ name: '__default__' });
this._defaultWorld.start();
}
/**

View File

@@ -11,7 +11,7 @@ import { Component } from '../Component';
import { ComponentSerializer, SerializedComponent } from './ComponentSerializer';
import { SerializedEntity } from './EntitySerializer';
import { ComponentType } from '../Core/ComponentStorage';
import * as msgpack from 'msgpack-lite';
import { encode, decode } from '@msgpack/msgpack';
/**
* 变更操作类型
@@ -609,7 +609,7 @@ export class IncrementalSerializer {
*
* @param incremental 增量快照
* @param options 序列化选项
* @returns 序列化后的数据JSON字符串或二进制Buffer
* @returns 序列化后的数据JSON字符串或二进制Uint8Array
*
* @example
* ```typescript
@@ -631,7 +631,7 @@ export class IncrementalSerializer {
public static serializeIncremental(
incremental: IncrementalSnapshot,
options?: { format?: IncrementalSerializationFormat; pretty?: boolean }
): string | Buffer {
): string | Uint8Array {
const opts = {
format: 'json' as IncrementalSerializationFormat,
pretty: false,
@@ -639,7 +639,7 @@ export class IncrementalSerializer {
};
if (opts.format === 'binary') {
return msgpack.encode(incremental);
return encode(incremental);
} else {
return opts.pretty
? JSON.stringify(incremental, null, 2)
@@ -650,7 +650,7 @@ export class IncrementalSerializer {
/**
* 反序列化增量快照
*
* @param data 序列化的数据JSON字符串或二进制Buffer
* @param data 序列化的数据JSON字符串或二进制Uint8Array
* @returns 增量快照
*
* @example
@@ -662,13 +662,13 @@ export class IncrementalSerializer {
* const snapshot = IncrementalSerializer.deserializeIncremental(buffer);
* ```
*/
public static deserializeIncremental(data: string | Buffer): IncrementalSnapshot {
public static deserializeIncremental(data: string | Uint8Array): IncrementalSnapshot {
if (typeof data === 'string') {
// JSON格式
return JSON.parse(data);
} else {
// 二进制格式MessagePack
return msgpack.decode(data);
return decode(data) as IncrementalSnapshot;
}
}

View File

@@ -11,7 +11,7 @@ import { ComponentType, ComponentRegistry } from '../Core/ComponentStorage';
import { EntitySerializer, SerializedEntity } from './EntitySerializer';
import { getComponentTypeName } from '../Decorators';
import { getSerializationMetadata } from './SerializationDecorators';
import * as msgpack from 'msgpack-lite';
import { encode, decode } from '@msgpack/msgpack';
/**
* 场景序列化格式
@@ -154,9 +154,9 @@ export class SceneSerializer {
*
* @param scene 要序列化的场景
* @param options 序列化选项
* @returns 序列化后的数据JSON字符串或二进制Buffer
* @returns 序列化后的数据JSON字符串或二进制Uint8Array
*/
public static serialize(scene: IScene, options?: SceneSerializationOptions): string | Buffer {
public static serialize(scene: IScene, options?: SceneSerializationOptions): string | Uint8Array {
const opts: SceneSerializationOptions = {
systems: false,
format: 'json',
@@ -207,7 +207,7 @@ export class SceneSerializer {
: JSON.stringify(serializedScene);
} else {
// 二进制格式(使用 MessagePack
return msgpack.encode(serializedScene);
return encode(serializedScene);
}
}
@@ -215,12 +215,12 @@ export class SceneSerializer {
* 反序列化场景
*
* @param scene 目标场景
* @param saveData 序列化的数据JSON字符串或二进制Buffer
* @param saveData 序列化的数据JSON字符串或二进制Uint8Array
* @param options 反序列化选项
*/
public static deserialize(
scene: IScene,
saveData: string | Buffer,
saveData: string | Uint8Array,
options?: SceneDeserializationOptions
): void {
const opts: SceneDeserializationOptions = {
@@ -237,7 +237,7 @@ export class SceneSerializer {
serializedScene = JSON.parse(saveData);
} else {
// 二进制格式MessagePack
serializedScene = msgpack.decode(saveData);
serializedScene = decode(saveData) as SerializedScene;
}
} catch (error) {
throw new Error(`Failed to parse save data: ${error}`);

View File

@@ -1,8 +1,6 @@
import { World, IWorldConfig } from './World';
import { createLogger } from '../Utils/Logger';
import type { IService } from '../Core/ServiceContainer';
import type { IUpdatable } from '../Types/IUpdatable';
import { Injectable, Updatable } from '../Core/DI';
const logger = createLogger('WorldManager');
@@ -14,28 +12,21 @@ export interface IWorldManagerConfig {
* 最大World数量
*/
maxWorlds?: number;
/**
* 是否自动清理空World
*/
autoCleanup?: boolean;
/**
* 清理间隔(毫秒)
*/
cleanupInterval?: number;
/**
* 是否启用调试模式
*/
debug?: boolean;
/**
* 是否创建默认World(默认true)
*
* 当通过Core使用时应该为true,直接使用WorldManager时可设为false
*/
createDefaultWorld?: boolean;
}
/**
@@ -66,18 +57,12 @@ export interface IWorldManagerConfig {
*
* // 游戏循环
* function gameLoop(deltaTime: number) {
* Core.update(deltaTime); // 自动更新所有@Updatable服务(包括WorldManager)
* Core.update(deltaTime);
* worldManager.updateAll(); // 更新所有活跃World
* }
* ```
*/
@Injectable()
@Updatable(5)
export class WorldManager implements IService, IUpdatable {
/**
* 默认World的ID
*/
public static readonly DEFAULT_WORLD_ID = '__default__';
export class WorldManager implements IService {
private readonly _config: IWorldManagerConfig;
private readonly _worlds: Map<string, World> = new Map();
private readonly _activeWorlds: Set<string> = new Set();
@@ -90,26 +75,16 @@ export class WorldManager implements IService, IUpdatable {
autoCleanup: true,
cleanupInterval: 30000, // 30秒
debug: false,
createDefaultWorld: true, // 默认创建
...config
};
// 默认启动运行状态
this._isRunning = true;
// 如果配置要求,创建并注册默认World
if (this._config.createDefaultWorld) {
const defaultWorld = new World({ name: WorldManager.DEFAULT_WORLD_ID });
this._worlds.set(WorldManager.DEFAULT_WORLD_ID, defaultWorld);
this._activeWorlds.add(WorldManager.DEFAULT_WORLD_ID);
defaultWorld.start();
}
logger.info('WorldManager已初始化', {
maxWorlds: this._config.maxWorlds,
autoCleanup: this._config.autoCleanup,
cleanupInterval: this._config.cleanupInterval,
defaultWorldCreated: this._config.createDefaultWorld
cleanupInterval: this._config.cleanupInterval
});
this.startCleanupTimer();
@@ -117,22 +92,6 @@ export class WorldManager implements IService, IUpdatable {
// ===== World管理 =====
/**
* 获取默认World
*
* 默认World由WorldManager自动创建供SceneManager使用。
* 此方法主要供SceneManager内部使用。
*
* @returns 默认World实例
*/
public getDefaultWorld(): World {
const defaultWorld = this._worlds.get(WorldManager.DEFAULT_WORLD_ID);
if (!defaultWorld) {
throw new Error('默认World不存在这不应该发生');
}
return defaultWorld;
}
/**
* 创建新World
*/
@@ -164,16 +123,8 @@ export class WorldManager implements IService, IUpdatable {
/**
* 移除World
*
* 注意:默认World不能被删除
*/
public removeWorld(worldId: string): boolean {
// 防止删除默认World
if (worldId === WorldManager.DEFAULT_WORLD_ID) {
logger.warn('无法删除默认World');
return false;
}
const world = this._worlds.get(worldId);
if (!world) {
return false;
@@ -246,12 +197,18 @@ export class WorldManager implements IService, IUpdatable {
/**
* 更新所有活跃的World
*
* 此方法由ServiceContainer自动调用(@Updatable装饰器)
* 应该在每帧的游戏循环中调用。
* 会自动更新所有活跃World的全局系统和场景。
*
* @param deltaTime 帧时间间隔(未使用,保留用于接口兼容)
* @example
* ```typescript
* function gameLoop(deltaTime: number) {
* Core.update(deltaTime); // 更新全局服务
* worldManager.updateAll(); // 更新所有World
* }
* ```
*/
public update(deltaTime?: number): void {
public updateAll(): void {
if (!this._isRunning) return;
for (const worldId of this._activeWorlds) {