2025-08-20 17:48:31 +08:00
|
|
|
|
import { World, IWorldConfig } from './World';
|
|
|
|
|
|
import { createLogger } from '../Utils/Logger';
|
2025-10-11 10:40:10 +08:00
|
|
|
|
import type { IService } from '../Core/ServiceContainer';
|
2025-08-20 17:48:31 +08:00
|
|
|
|
|
|
|
|
|
|
const logger = createLogger('WorldManager');
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* WorldManager配置接口
|
|
|
|
|
|
*/
|
|
|
|
|
|
export interface IWorldManagerConfig {
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 最大World数量
|
|
|
|
|
|
*/
|
|
|
|
|
|
maxWorlds?: number;
|
2025-11-01 17:41:50 +08:00
|
|
|
|
|
2025-08-20 17:48:31 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 是否自动清理空World
|
|
|
|
|
|
*/
|
|
|
|
|
|
autoCleanup?: boolean;
|
2025-11-01 17:41:50 +08:00
|
|
|
|
|
2025-08-20 17:48:31 +08:00
|
|
|
|
/**
|
2025-11-09 17:35:07 +08:00
|
|
|
|
* 清理间隔(帧数)
|
2025-08-20 17:48:31 +08:00
|
|
|
|
*/
|
2025-11-09 17:35:07 +08:00
|
|
|
|
cleanupFrameInterval?: number;
|
2025-11-01 17:41:50 +08:00
|
|
|
|
|
2025-08-20 17:48:31 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 是否启用调试模式
|
|
|
|
|
|
*/
|
|
|
|
|
|
debug?: boolean;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* World管理器 - 管理所有World实例
|
2025-10-09 23:33:11 +08:00
|
|
|
|
*
|
|
|
|
|
|
* WorldManager负责管理多个独立的World实例。
|
2025-08-20 17:48:31 +08:00
|
|
|
|
* 每个World都是独立的ECS环境,可以包含多个Scene。
|
2025-10-09 23:33:11 +08:00
|
|
|
|
*
|
|
|
|
|
|
* 适用场景:
|
|
|
|
|
|
* - MMO游戏的多房间管理
|
|
|
|
|
|
* - 服务器端的多游戏实例
|
|
|
|
|
|
* - 需要完全隔离的多个游戏环境
|
|
|
|
|
|
*
|
2025-08-20 17:48:31 +08:00
|
|
|
|
* @example
|
|
|
|
|
|
* ```typescript
|
2025-10-09 23:33:11 +08:00
|
|
|
|
* // 创建WorldManager实例
|
|
|
|
|
|
* const worldManager = new WorldManager({
|
|
|
|
|
|
* maxWorlds: 100,
|
|
|
|
|
|
* autoCleanup: true
|
|
|
|
|
|
* });
|
|
|
|
|
|
*
|
2025-08-20 17:48:31 +08:00
|
|
|
|
* // 创建游戏房间World
|
2025-10-09 23:33:11 +08:00
|
|
|
|
* const room1 = worldManager.createWorld('room_001', {
|
2025-08-20 17:48:31 +08:00
|
|
|
|
* name: 'GameRoom_001',
|
|
|
|
|
|
* maxScenes: 5
|
|
|
|
|
|
* });
|
2025-10-09 23:33:11 +08:00
|
|
|
|
* room1.setActive(true);
|
|
|
|
|
|
*
|
|
|
|
|
|
* // 游戏循环
|
|
|
|
|
|
* function gameLoop(deltaTime: number) {
|
2025-10-12 21:38:53 +08:00
|
|
|
|
* Core.update(deltaTime);
|
|
|
|
|
|
* worldManager.updateAll(); // 更新所有活跃World
|
2025-10-09 23:33:11 +08:00
|
|
|
|
* }
|
2025-08-20 17:48:31 +08:00
|
|
|
|
* ```
|
|
|
|
|
|
*/
|
2025-10-12 21:38:53 +08:00
|
|
|
|
export class WorldManager implements IService {
|
2025-11-09 17:35:07 +08:00
|
|
|
|
private readonly _config: Required<IWorldManagerConfig>;
|
2025-08-20 17:48:31 +08:00
|
|
|
|
private readonly _worlds: Map<string, World> = new Map();
|
|
|
|
|
|
private _isRunning: boolean = false;
|
2025-11-09 17:35:07 +08:00
|
|
|
|
private _framesSinceCleanup: number = 0;
|
2025-08-20 17:48:31 +08:00
|
|
|
|
|
2025-10-09 23:33:11 +08:00
|
|
|
|
public constructor(config: IWorldManagerConfig = {}) {
|
2025-08-20 17:48:31 +08:00
|
|
|
|
this._config = {
|
|
|
|
|
|
maxWorlds: 50,
|
|
|
|
|
|
autoCleanup: true,
|
2025-11-09 17:35:07 +08:00
|
|
|
|
cleanupFrameInterval: 1800, // 1800帧
|
2025-08-20 17:48:31 +08:00
|
|
|
|
debug: false,
|
|
|
|
|
|
...config
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-10-09 23:33:11 +08:00
|
|
|
|
// 默认启动运行状态
|
|
|
|
|
|
this._isRunning = true;
|
|
|
|
|
|
|
2025-08-20 17:48:31 +08:00
|
|
|
|
logger.info('WorldManager已初始化', {
|
|
|
|
|
|
maxWorlds: this._config.maxWorlds,
|
|
|
|
|
|
autoCleanup: this._config.autoCleanup,
|
2025-11-09 17:35:07 +08:00
|
|
|
|
cleanupFrameInterval: this._config.cleanupFrameInterval
|
2025-08-20 17:48:31 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 创建新World
|
|
|
|
|
|
*/
|
2025-11-15 00:20:17 +08:00
|
|
|
|
public createWorld(worldName: string, config?: IWorldConfig): World {
|
|
|
|
|
|
if (!worldName || typeof worldName !== 'string' || worldName.trim() === '') {
|
|
|
|
|
|
throw new Error('World name不能为空');
|
2025-08-20 17:48:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-15 00:20:17 +08:00
|
|
|
|
if (this._worlds.has(worldName)) {
|
|
|
|
|
|
throw new Error(`World name '${worldName}' 已存在`);
|
2025-08-20 17:48:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (this._worlds.size >= this._config.maxWorlds!) {
|
|
|
|
|
|
throw new Error(`已达到最大World数量限制: ${this._config.maxWorlds}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-09 11:32:04 +08:00
|
|
|
|
// 优先级:config.debug > WorldManager.debug > 默认
|
2025-08-20 17:48:31 +08:00
|
|
|
|
const worldConfig: IWorldConfig = {
|
2025-11-15 00:20:17 +08:00
|
|
|
|
name: worldName,
|
2025-11-09 11:32:04 +08:00
|
|
|
|
debug: config?.debug ?? this._config.debug ?? false,
|
2025-10-31 16:14:23 +08:00
|
|
|
|
...(config?.maxScenes !== undefined && { maxScenes: config.maxScenes }),
|
|
|
|
|
|
...(config?.autoCleanup !== undefined && { autoCleanup: config.autoCleanup })
|
2025-08-20 17:48:31 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const world = new World(worldConfig);
|
2025-11-15 00:20:17 +08:00
|
|
|
|
this._worlds.set(worldName, world);
|
2025-08-20 17:48:31 +08:00
|
|
|
|
|
|
|
|
|
|
return world;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 移除World
|
|
|
|
|
|
*/
|
2025-11-15 00:20:17 +08:00
|
|
|
|
public removeWorld(worldName: string): boolean {
|
|
|
|
|
|
const world = this._worlds.get(worldName);
|
2025-08-20 17:48:31 +08:00
|
|
|
|
if (!world) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 销毁World
|
|
|
|
|
|
world.destroy();
|
2025-11-15 00:20:17 +08:00
|
|
|
|
this._worlds.delete(worldName);
|
2025-08-20 17:48:31 +08:00
|
|
|
|
|
2025-11-15 00:20:17 +08:00
|
|
|
|
logger.info(`移除World: ${worldName}`);
|
2025-08-20 17:48:31 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取World
|
|
|
|
|
|
*/
|
2025-11-15 00:20:17 +08:00
|
|
|
|
public getWorld(worldName: string): World | null {
|
|
|
|
|
|
return this._worlds.get(worldName) || null;
|
2025-08-20 17:48:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取所有World ID
|
|
|
|
|
|
*/
|
|
|
|
|
|
public getWorldIds(): string[] {
|
|
|
|
|
|
return Array.from(this._worlds.keys());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取所有World
|
|
|
|
|
|
*/
|
|
|
|
|
|
public getAllWorlds(): World[] {
|
|
|
|
|
|
return Array.from(this._worlds.values());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置World激活状态
|
|
|
|
|
|
*/
|
2025-11-15 00:20:17 +08:00
|
|
|
|
public setWorldActive(worldName: string, active: boolean): void {
|
|
|
|
|
|
const world = this._worlds.get(worldName);
|
2025-08-20 17:48:31 +08:00
|
|
|
|
if (!world) {
|
2025-11-15 00:20:17 +08:00
|
|
|
|
logger.warn(`World '${worldName}' 不存在`);
|
2025-08-20 17:48:31 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (active) {
|
|
|
|
|
|
world.start();
|
2025-11-15 00:20:17 +08:00
|
|
|
|
logger.debug(`激活World: ${worldName}`);
|
2025-08-20 17:48:31 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
world.stop();
|
2025-11-15 00:20:17 +08:00
|
|
|
|
logger.debug(`停用World: ${worldName}`);
|
2025-08-20 17:48:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检查World是否激活
|
|
|
|
|
|
*/
|
2025-11-15 00:20:17 +08:00
|
|
|
|
public isWorldActive(worldName: string): boolean {
|
|
|
|
|
|
const world = this._worlds.get(worldName);
|
2025-11-09 17:35:07 +08:00
|
|
|
|
return world?.isActive ?? false;
|
2025-08-20 17:48:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-09 23:33:11 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 更新所有活跃的World
|
|
|
|
|
|
*
|
2025-10-12 21:38:53 +08:00
|
|
|
|
* 应该在每帧的游戏循环中调用。
|
2025-10-09 23:33:11 +08:00
|
|
|
|
* 会自动更新所有活跃World的全局系统和场景。
|
|
|
|
|
|
*
|
2025-10-12 21:38:53 +08:00
|
|
|
|
* @example
|
|
|
|
|
|
* ```typescript
|
|
|
|
|
|
* function gameLoop(deltaTime: number) {
|
|
|
|
|
|
* Core.update(deltaTime); // 更新全局服务
|
|
|
|
|
|
* worldManager.updateAll(); // 更新所有World
|
|
|
|
|
|
* }
|
|
|
|
|
|
* ```
|
|
|
|
|
|
*/
|
|
|
|
|
|
public updateAll(): void {
|
2025-10-09 23:33:11 +08:00
|
|
|
|
if (!this._isRunning) return;
|
|
|
|
|
|
|
2025-11-09 17:35:07 +08:00
|
|
|
|
for (const world of this._worlds.values()) {
|
|
|
|
|
|
if (world.isActive) {
|
2025-10-09 23:33:11 +08:00
|
|
|
|
// 更新World的全局System
|
|
|
|
|
|
world.updateGlobalSystems();
|
|
|
|
|
|
|
|
|
|
|
|
// 更新World中的所有Scene
|
|
|
|
|
|
world.updateScenes();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-09 17:35:07 +08:00
|
|
|
|
|
|
|
|
|
|
// 基于帧的自动清理
|
|
|
|
|
|
if (this._config.autoCleanup) {
|
|
|
|
|
|
this._framesSinceCleanup++;
|
|
|
|
|
|
|
|
|
|
|
|
if (this._framesSinceCleanup >= this._config.cleanupFrameInterval) {
|
|
|
|
|
|
this.cleanup();
|
|
|
|
|
|
this._framesSinceCleanup = 0; // 重置计数器
|
|
|
|
|
|
|
|
|
|
|
|
if (this._config.debug) {
|
|
|
|
|
|
logger.debug(`执行定期清理World (间隔: ${this._config.cleanupFrameInterval} 帧)`);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-09 23:33:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-20 17:48:31 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取所有激活的World
|
|
|
|
|
|
*/
|
|
|
|
|
|
public getActiveWorlds(): World[] {
|
|
|
|
|
|
const activeWorlds: World[] = [];
|
2025-11-09 17:35:07 +08:00
|
|
|
|
for (const world of this._worlds.values()) {
|
|
|
|
|
|
if (world.isActive) {
|
2025-08-20 17:48:31 +08:00
|
|
|
|
activeWorlds.push(world);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return activeWorlds;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 启动所有World
|
|
|
|
|
|
*/
|
|
|
|
|
|
public startAll(): void {
|
|
|
|
|
|
this._isRunning = true;
|
2025-11-01 17:41:50 +08:00
|
|
|
|
|
2025-11-09 17:35:07 +08:00
|
|
|
|
for (const world of this._worlds.values()) {
|
|
|
|
|
|
world.start();
|
2025-08-20 17:48:31 +08:00
|
|
|
|
}
|
2025-11-01 17:41:50 +08:00
|
|
|
|
|
2025-08-20 17:48:31 +08:00
|
|
|
|
logger.info('启动所有World');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 停止所有World
|
|
|
|
|
|
*/
|
|
|
|
|
|
public stopAll(): void {
|
|
|
|
|
|
this._isRunning = false;
|
2025-11-01 17:41:50 +08:00
|
|
|
|
|
2025-11-09 17:35:07 +08:00
|
|
|
|
for (const world of this._worlds.values()) {
|
|
|
|
|
|
world.stop();
|
2025-08-20 17:48:31 +08:00
|
|
|
|
}
|
2025-11-01 17:41:50 +08:00
|
|
|
|
|
2025-08-20 17:48:31 +08:00
|
|
|
|
logger.info('停止所有World');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 查找满足条件的World
|
|
|
|
|
|
*/
|
|
|
|
|
|
public findWorlds(predicate: (world: World) => boolean): World[] {
|
|
|
|
|
|
const results: World[] = [];
|
|
|
|
|
|
for (const world of this._worlds.values()) {
|
|
|
|
|
|
if (predicate(world)) {
|
|
|
|
|
|
results.push(world);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return results;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 根据名称查找World
|
|
|
|
|
|
*/
|
|
|
|
|
|
public findWorldByName(name: string): World | null {
|
|
|
|
|
|
for (const world of this._worlds.values()) {
|
|
|
|
|
|
if (world.name === name) {
|
|
|
|
|
|
return world;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取WorldManager统计信息
|
|
|
|
|
|
*/
|
|
|
|
|
|
public getStats() {
|
|
|
|
|
|
const stats = {
|
|
|
|
|
|
totalWorlds: this._worlds.size,
|
2025-11-09 17:35:07 +08:00
|
|
|
|
activeWorlds: this.activeWorldCount,
|
2025-08-20 17:48:31 +08:00
|
|
|
|
totalScenes: 0,
|
|
|
|
|
|
totalEntities: 0,
|
|
|
|
|
|
totalSystems: 0,
|
|
|
|
|
|
memoryUsage: 0,
|
|
|
|
|
|
isRunning: this._isRunning,
|
|
|
|
|
|
config: { ...this._config },
|
|
|
|
|
|
worlds: [] as any[]
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-11-15 00:20:17 +08:00
|
|
|
|
for (const [worldName, world] of this._worlds) {
|
2025-08-20 17:48:31 +08:00
|
|
|
|
const worldStats = world.getStats();
|
|
|
|
|
|
stats.totalScenes += worldStats.totalSystems; // World的getStats可能需要调整
|
|
|
|
|
|
stats.totalEntities += worldStats.totalEntities;
|
|
|
|
|
|
stats.totalSystems += worldStats.totalSystems;
|
|
|
|
|
|
|
|
|
|
|
|
stats.worlds.push({
|
2025-11-15 00:20:17 +08:00
|
|
|
|
id: worldName,
|
2025-08-20 17:48:31 +08:00
|
|
|
|
name: world.name,
|
2025-11-09 17:35:07 +08:00
|
|
|
|
isActive: world.isActive,
|
2025-08-20 17:48:31 +08:00
|
|
|
|
sceneCount: world.sceneCount,
|
|
|
|
|
|
...worldStats
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return stats;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取详细状态信息
|
|
|
|
|
|
*/
|
|
|
|
|
|
public getDetailedStatus() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
...this.getStats(),
|
2025-11-15 00:20:17 +08:00
|
|
|
|
worlds: Array.from(this._worlds.entries()).map(([worldName, world]) => ({
|
|
|
|
|
|
id: worldName,
|
2025-11-09 17:35:07 +08:00
|
|
|
|
isActive: world.isActive,
|
2025-08-20 17:48:31 +08:00
|
|
|
|
status: world.getStatus()
|
|
|
|
|
|
}))
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 清理空World
|
|
|
|
|
|
*/
|
|
|
|
|
|
public cleanup(): number {
|
|
|
|
|
|
const worldsToRemove: string[] = [];
|
|
|
|
|
|
|
2025-11-15 00:20:17 +08:00
|
|
|
|
for (const [worldName, world] of this._worlds) {
|
2025-08-20 17:48:31 +08:00
|
|
|
|
if (this.shouldCleanupWorld(world)) {
|
2025-11-15 00:20:17 +08:00
|
|
|
|
worldsToRemove.push(worldName);
|
2025-08-20 17:48:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-15 00:20:17 +08:00
|
|
|
|
for (const worldName of worldsToRemove) {
|
|
|
|
|
|
this.removeWorld(worldName);
|
2025-08-20 17:48:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (worldsToRemove.length > 0) {
|
|
|
|
|
|
logger.debug(`清理了 ${worldsToRemove.length} 个World`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return worldsToRemove.length;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 销毁WorldManager
|
|
|
|
|
|
*/
|
|
|
|
|
|
public destroy(): void {
|
|
|
|
|
|
logger.info('正在销毁WorldManager...');
|
|
|
|
|
|
|
|
|
|
|
|
// 停止所有World
|
|
|
|
|
|
this.stopAll();
|
|
|
|
|
|
|
|
|
|
|
|
// 销毁所有World
|
2025-11-15 00:20:17 +08:00
|
|
|
|
const worldNames = Array.from(this._worlds.keys());
|
|
|
|
|
|
for (const worldName of worldNames) {
|
|
|
|
|
|
this.removeWorld(worldName);
|
2025-08-20 17:48:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this._worlds.clear();
|
|
|
|
|
|
this._isRunning = false;
|
|
|
|
|
|
|
|
|
|
|
|
logger.info('WorldManager已销毁');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-11 10:40:10 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 实现 IService 接口的 dispose 方法
|
|
|
|
|
|
* 调用 destroy 方法进行清理
|
|
|
|
|
|
*/
|
|
|
|
|
|
public dispose(): void {
|
|
|
|
|
|
this.destroy();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-20 17:48:31 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 判断World是否应该被清理
|
2025-11-09 17:35:07 +08:00
|
|
|
|
* 清理策略:
|
|
|
|
|
|
* 1. World未激活
|
|
|
|
|
|
* 2. 没有Scene或所有Scene都是空的
|
|
|
|
|
|
* 3. 创建时间超过10分钟
|
2025-08-20 17:48:31 +08:00
|
|
|
|
*/
|
|
|
|
|
|
private shouldCleanupWorld(world: World): boolean {
|
|
|
|
|
|
if (world.isActive) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-09 17:35:07 +08:00
|
|
|
|
const age = Date.now() - world.createdAt;
|
|
|
|
|
|
const isOldEnough = age > 10 * 60 * 1000; // 10分钟
|
|
|
|
|
|
|
2025-08-20 17:48:31 +08:00
|
|
|
|
if (world.sceneCount === 0) {
|
2025-11-09 17:35:07 +08:00
|
|
|
|
return isOldEnough;
|
2025-08-20 17:48:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否所有Scene都是空的
|
|
|
|
|
|
const allScenes = world.getAllScenes();
|
2025-11-09 17:35:07 +08:00
|
|
|
|
const hasEntities = allScenes.some((scene) => scene.entities && scene.entities.count > 0);
|
|
|
|
|
|
return !hasEntities && isOldEnough;
|
2025-08-20 17:48:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取World总数
|
|
|
|
|
|
*/
|
|
|
|
|
|
public get worldCount(): number {
|
|
|
|
|
|
return this._worlds.size;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取激活World数量
|
|
|
|
|
|
*/
|
|
|
|
|
|
public get activeWorldCount(): number {
|
2025-11-09 17:35:07 +08:00
|
|
|
|
let count = 0;
|
|
|
|
|
|
for (const world of this._worlds.values()) {
|
|
|
|
|
|
if (world.isActive) count++;
|
|
|
|
|
|
}
|
|
|
|
|
|
return count;
|
2025-08-20 17:48:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检查是否正在运行
|
|
|
|
|
|
*/
|
|
|
|
|
|
public get isRunning(): boolean {
|
|
|
|
|
|
return this._isRunning;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取配置
|
|
|
|
|
|
*/
|
|
|
|
|
|
public get config(): IWorldManagerConfig {
|
|
|
|
|
|
return { ...this._config };
|
|
|
|
|
|
}
|
2025-11-01 17:41:50 +08:00
|
|
|
|
}
|