refactor(core): 移除 _activeWorlds 并优化 WorldManager 清理机制 (#220)
* refactor(core): 将 WorldManager 清理机制从定时器改为帧驱动 * refactor(core): 移除 WorldManager _activeWorlds 优化,简化状态管理 * test(core): 补充 WorldManager 测试用例 * docs(core): 更新 WorldManager cleanupFrameInterval 配置说明
This commit is contained in:
@@ -435,7 +435,7 @@ const worldManager = Core.services.resolve(WorldManager);
|
||||
// {
|
||||
// maxWorlds: 50,
|
||||
// autoCleanup: true,
|
||||
// cleanupInterval: 30000 // 30 秒
|
||||
// cleanupFrameInterval: 1800 // 间隔多少帧清理闲置 World
|
||||
// }
|
||||
```
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@ export interface IWorldManagerConfig {
|
||||
autoCleanup?: boolean;
|
||||
|
||||
/**
|
||||
* 清理间隔(毫秒)
|
||||
* 清理间隔(帧数)
|
||||
*/
|
||||
cleanupInterval?: number;
|
||||
cleanupFrameInterval?: number;
|
||||
|
||||
/**
|
||||
* 是否启用调试模式
|
||||
@@ -63,17 +63,16 @@ export interface IWorldManagerConfig {
|
||||
* ```
|
||||
*/
|
||||
export class WorldManager implements IService {
|
||||
private readonly _config: IWorldManagerConfig;
|
||||
private readonly _config: Required<IWorldManagerConfig>;
|
||||
private readonly _worlds: Map<string, World> = new Map();
|
||||
private readonly _activeWorlds: Set<string> = new Set();
|
||||
private _cleanupTimer: ReturnType<typeof setInterval> | null = null;
|
||||
private _isRunning: boolean = false;
|
||||
private _framesSinceCleanup: number = 0;
|
||||
|
||||
public constructor(config: IWorldManagerConfig = {}) {
|
||||
this._config = {
|
||||
maxWorlds: 50,
|
||||
autoCleanup: true,
|
||||
cleanupInterval: 30000, // 30秒
|
||||
cleanupFrameInterval: 1800, // 1800帧
|
||||
debug: false,
|
||||
...config
|
||||
};
|
||||
@@ -84,10 +83,8 @@ export class WorldManager implements IService {
|
||||
logger.info('WorldManager已初始化', {
|
||||
maxWorlds: this._config.maxWorlds,
|
||||
autoCleanup: this._config.autoCleanup,
|
||||
cleanupInterval: this._config.cleanupInterval
|
||||
cleanupFrameInterval: this._config.cleanupFrameInterval
|
||||
});
|
||||
|
||||
this.startCleanupTimer();
|
||||
}
|
||||
|
||||
// ===== World管理 =====
|
||||
@@ -131,11 +128,6 @@ export class WorldManager implements IService {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果World正在运行,先停止它
|
||||
if (this._activeWorlds.has(worldId)) {
|
||||
this.setWorldActive(worldId, false);
|
||||
}
|
||||
|
||||
// 销毁World
|
||||
world.destroy();
|
||||
this._worlds.delete(worldId);
|
||||
@@ -176,11 +168,9 @@ export class WorldManager implements IService {
|
||||
}
|
||||
|
||||
if (active) {
|
||||
this._activeWorlds.add(worldId);
|
||||
world.start();
|
||||
logger.debug(`激活World: ${worldId}`);
|
||||
} else {
|
||||
this._activeWorlds.delete(worldId);
|
||||
world.stop();
|
||||
logger.debug(`停用World: ${worldId}`);
|
||||
}
|
||||
@@ -190,7 +180,8 @@ export class WorldManager implements IService {
|
||||
* 检查World是否激活
|
||||
*/
|
||||
public isWorldActive(worldId: string): boolean {
|
||||
return this._activeWorlds.has(worldId);
|
||||
const world = this._worlds.get(worldId);
|
||||
return world?.isActive ?? false;
|
||||
}
|
||||
|
||||
// ===== 批量操作 =====
|
||||
@@ -212,9 +203,8 @@ export class WorldManager implements IService {
|
||||
public updateAll(): void {
|
||||
if (!this._isRunning) return;
|
||||
|
||||
for (const worldId of this._activeWorlds) {
|
||||
const world = this._worlds.get(worldId);
|
||||
if (world && world.isActive) {
|
||||
for (const world of this._worlds.values()) {
|
||||
if (world.isActive) {
|
||||
// 更新World的全局System
|
||||
world.updateGlobalSystems();
|
||||
|
||||
@@ -222,6 +212,20 @@ export class WorldManager implements IService {
|
||||
world.updateScenes();
|
||||
}
|
||||
}
|
||||
|
||||
// 基于帧的自动清理
|
||||
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} 帧)`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,9 +233,8 @@ export class WorldManager implements IService {
|
||||
*/
|
||||
public getActiveWorlds(): World[] {
|
||||
const activeWorlds: World[] = [];
|
||||
for (const worldId of this._activeWorlds) {
|
||||
const world = this._worlds.get(worldId);
|
||||
if (world) {
|
||||
for (const world of this._worlds.values()) {
|
||||
if (world.isActive) {
|
||||
activeWorlds.push(world);
|
||||
}
|
||||
}
|
||||
@@ -244,8 +247,8 @@ export class WorldManager implements IService {
|
||||
public startAll(): void {
|
||||
this._isRunning = true;
|
||||
|
||||
for (const worldId of this._worlds.keys()) {
|
||||
this.setWorldActive(worldId, true);
|
||||
for (const world of this._worlds.values()) {
|
||||
world.start();
|
||||
}
|
||||
|
||||
logger.info('启动所有World');
|
||||
@@ -257,8 +260,8 @@ export class WorldManager implements IService {
|
||||
public stopAll(): void {
|
||||
this._isRunning = false;
|
||||
|
||||
for (const worldId of this._activeWorlds) {
|
||||
this.setWorldActive(worldId, false);
|
||||
for (const world of this._worlds.values()) {
|
||||
world.stop();
|
||||
}
|
||||
|
||||
logger.info('停止所有World');
|
||||
@@ -297,7 +300,7 @@ export class WorldManager implements IService {
|
||||
public getStats() {
|
||||
const stats = {
|
||||
totalWorlds: this._worlds.size,
|
||||
activeWorlds: this._activeWorlds.size,
|
||||
activeWorlds: this.activeWorldCount,
|
||||
totalScenes: 0,
|
||||
totalEntities: 0,
|
||||
totalSystems: 0,
|
||||
@@ -316,7 +319,7 @@ export class WorldManager implements IService {
|
||||
stats.worlds.push({
|
||||
id: worldId,
|
||||
name: world.name,
|
||||
isActive: this._activeWorlds.has(worldId),
|
||||
isActive: world.isActive,
|
||||
sceneCount: world.sceneCount,
|
||||
...worldStats
|
||||
});
|
||||
@@ -333,7 +336,7 @@ export class WorldManager implements IService {
|
||||
...this.getStats(),
|
||||
worlds: Array.from(this._worlds.entries()).map(([worldId, world]) => ({
|
||||
id: worldId,
|
||||
isActive: this._activeWorlds.has(worldId),
|
||||
isActive: world.isActive,
|
||||
status: world.getStatus()
|
||||
}))
|
||||
};
|
||||
@@ -370,9 +373,6 @@ export class WorldManager implements IService {
|
||||
public destroy(): void {
|
||||
logger.info('正在销毁WorldManager...');
|
||||
|
||||
// 停止清理定时器
|
||||
this.stopCleanupTimer();
|
||||
|
||||
// 停止所有World
|
||||
this.stopAll();
|
||||
|
||||
@@ -383,7 +383,6 @@ export class WorldManager implements IService {
|
||||
}
|
||||
|
||||
this._worlds.clear();
|
||||
this._activeWorlds.clear();
|
||||
this._isRunning = false;
|
||||
|
||||
logger.info('WorldManager已销毁');
|
||||
@@ -399,62 +398,29 @@ export class WorldManager implements IService {
|
||||
|
||||
// ===== 私有方法 =====
|
||||
|
||||
/**
|
||||
* 启动清理定时器
|
||||
*/
|
||||
private startCleanupTimer(): void {
|
||||
if (!this._config.autoCleanup || this._cleanupTimer) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._cleanupTimer = setInterval(() => {
|
||||
this.cleanup();
|
||||
}, this._config.cleanupInterval);
|
||||
|
||||
logger.debug(`启动World清理定时器,间隔: ${this._config.cleanupInterval}ms`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止清理定时器
|
||||
*/
|
||||
private stopCleanupTimer(): void {
|
||||
if (this._cleanupTimer) {
|
||||
clearInterval(this._cleanupTimer);
|
||||
this._cleanupTimer = null;
|
||||
logger.debug('停止World清理定时器');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断World是否应该被清理
|
||||
* 清理策略:
|
||||
* 1. World未激活
|
||||
* 2. 没有Scene或所有Scene都是空的
|
||||
* 3. 创建时间超过10分钟
|
||||
*/
|
||||
private shouldCleanupWorld(world: World): boolean {
|
||||
// 清理策略:
|
||||
// 1. World未激活
|
||||
// 2. 没有Scene或所有Scene都是空的
|
||||
// 3. 创建时间超过10分钟
|
||||
|
||||
if (world.isActive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (world.sceneCount === 0) {
|
||||
const age = Date.now() - world.createdAt;
|
||||
return age > 10 * 60 * 1000; // 10分钟
|
||||
const isOldEnough = age > 10 * 60 * 1000; // 10分钟
|
||||
|
||||
if (world.sceneCount === 0) {
|
||||
return isOldEnough;
|
||||
}
|
||||
|
||||
// 检查是否所有Scene都是空的
|
||||
const allScenes = world.getAllScenes();
|
||||
const hasEntities = allScenes.some((scene) =>
|
||||
scene.entities && scene.entities.count > 0
|
||||
);
|
||||
|
||||
if (!hasEntities) {
|
||||
const age = Date.now() - world.createdAt;
|
||||
return age > 10 * 60 * 1000; // 10分钟
|
||||
}
|
||||
|
||||
return false;
|
||||
const hasEntities = allScenes.some((scene) => scene.entities && scene.entities.count > 0);
|
||||
return !hasEntities && isOldEnough;
|
||||
}
|
||||
|
||||
// ===== 访问器 =====
|
||||
@@ -470,7 +436,11 @@ export class WorldManager implements IService {
|
||||
* 获取激活World数量
|
||||
*/
|
||||
public get activeWorldCount(): number {
|
||||
return this._activeWorlds.size;
|
||||
let count = 0;
|
||||
for (const world of this._worlds.values()) {
|
||||
if (world.isActive) count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { WorldManager, IWorldManagerConfig } from '../../src/ECS/WorldManager';
|
||||
import { World, IWorldConfig } from '../../src/ECS/World';
|
||||
import { Scene } from '../../src/ECS/Scene';
|
||||
import { EntitySystem } from '../../src/ECS/Systems/EntitySystem';
|
||||
import { IWorldConfig, World } from '../../src/ECS/World';
|
||||
import { Component } from '../../src/ECS/Component';
|
||||
import { Matcher } from '../../src/ECS/Utils/Matcher';
|
||||
|
||||
// 测试用组件
|
||||
class TestComponent extends Component {
|
||||
@@ -49,7 +46,7 @@ describe('WorldManager', () => {
|
||||
// 清理所有World
|
||||
if (worldManager) {
|
||||
const worldIds = worldManager.getWorldIds();
|
||||
worldIds.forEach(id => {
|
||||
worldIds.forEach((id) => {
|
||||
worldManager.removeWorld(id);
|
||||
});
|
||||
// 清理定时器
|
||||
@@ -128,7 +125,7 @@ describe('WorldManager', () => {
|
||||
|
||||
expect(() => {
|
||||
limitedManager.createWorld('world3');
|
||||
}).toThrow("已达到最大World数量限制: 2");
|
||||
}).toThrow('已达到最大World数量限制: 2');
|
||||
|
||||
// 清理
|
||||
limitedManager.destroy();
|
||||
@@ -194,7 +191,7 @@ describe('WorldManager', () => {
|
||||
});
|
||||
|
||||
test('停止World应该从活跃列表移除', () => {
|
||||
const world = worldManager.createWorld('inactive-world');
|
||||
worldManager.createWorld('inactive-world');
|
||||
worldManager.setWorldActive('inactive-world', true);
|
||||
|
||||
worldManager.setWorldActive('inactive-world', false);
|
||||
@@ -204,7 +201,7 @@ describe('WorldManager', () => {
|
||||
});
|
||||
|
||||
test('销毁激活的World应该从活跃列表移除', () => {
|
||||
const world = worldManager.createWorld('destroy-active');
|
||||
worldManager.createWorld('destroy-active');
|
||||
worldManager.setWorldActive('destroy-active', true);
|
||||
|
||||
worldManager.removeWorld('destroy-active');
|
||||
@@ -234,7 +231,7 @@ describe('WorldManager', () => {
|
||||
describe('统计和监控', () => {
|
||||
test('获取WorldManager状态应该正确', () => {
|
||||
worldManager.createWorld('status-world1');
|
||||
const world2 = worldManager.createWorld('status-world2');
|
||||
worldManager.createWorld('status-world2');
|
||||
worldManager.setWorldActive('status-world2', true);
|
||||
|
||||
const status = worldManager.getStats();
|
||||
@@ -248,7 +245,7 @@ describe('WorldManager', () => {
|
||||
|
||||
test('获取所有World统计应该包含详细信息', () => {
|
||||
const world1 = worldManager.createWorld('stats-world1');
|
||||
const world2 = worldManager.createWorld('stats-world2');
|
||||
worldManager.createWorld('stats-world2');
|
||||
|
||||
// 为world1添加一些内容
|
||||
const scene1 = world1.createScene('scene1');
|
||||
@@ -261,8 +258,8 @@ describe('WorldManager', () => {
|
||||
|
||||
expect(allStats).toHaveLength(2);
|
||||
|
||||
const world1Stats = allStats.find(stat => stat.id === 'stats-world1');
|
||||
const world2Stats = allStats.find(stat => stat.id === 'stats-world2');
|
||||
const world1Stats = allStats.find((stat) => stat.id === 'stats-world1');
|
||||
const world2Stats = allStats.find((stat) => stat.id === 'stats-world2');
|
||||
|
||||
expect(world1Stats).toBeDefined();
|
||||
expect(world2Stats).toBeDefined();
|
||||
@@ -283,7 +280,7 @@ describe('WorldManager', () => {
|
||||
describe('清理功能', () => {
|
||||
test('清理空闲World应该移除符合条件的World', () => {
|
||||
// 创建一个空的World
|
||||
const emptyWorld = worldManager.createWorld('empty-world');
|
||||
worldManager.createWorld('empty-world');
|
||||
|
||||
// 创建一个有内容的World
|
||||
const fullWorld = worldManager.createWorld('full-world');
|
||||
@@ -298,13 +295,108 @@ describe('WorldManager', () => {
|
||||
expect(cleanedCount).toBeGreaterThanOrEqual(0);
|
||||
expect(() => worldManager.cleanup()).not.toThrow();
|
||||
});
|
||||
|
||||
test('应该在指定帧数后自动执行清理', () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
const manager = new WorldManager({
|
||||
autoCleanup: true,
|
||||
cleanupFrameInterval: 10 // 10 帧后清理
|
||||
});
|
||||
|
||||
manager.createWorld('test');
|
||||
// 模拟一个空的老 World (超过 10 分钟)
|
||||
jest.advanceTimersByTime(11 * 60 * 1000);
|
||||
|
||||
// 执行 9 帧,不应该清理
|
||||
for (let i = 0; i < 9; i++) {
|
||||
manager.updateAll();
|
||||
}
|
||||
expect(manager.getWorld('test')).not.toBeNull();
|
||||
|
||||
// 第 10 帧,应该清理
|
||||
manager.updateAll();
|
||||
expect(manager.getWorld('test')).toBeNull();
|
||||
|
||||
jest.useRealTimers();
|
||||
manager.destroy();
|
||||
});
|
||||
|
||||
test('autoCleanup=false 时不应该自动清理', () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
const manager = new WorldManager({
|
||||
autoCleanup: false
|
||||
});
|
||||
|
||||
manager.createWorld('test');
|
||||
jest.advanceTimersByTime(20 * 60 * 1000);
|
||||
|
||||
// 执行多帧
|
||||
for (let i = 0; i < 2000; i++) {
|
||||
manager.updateAll();
|
||||
}
|
||||
|
||||
// 不应该清理
|
||||
expect(manager.getWorld('test')).not.toBeNull();
|
||||
|
||||
jest.useRealTimers();
|
||||
manager.destroy();
|
||||
});
|
||||
|
||||
test('清理后计数器应该重置', () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
const manager = new WorldManager({
|
||||
autoCleanup: true,
|
||||
cleanupFrameInterval: 10
|
||||
});
|
||||
|
||||
manager.createWorld('world1');
|
||||
jest.advanceTimersByTime(11 * 60 * 1000);
|
||||
|
||||
// 第 10 帧触发清理
|
||||
for (let i = 0; i < 10; i++) {
|
||||
manager.updateAll();
|
||||
}
|
||||
|
||||
// world1 被清理
|
||||
expect(manager.getWorld('world1')).toBeNull();
|
||||
|
||||
// 创建新 World
|
||||
manager.createWorld('world2');
|
||||
jest.advanceTimersByTime(11 * 60 * 1000);
|
||||
|
||||
// 又要等 10 帧才能清理 (计数器已重置)
|
||||
for (let i = 0; i < 9; i++) {
|
||||
manager.updateAll();
|
||||
}
|
||||
expect(manager.getWorld('world2')).not.toBeNull();
|
||||
|
||||
manager.updateAll();
|
||||
expect(manager.getWorld('world2')).toBeNull();
|
||||
|
||||
jest.useRealTimers();
|
||||
manager.destroy();
|
||||
});
|
||||
|
||||
test('应该使用配置的 cleanupFrameInterval', () => {
|
||||
const manager = new WorldManager({
|
||||
autoCleanup: true,
|
||||
cleanupFrameInterval: 5
|
||||
});
|
||||
|
||||
expect(manager.config.cleanupFrameInterval).toBe(5);
|
||||
|
||||
manager.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('World更新协调', () => {
|
||||
test('更新所有活跃World应该正确', () => {
|
||||
const world1 = worldManager.createWorld('update-world1');
|
||||
const world2 = worldManager.createWorld('update-world2');
|
||||
const world3 = worldManager.createWorld('update-world3');
|
||||
worldManager.createWorld('update-world3');
|
||||
|
||||
// 添加一些内容到World中
|
||||
const scene1 = world1.createScene('scene1');
|
||||
@@ -322,7 +414,7 @@ describe('WorldManager', () => {
|
||||
const activeWorlds = worldManager.getActiveWorlds();
|
||||
|
||||
expect(() => {
|
||||
activeWorlds.forEach(world => {
|
||||
activeWorlds.forEach((world) => {
|
||||
world.updateGlobalSystems();
|
||||
world.updateScenes();
|
||||
});
|
||||
@@ -330,6 +422,64 @@ describe('WorldManager', () => {
|
||||
|
||||
expect(activeWorlds).toHaveLength(2);
|
||||
});
|
||||
|
||||
test('updateAll 应该只更新活跃的 World', () => {
|
||||
const world1 = worldManager.createWorld('world1');
|
||||
const world2 = worldManager.createWorld('world2');
|
||||
|
||||
const system1 = new TestGlobalSystem();
|
||||
const system2 = new TestGlobalSystem();
|
||||
|
||||
world1.addGlobalSystem(system1);
|
||||
world2.addGlobalSystem(system2);
|
||||
|
||||
worldManager.setWorldActive('world1', true);
|
||||
// world2 保持未激活
|
||||
|
||||
worldManager.updateAll();
|
||||
|
||||
expect(system1.updateCount).toBe(1); // world1 被更新
|
||||
expect(system2.updateCount).toBe(0); // world2 未被更新
|
||||
});
|
||||
|
||||
test('isRunning=false 时 updateAll 不应该更新任何 World', () => {
|
||||
const world = worldManager.createWorld('world');
|
||||
const system = new TestGlobalSystem();
|
||||
world.addGlobalSystem(system);
|
||||
worldManager.setWorldActive('world', true);
|
||||
|
||||
worldManager.stopAll(); // isRunning = false
|
||||
worldManager.updateAll();
|
||||
|
||||
expect(system.updateCount).toBe(0);
|
||||
});
|
||||
|
||||
test('updateAll 应该正确处理多个活跃和非活跃 World', () => {
|
||||
const worlds: World[] = [];
|
||||
const systems: TestGlobalSystem[] = [];
|
||||
|
||||
// 创建 5 个 World
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const world = worldManager.createWorld(`world${i}`);
|
||||
const system = new TestGlobalSystem();
|
||||
world.addGlobalSystem(system);
|
||||
worlds.push(world);
|
||||
systems.push(system);
|
||||
}
|
||||
|
||||
// 激活第 0, 2, 4 个
|
||||
worldManager.setWorldActive('world0', true);
|
||||
worldManager.setWorldActive('world2', true);
|
||||
worldManager.setWorldActive('world4', true);
|
||||
|
||||
worldManager.updateAll();
|
||||
|
||||
expect(systems[0].updateCount).toBe(1); // 活跃
|
||||
expect(systems[1].updateCount).toBe(0); // 非活跃
|
||||
expect(systems[2].updateCount).toBe(1); // 活跃
|
||||
expect(systems[3].updateCount).toBe(0); // 非活跃
|
||||
expect(systems[4].updateCount).toBe(1); // 活跃
|
||||
});
|
||||
});
|
||||
|
||||
describe('边界情况和错误处理', () => {
|
||||
@@ -341,11 +491,11 @@ describe('WorldManager', () => {
|
||||
|
||||
test('World ID为null或undefined应该抛出错误', () => {
|
||||
expect(() => {
|
||||
worldManager.createWorld(null as any);
|
||||
worldManager.createWorld(null as unknown as string);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
worldManager.createWorld(undefined as any);
|
||||
worldManager.createWorld(undefined as unknown as string);
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
@@ -373,7 +523,7 @@ describe('WorldManager', () => {
|
||||
expect(worldManager.getActiveWorlds()).toHaveLength(worldCount / 2);
|
||||
|
||||
// 批量清理
|
||||
worldIds.forEach(id => {
|
||||
worldIds.forEach((id) => {
|
||||
expect(() => {
|
||||
worldManager.removeWorld(id);
|
||||
}).not.toThrow();
|
||||
@@ -413,7 +563,7 @@ describe('WorldManager', () => {
|
||||
|
||||
// 清理所有World
|
||||
const worldIds = worldManager.getWorldIds();
|
||||
worldIds.forEach(id => {
|
||||
worldIds.forEach((id) => {
|
||||
worldManager.removeWorld(id);
|
||||
});
|
||||
|
||||
@@ -461,4 +611,95 @@ describe('WorldManager', () => {
|
||||
manager.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('isWorldActive()', () => {
|
||||
test('应该正确返回 World 激活状态', () => {
|
||||
worldManager.createWorld('test');
|
||||
|
||||
// 初始未激活
|
||||
expect(worldManager.isWorldActive('test')).toBe(false);
|
||||
|
||||
// 激活后
|
||||
worldManager.setWorldActive('test', true);
|
||||
expect(worldManager.isWorldActive('test')).toBe(true);
|
||||
|
||||
// 停用后
|
||||
worldManager.setWorldActive('test', false);
|
||||
expect(worldManager.isWorldActive('test')).toBe(false);
|
||||
});
|
||||
|
||||
test('不存在的 World 应该返回 false', () => {
|
||||
expect(worldManager.isWorldActive('non-existent')).toBe(false);
|
||||
});
|
||||
|
||||
test('应该与 world.isActive 保持一致', () => {
|
||||
const world = worldManager.createWorld('test');
|
||||
|
||||
expect(worldManager.isWorldActive('test')).toBe(world.isActive);
|
||||
|
||||
worldManager.setWorldActive('test', true);
|
||||
expect(worldManager.isWorldActive('test')).toBe(world.isActive);
|
||||
|
||||
worldManager.setWorldActive('test', false);
|
||||
expect(worldManager.isWorldActive('test')).toBe(world.isActive);
|
||||
});
|
||||
});
|
||||
|
||||
describe('activeWorldCount', () => {
|
||||
test('应该正确返回激活的 World 数量', () => {
|
||||
expect(worldManager.activeWorldCount).toBe(0);
|
||||
|
||||
worldManager.createWorld('world1');
|
||||
worldManager.createWorld('world2');
|
||||
worldManager.createWorld('world3');
|
||||
|
||||
expect(worldManager.activeWorldCount).toBe(0);
|
||||
|
||||
worldManager.setWorldActive('world1', true);
|
||||
expect(worldManager.activeWorldCount).toBe(1);
|
||||
|
||||
worldManager.setWorldActive('world2', true);
|
||||
expect(worldManager.activeWorldCount).toBe(2);
|
||||
|
||||
worldManager.setWorldActive('world1', false);
|
||||
expect(worldManager.activeWorldCount).toBe(1);
|
||||
});
|
||||
|
||||
test('应该与 getActiveWorlds().length 一致', () => {
|
||||
worldManager.createWorld('world1');
|
||||
worldManager.createWorld('world2');
|
||||
worldManager.setWorldActive('world1', true);
|
||||
|
||||
expect(worldManager.activeWorldCount).toBe(worldManager.getActiveWorlds().length);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAllWorlds()', () => {
|
||||
test('应该返回所有 World', () => {
|
||||
const world1 = worldManager.createWorld('world1');
|
||||
const world2 = worldManager.createWorld('world2');
|
||||
const world3 = worldManager.createWorld('world3');
|
||||
|
||||
const allWorlds = worldManager.getAllWorlds();
|
||||
|
||||
expect(allWorlds).toHaveLength(3);
|
||||
expect(allWorlds).toContain(world1);
|
||||
expect(allWorlds).toContain(world2);
|
||||
expect(allWorlds).toContain(world3);
|
||||
});
|
||||
|
||||
test('空 WorldManager 应该返回空数组', () => {
|
||||
const allWorlds = worldManager.getAllWorlds();
|
||||
expect(allWorlds).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('返回的数组修改不应该影响内部状态', () => {
|
||||
worldManager.createWorld('world1');
|
||||
|
||||
const allWorlds = worldManager.getAllWorlds();
|
||||
allWorlds.push({} as unknown as World);
|
||||
|
||||
expect(worldManager.getAllWorlds()).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user