Revert "Merge pull request #102 from esengine/issue-74-World与Scene关系不清晰"

This reverts commit f2b9c5cc5a, reversing
changes made to 5f507532ed.
This commit is contained in:
YHH
2025-10-12 21:38:53 +08:00
parent ed84394301
commit 1924d979d6
5 changed files with 65 additions and 119 deletions

View File

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

View File

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

View File

@@ -1,8 +1,6 @@
import { World, IWorldConfig } from './World'; import { World, IWorldConfig } from './World';
import { createLogger } from '../Utils/Logger'; import { createLogger } from '../Utils/Logger';
import type { IService } from '../Core/ServiceContainer'; import type { IService } from '../Core/ServiceContainer';
import type { IUpdatable } from '../Types/IUpdatable';
import { Injectable, Updatable } from '../Core/DI';
const logger = createLogger('WorldManager'); const logger = createLogger('WorldManager');
@@ -29,13 +27,6 @@ export interface IWorldManagerConfig {
* 是否启用调试模式 * 是否启用调试模式
*/ */
debug?: boolean; debug?: boolean;
/**
* 是否创建默认World(默认true)
*
* 当通过Core使用时应该为true,直接使用WorldManager时可设为false
*/
createDefaultWorld?: boolean;
} }
/** /**
@@ -66,18 +57,12 @@ export interface IWorldManagerConfig {
* *
* // 游戏循环 * // 游戏循环
* function gameLoop(deltaTime: number) { * function gameLoop(deltaTime: number) {
* Core.update(deltaTime); // 自动更新所有@Updatable服务(包括WorldManager) * Core.update(deltaTime);
* worldManager.updateAll(); // 更新所有活跃World
* } * }
* ``` * ```
*/ */
@Injectable() export class WorldManager implements IService {
@Updatable(5)
export class WorldManager implements IService, IUpdatable {
/**
* 默认World的ID
*/
public static readonly DEFAULT_WORLD_ID = '__default__';
private readonly _config: IWorldManagerConfig; private readonly _config: IWorldManagerConfig;
private readonly _worlds: Map<string, World> = new Map(); private readonly _worlds: Map<string, World> = new Map();
private readonly _activeWorlds: Set<string> = new Set(); private readonly _activeWorlds: Set<string> = new Set();
@@ -90,26 +75,16 @@ export class WorldManager implements IService, IUpdatable {
autoCleanup: true, autoCleanup: true,
cleanupInterval: 30000, // 30秒 cleanupInterval: 30000, // 30秒
debug: false, debug: false,
createDefaultWorld: true, // 默认创建
...config ...config
}; };
// 默认启动运行状态 // 默认启动运行状态
this._isRunning = true; 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已初始化', { logger.info('WorldManager已初始化', {
maxWorlds: this._config.maxWorlds, maxWorlds: this._config.maxWorlds,
autoCleanup: this._config.autoCleanup, autoCleanup: this._config.autoCleanup,
cleanupInterval: this._config.cleanupInterval, cleanupInterval: this._config.cleanupInterval
defaultWorldCreated: this._config.createDefaultWorld
}); });
this.startCleanupTimer(); this.startCleanupTimer();
@@ -117,22 +92,6 @@ export class WorldManager implements IService, IUpdatable {
// ===== World管理 ===== // ===== 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 * 创建新World
*/ */
@@ -164,16 +123,8 @@ export class WorldManager implements IService, IUpdatable {
/** /**
* 移除World * 移除World
*
* 注意:默认World不能被删除
*/ */
public removeWorld(worldId: string): boolean { public removeWorld(worldId: string): boolean {
// 防止删除默认World
if (worldId === WorldManager.DEFAULT_WORLD_ID) {
logger.warn('无法删除默认World');
return false;
}
const world = this._worlds.get(worldId); const world = this._worlds.get(worldId);
if (!world) { if (!world) {
return false; return false;
@@ -246,12 +197,18 @@ export class WorldManager implements IService, IUpdatable {
/** /**
* 更新所有活跃的World * 更新所有活跃的World
* *
* 此方法由ServiceContainer自动调用(@Updatable装饰器) * 应该在每帧的游戏循环中调用。
* 会自动更新所有活跃World的全局系统和场景。 * 会自动更新所有活跃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; if (!this._isRunning) return;
for (const worldId of this._activeWorlds) { for (const worldId of this._activeWorlds) {

View File

@@ -47,6 +47,13 @@ class NetworkGlobalSystem implements IGlobalSystem {
/** /**
* World与Core集成测试 * World与Core集成测试
*
* 注意v3.0重构后Core不再直接管理Scene/World
* - 场景管理由 SceneManager 负责
* - 多世界管理由 WorldManager 负责
* - Core 仅负责全局服务Timer、Performance等
*
* 大部分旧的集成测试已移至 SceneManager.test.ts 和 WorldManager.test.ts
*/ */
describe('World与Core集成测试', () => { describe('World与Core集成测试', () => {
let worldManager: WorldManager; let worldManager: WorldManager;
@@ -60,10 +67,8 @@ describe('World与Core集成测试', () => {
Core.create({ debug: false }); Core.create({ debug: false });
// WorldManager和SceneManager不再是单例 // WorldManager和SceneManager不再是单例
// SceneManager需要WorldManager的默认World,所以必须创建 worldManager = new WorldManager();
worldManager = new WorldManager({ createDefaultWorld: true }); sceneManager = new SceneManager();
// SceneManager需要WorldManager实例
sceneManager = new SceneManager(worldManager);
}); });
afterEach(() => { afterEach(() => {
@@ -104,8 +109,7 @@ describe('World与Core集成测试', () => {
const world1 = worldManager.createWorld('world1'); const world1 = worldManager.createWorld('world1');
const world2 = worldManager.createWorld('world2'); const world2 = worldManager.createWorld('world2');
// worldManager已包含默认World,所以总数是3 expect(worldManager.worldCount).toBe(2);
expect(worldManager.worldCount).toBe(3);
expect(worldManager.getWorld('world1')).toBe(world1); expect(worldManager.getWorld('world1')).toBe(world1);
expect(worldManager.getWorld('world2')).toBe(world2); expect(worldManager.getWorld('world2')).toBe(world2);
}); });
@@ -133,7 +137,7 @@ describe('World与Core集成测试', () => {
// 游戏循环 // 游戏循环
Core.update(0.016); // 更新全局服务 Core.update(0.016); // 更新全局服务
worldManager.update(); // 更新所有World worldManager.updateAll(); // 更新所有World
expect(world.isActive).toBe(true); expect(world.isActive).toBe(true);
}); });
@@ -146,7 +150,7 @@ describe('World与Core集成测试', () => {
worldManager.setWorldActive('test-world', true); worldManager.setWorldActive('test-world', true);
// 更新World // 更新World
worldManager.update(); worldManager.updateAll();
expect(globalSystem.syncCount).toBeGreaterThan(0); expect(globalSystem.syncCount).toBeGreaterThan(0);
}); });
@@ -154,8 +158,8 @@ describe('World与Core集成测试', () => {
describe('隔离性测试', () => { describe('隔离性测试', () => {
test('多个WorldManager实例应该完全隔离', () => { test('多个WorldManager实例应该完全隔离', () => {
const manager1 = new WorldManager({ createDefaultWorld: false }); const manager1 = new WorldManager();
const manager2 = new WorldManager({ createDefaultWorld: false }); const manager2 = new WorldManager();
manager1.createWorld('world1'); manager1.createWorld('world1');
manager2.createWorld('world2'); manager2.createWorld('world2');
@@ -171,10 +175,8 @@ describe('World与Core集成测试', () => {
}); });
test('多个SceneManager实例应该完全隔离', () => { test('多个SceneManager实例应该完全隔离', () => {
const wm1 = new WorldManager({ createDefaultWorld: true }); const sm1 = new SceneManager();
const wm2 = new WorldManager({ createDefaultWorld: true }); const sm2 = new SceneManager();
const sm1 = new SceneManager(wm1);
const sm2 = new SceneManager(wm2);
const scene1 = new Scene(); const scene1 = new Scene();
const scene2 = new Scene(); const scene2 = new Scene();
@@ -188,8 +190,6 @@ describe('World与Core集成测试', () => {
// 清理 // 清理
sm1.destroy(); sm1.destroy();
sm2.destroy(); sm2.destroy();
wm1.destroy();
wm2.destroy();
}); });
}); });
}); });

View File

@@ -42,8 +42,7 @@ describe('WorldManager', () => {
beforeEach(() => { beforeEach(() => {
// WorldManager不再是单例直接创建新实例 // WorldManager不再是单例直接创建新实例
// 测试时不创建默认World worldManager = new WorldManager();
worldManager = new WorldManager({ createDefaultWorld: false });
}); });
afterEach(() => { afterEach(() => {
@@ -60,8 +59,8 @@ describe('WorldManager', () => {
describe('实例化', () => { describe('实例化', () => {
test('可以创建多个独立的WorldManager实例', () => { test('可以创建多个独立的WorldManager实例', () => {
const manager1 = new WorldManager({ createDefaultWorld: false }); const manager1 = new WorldManager();
const manager2 = new WorldManager({ createDefaultWorld: false }); const manager2 = new WorldManager();
expect(manager1).not.toBe(manager2); expect(manager1).not.toBe(manager2);
@@ -77,8 +76,7 @@ describe('WorldManager', () => {
const config: IWorldManagerConfig = { const config: IWorldManagerConfig = {
maxWorlds: 10, maxWorlds: 10,
autoCleanup: true, autoCleanup: true,
debug: false, debug: false
createDefaultWorld: false
}; };
const instance = new WorldManager(config); const instance = new WorldManager(config);
@@ -123,7 +121,7 @@ describe('WorldManager', () => {
}); });
test('超出最大World数量应该抛出错误', () => { test('超出最大World数量应该抛出错误', () => {
const limitedManager = new WorldManager({ maxWorlds: 2, createDefaultWorld: false }); const limitedManager = new WorldManager({ maxWorlds: 2 });
limitedManager.createWorld('world1'); limitedManager.createWorld('world1');
limitedManager.createWorld('world2'); limitedManager.createWorld('world2');
@@ -430,8 +428,7 @@ describe('WorldManager', () => {
const invalidConfig: IWorldManagerConfig = { const invalidConfig: IWorldManagerConfig = {
maxWorlds: -1, maxWorlds: -1,
autoCleanup: true, autoCleanup: true,
debug: true, debug: true
createDefaultWorld: false
}; };
const manager = new WorldManager(invalidConfig); const manager = new WorldManager(invalidConfig);
@@ -445,8 +442,7 @@ describe('WorldManager', () => {
const config: IWorldManagerConfig = { const config: IWorldManagerConfig = {
maxWorlds: 3, maxWorlds: 3,
autoCleanup: true, autoCleanup: true,
debug: true, debug: true
createDefaultWorld: false
}; };
const manager = new WorldManager(config); const manager = new WorldManager(config);