diff --git a/packages/core/src/Core.ts b/packages/core/src/Core.ts index d240c4f3..f04e2202 100644 --- a/packages/core/src/Core.ts +++ b/packages/core/src/Core.ts @@ -13,6 +13,7 @@ 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'; /** * 游戏引擎核心类 @@ -177,9 +178,14 @@ export class Core { this._poolManager = new PoolManager(); this._serviceContainer.registerInstance(PoolManager, this._poolManager); - // 初始化场景管理器 - this._sceneManager = new SceneManager(); - this._serviceContainer.registerInstance(SceneManager, this._sceneManager); + // 使用依赖注入自动注册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.setSceneChangedCallback(() => { @@ -188,10 +194,6 @@ export class Core { } }); - // 初始化World管理器 - this._worldManager = new WorldManager(); - this._serviceContainer.registerInstance(WorldManager, this._worldManager); - // 初始化插件管理器 this._pluginManager = new PluginManager(); this._pluginManager.initialize(this, this._serviceContainer); @@ -645,7 +647,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()); @@ -653,12 +655,6 @@ export class Core { // 更新对象池管理器 this._poolManager.update(); - // 更新默认场景(通过 SceneManager) - this._sceneManager.update(); - - // 更新额外的 WorldManager - this._worldManager.updateAll(); - // 更新调试管理器(基于FPS的数据发送) if (this._debugManager) { this._debugManager.onFrameUpdate(deltaTime); diff --git a/packages/core/src/ECS/SceneManager.ts b/packages/core/src/ECS/SceneManager.ts index 8d1b2b50..62b3876d 100644 --- a/packages/core/src/ECS/SceneManager.ts +++ b/packages/core/src/ECS/SceneManager.ts @@ -3,7 +3,10 @@ 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'; /** * 单场景管理器 @@ -18,15 +21,13 @@ import { World } from './World'; * - 简单直观的API * - 支持延迟场景切换 * - 自动管理ECS API + * - 通过依赖注入获取WorldManager的默认World * * @example * ```typescript * // 初始化Core * Core.create({ debug: true }); * - * // 创建场景管理器 - * const sceneManager = new SceneManager(); - * * // 设置场景 * class GameScene extends Scene { * initialize() { @@ -35,21 +36,22 @@ import { World } from './World'; * } * } * - * sceneManager.setScene(new GameScene()); + * Core.setScene(new GameScene()); * * // 游戏循环 * function gameLoop(deltaTime: number) { - * Core.update(deltaTime); // 更新全局服务 - * sceneManager.update(); // 更新场景 + * Core.update(deltaTime); // 自动更新所有服务(包括SceneManager) * } * * // 延迟切换场景(下一帧生效) - * sceneManager.loadScene(new MenuScene()); + * Core.loadScene(new MenuScene()); * ``` */ -export class SceneManager implements IService { +@Injectable() +@Updatable(10) +export class SceneManager implements IService, IUpdatable { /** - * 内部默认World + * 内部默认World(从WorldManager获取) */ private _defaultWorld: World; @@ -78,9 +80,18 @@ export class SceneManager implements IService { */ private static readonly DEFAULT_SCENE_ID = '__main__'; - constructor() { - this._defaultWorld = new World({ name: '__default__' }); - this._defaultWorld.start(); + /** + * 构造函数 + * + * WorldManager通过依赖注入自动传入 + * + * @param worldManager WorldManager实例,用于获取默认World + */ + constructor( + @Inject(WorldManager) worldManager: WorldManager + ) { + // 使用WorldManager管理的默认World + this._defaultWorld = worldManager.getDefaultWorld(); } /** diff --git a/packages/core/src/ECS/WorldManager.ts b/packages/core/src/ECS/WorldManager.ts index 5296e8a9..d04c6151 100644 --- a/packages/core/src/ECS/WorldManager.ts +++ b/packages/core/src/ECS/WorldManager.ts @@ -1,6 +1,8 @@ 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'); @@ -12,21 +14,28 @@ export interface IWorldManagerConfig { * 最大World数量 */ maxWorlds?: number; - + /** * 是否自动清理空World */ autoCleanup?: boolean; - + /** * 清理间隔(毫秒) */ cleanupInterval?: number; - + /** * 是否启用调试模式 */ debug?: boolean; + + /** + * 是否创建默认World(默认true) + * + * 当通过Core使用时应该为true,直接使用WorldManager时可设为false + */ + createDefaultWorld?: boolean; } /** @@ -57,12 +66,18 @@ export interface IWorldManagerConfig { * * // 游戏循环 * function gameLoop(deltaTime: number) { - * Core.update(deltaTime); - * worldManager.updateAll(); // 更新所有活跃World + * Core.update(deltaTime); // 自动更新所有@Updatable服务(包括WorldManager) * } * ``` */ -export class WorldManager implements IService { +@Injectable() +@Updatable(5) +export class WorldManager implements IService, IUpdatable { + /** + * 默认World的ID + */ + public static readonly DEFAULT_WORLD_ID = '__default__'; + private readonly _config: IWorldManagerConfig; private readonly _worlds: Map = new Map(); private readonly _activeWorlds: Set = new Set(); @@ -75,16 +90,26 @@ export class WorldManager implements IService { 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 + cleanupInterval: this._config.cleanupInterval, + defaultWorldCreated: this._config.createDefaultWorld }); this.startCleanupTimer(); @@ -92,6 +117,22 @@ export class WorldManager implements IService { // ===== 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 */ @@ -123,8 +164,16 @@ export class WorldManager implements IService { /** * 移除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; @@ -197,18 +246,12 @@ export class WorldManager implements IService { /** * 更新所有活跃的World * - * 应该在每帧的游戏循环中调用。 + * 此方法由ServiceContainer自动调用(@Updatable装饰器) * 会自动更新所有活跃World的全局系统和场景。 * - * @example - * ```typescript - * function gameLoop(deltaTime: number) { - * Core.update(deltaTime); // 更新全局服务 - * worldManager.updateAll(); // 更新所有World - * } - * ``` + * @param deltaTime 帧时间间隔(未使用,保留用于接口兼容) */ - public updateAll(): void { + public update(deltaTime?: number): void { if (!this._isRunning) return; for (const worldId of this._activeWorlds) { diff --git a/packages/core/tests/ECS/Core/WorldCoreIntegration.test.ts b/packages/core/tests/ECS/Core/WorldCoreIntegration.test.ts index 969a8851..6ea14e3e 100644 --- a/packages/core/tests/ECS/Core/WorldCoreIntegration.test.ts +++ b/packages/core/tests/ECS/Core/WorldCoreIntegration.test.ts @@ -47,13 +47,6 @@ class NetworkGlobalSystem implements IGlobalSystem { /** * World与Core集成测试 - * - * 注意:v3.0重构后,Core不再直接管理Scene/World - * - 场景管理由 SceneManager 负责 - * - 多世界管理由 WorldManager 负责 - * - Core 仅负责全局服务(Timer、Performance等) - * - * 大部分旧的集成测试已移至 SceneManager.test.ts 和 WorldManager.test.ts */ describe('World与Core集成测试', () => { let worldManager: WorldManager; @@ -67,8 +60,10 @@ describe('World与Core集成测试', () => { Core.create({ debug: false }); // WorldManager和SceneManager不再是单例 - worldManager = new WorldManager(); - sceneManager = new SceneManager(); + // SceneManager需要WorldManager的默认World,所以必须创建 + worldManager = new WorldManager({ createDefaultWorld: true }); + // SceneManager需要WorldManager实例 + sceneManager = new SceneManager(worldManager); }); afterEach(() => { @@ -109,7 +104,8 @@ describe('World与Core集成测试', () => { const world1 = worldManager.createWorld('world1'); const world2 = worldManager.createWorld('world2'); - expect(worldManager.worldCount).toBe(2); + // worldManager已包含默认World,所以总数是3 + expect(worldManager.worldCount).toBe(3); expect(worldManager.getWorld('world1')).toBe(world1); expect(worldManager.getWorld('world2')).toBe(world2); }); @@ -137,7 +133,7 @@ describe('World与Core集成测试', () => { // 游戏循环 Core.update(0.016); // 更新全局服务 - worldManager.updateAll(); // 更新所有World + worldManager.update(); // 更新所有World expect(world.isActive).toBe(true); }); @@ -150,7 +146,7 @@ describe('World与Core集成测试', () => { worldManager.setWorldActive('test-world', true); // 更新World - worldManager.updateAll(); + worldManager.update(); expect(globalSystem.syncCount).toBeGreaterThan(0); }); @@ -158,8 +154,8 @@ describe('World与Core集成测试', () => { describe('隔离性测试', () => { test('多个WorldManager实例应该完全隔离', () => { - const manager1 = new WorldManager(); - const manager2 = new WorldManager(); + const manager1 = new WorldManager({ createDefaultWorld: false }); + const manager2 = new WorldManager({ createDefaultWorld: false }); manager1.createWorld('world1'); manager2.createWorld('world2'); @@ -175,8 +171,10 @@ describe('World与Core集成测试', () => { }); test('多个SceneManager实例应该完全隔离', () => { - const sm1 = new SceneManager(); - const sm2 = new SceneManager(); + const wm1 = new WorldManager({ createDefaultWorld: true }); + const wm2 = new WorldManager({ createDefaultWorld: true }); + const sm1 = new SceneManager(wm1); + const sm2 = new SceneManager(wm2); const scene1 = new Scene(); const scene2 = new Scene(); @@ -190,6 +188,8 @@ describe('World与Core集成测试', () => { // 清理 sm1.destroy(); sm2.destroy(); + wm1.destroy(); + wm2.destroy(); }); }); }); diff --git a/packages/core/tests/ECS/WorldManager.test.ts b/packages/core/tests/ECS/WorldManager.test.ts index 0285fd2c..64ffbbad 100644 --- a/packages/core/tests/ECS/WorldManager.test.ts +++ b/packages/core/tests/ECS/WorldManager.test.ts @@ -42,7 +42,8 @@ describe('WorldManager', () => { beforeEach(() => { // WorldManager不再是单例,直接创建新实例 - worldManager = new WorldManager(); + // 测试时不创建默认World + worldManager = new WorldManager({ createDefaultWorld: false }); }); afterEach(() => { @@ -59,8 +60,8 @@ describe('WorldManager', () => { describe('实例化', () => { test('可以创建多个独立的WorldManager实例', () => { - const manager1 = new WorldManager(); - const manager2 = new WorldManager(); + const manager1 = new WorldManager({ createDefaultWorld: false }); + const manager2 = new WorldManager({ createDefaultWorld: false }); expect(manager1).not.toBe(manager2); @@ -76,7 +77,8 @@ describe('WorldManager', () => { const config: IWorldManagerConfig = { maxWorlds: 10, autoCleanup: true, - debug: false + debug: false, + createDefaultWorld: false }; const instance = new WorldManager(config); @@ -121,7 +123,7 @@ describe('WorldManager', () => { }); test('超出最大World数量应该抛出错误', () => { - const limitedManager = new WorldManager({ maxWorlds: 2 }); + const limitedManager = new WorldManager({ maxWorlds: 2, createDefaultWorld: false }); limitedManager.createWorld('world1'); limitedManager.createWorld('world2'); @@ -428,7 +430,8 @@ describe('WorldManager', () => { const invalidConfig: IWorldManagerConfig = { maxWorlds: -1, autoCleanup: true, - debug: true + debug: true, + createDefaultWorld: false }; const manager = new WorldManager(invalidConfig); @@ -442,7 +445,8 @@ describe('WorldManager', () => { const config: IWorldManagerConfig = { maxWorlds: 3, autoCleanup: true, - debug: true + debug: true, + createDefaultWorld: false }; const manager = new WorldManager(config);