Merge remote-tracking branch 'origin/master' into issue-94-响应式查询(Reactive_Query_System)/_Event-driven_Query
This commit is contained in:
@@ -47,6 +47,13 @@ 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;
|
||||
@@ -60,10 +67,8 @@ describe('World与Core集成测试', () => {
|
||||
Core.create({ debug: false });
|
||||
|
||||
// WorldManager和SceneManager不再是单例
|
||||
// SceneManager需要WorldManager的默认World,所以必须创建
|
||||
worldManager = new WorldManager({ createDefaultWorld: true });
|
||||
// SceneManager需要WorldManager实例
|
||||
sceneManager = new SceneManager(worldManager);
|
||||
worldManager = new WorldManager();
|
||||
sceneManager = new SceneManager();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -104,8 +109,7 @@ describe('World与Core集成测试', () => {
|
||||
const world1 = worldManager.createWorld('world1');
|
||||
const world2 = worldManager.createWorld('world2');
|
||||
|
||||
// worldManager已包含默认World,所以总数是3
|
||||
expect(worldManager.worldCount).toBe(3);
|
||||
expect(worldManager.worldCount).toBe(2);
|
||||
expect(worldManager.getWorld('world1')).toBe(world1);
|
||||
expect(worldManager.getWorld('world2')).toBe(world2);
|
||||
});
|
||||
@@ -133,7 +137,7 @@ describe('World与Core集成测试', () => {
|
||||
|
||||
// 游戏循环
|
||||
Core.update(0.016); // 更新全局服务
|
||||
worldManager.update(); // 更新所有World
|
||||
worldManager.updateAll(); // 更新所有World
|
||||
|
||||
expect(world.isActive).toBe(true);
|
||||
});
|
||||
@@ -146,7 +150,7 @@ describe('World与Core集成测试', () => {
|
||||
worldManager.setWorldActive('test-world', true);
|
||||
|
||||
// 更新World
|
||||
worldManager.update();
|
||||
worldManager.updateAll();
|
||||
|
||||
expect(globalSystem.syncCount).toBeGreaterThan(0);
|
||||
});
|
||||
@@ -154,8 +158,8 @@ describe('World与Core集成测试', () => {
|
||||
|
||||
describe('隔离性测试', () => {
|
||||
test('多个WorldManager实例应该完全隔离', () => {
|
||||
const manager1 = new WorldManager({ createDefaultWorld: false });
|
||||
const manager2 = new WorldManager({ createDefaultWorld: false });
|
||||
const manager1 = new WorldManager();
|
||||
const manager2 = new WorldManager();
|
||||
|
||||
manager1.createWorld('world1');
|
||||
manager2.createWorld('world2');
|
||||
@@ -171,10 +175,8 @@ describe('World与Core集成测试', () => {
|
||||
});
|
||||
|
||||
test('多个SceneManager实例应该完全隔离', () => {
|
||||
const wm1 = new WorldManager({ createDefaultWorld: true });
|
||||
const wm2 = new WorldManager({ createDefaultWorld: true });
|
||||
const sm1 = new SceneManager(wm1);
|
||||
const sm2 = new SceneManager(wm2);
|
||||
const sm1 = new SceneManager();
|
||||
const sm2 = new SceneManager();
|
||||
|
||||
const scene1 = new Scene();
|
||||
const scene2 = new Scene();
|
||||
@@ -188,8 +190,6 @@ describe('World与Core集成测试', () => {
|
||||
// 清理
|
||||
sm1.destroy();
|
||||
sm2.destroy();
|
||||
wm1.destroy();
|
||||
wm2.destroy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ import { EntitySystem } from '../../src/ECS/Systems/EntitySystem';
|
||||
import { Entity } from '../../src/ECS/Entity';
|
||||
import { Component } from '../../src/ECS/Component';
|
||||
import { Matcher } from '../../src/ECS/Utils/Matcher';
|
||||
import { Injectable, Inject } from '../../src/Core/DI';
|
||||
import { Injectable, Inject, InjectProperty } from '../../src/Core/DI';
|
||||
import { Core } from '../../src/Core';
|
||||
import type { IService } from '../../src/Core/ServiceContainer';
|
||||
import { ECSSystem } from '../../src/ECS/Decorators';
|
||||
@@ -423,4 +423,170 @@ describe('EntitySystem - 依赖注入测试', () => {
|
||||
expect(transform.y).toBeCloseTo(0.8, 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('属性注入 @InjectProperty', () => {
|
||||
test('应该支持单个属性注入', () => {
|
||||
@Injectable()
|
||||
@ECSSystem('Config')
|
||||
class GameConfig extends EntitySystem implements IService {
|
||||
public bulletDamage = 10;
|
||||
|
||||
constructor() {
|
||||
super(Matcher.empty());
|
||||
}
|
||||
override dispose() {}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@ECSSystem('Combat')
|
||||
class CombatSystem extends EntitySystem implements IService {
|
||||
@InjectProperty(GameConfig)
|
||||
gameConfig!: GameConfig;
|
||||
|
||||
constructor() {
|
||||
super(Matcher.empty().all(Health));
|
||||
}
|
||||
|
||||
protected override onInitialize(): void {
|
||||
expect(this.gameConfig).toBeInstanceOf(GameConfig);
|
||||
expect(this.gameConfig.bulletDamage).toBe(10);
|
||||
}
|
||||
|
||||
override dispose() {}
|
||||
}
|
||||
|
||||
scene.addEntityProcessor(GameConfig);
|
||||
scene.addEntityProcessor(CombatSystem);
|
||||
});
|
||||
|
||||
test('应该支持多个属性注入', () => {
|
||||
@Injectable()
|
||||
@ECSSystem('Time')
|
||||
class TimeService extends EntitySystem implements IService {
|
||||
public deltaTime = 0.016;
|
||||
constructor() {
|
||||
super(Matcher.empty());
|
||||
}
|
||||
override dispose() {}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@ECSSystem('Collision')
|
||||
class CollisionSystem extends EntitySystem implements IService {
|
||||
public checkCount = 0;
|
||||
constructor() {
|
||||
super(Matcher.empty());
|
||||
}
|
||||
override dispose() {}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@ECSSystem('Physics')
|
||||
class PhysicsSystem extends EntitySystem implements IService {
|
||||
@InjectProperty(TimeService)
|
||||
time!: TimeService;
|
||||
|
||||
@InjectProperty(CollisionSystem)
|
||||
collision!: CollisionSystem;
|
||||
|
||||
constructor() {
|
||||
super(Matcher.empty());
|
||||
}
|
||||
|
||||
protected override onInitialize(): void {
|
||||
expect(this.time).toBeInstanceOf(TimeService);
|
||||
expect(this.collision).toBeInstanceOf(CollisionSystem);
|
||||
expect(this.time.deltaTime).toBe(0.016);
|
||||
}
|
||||
|
||||
override dispose() {}
|
||||
}
|
||||
|
||||
scene.registerSystems([TimeService, CollisionSystem, PhysicsSystem]);
|
||||
});
|
||||
|
||||
test('属性注入应该在onInitialize之前完成', () => {
|
||||
@Injectable()
|
||||
@ECSSystem('Service')
|
||||
class TestService extends EntitySystem implements IService {
|
||||
public value = 42;
|
||||
constructor() {
|
||||
super(Matcher.empty());
|
||||
}
|
||||
override dispose() {}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@ECSSystem('Consumer')
|
||||
class ConsumerSystem extends EntitySystem implements IService {
|
||||
@InjectProperty(TestService)
|
||||
service!: TestService;
|
||||
|
||||
private initializeValue = 0;
|
||||
|
||||
constructor() {
|
||||
super(Matcher.empty());
|
||||
}
|
||||
|
||||
protected override onInitialize(): void {
|
||||
this.initializeValue = this.service.value;
|
||||
}
|
||||
|
||||
public getInitializeValue(): number {
|
||||
return this.initializeValue;
|
||||
}
|
||||
|
||||
override dispose() {}
|
||||
}
|
||||
|
||||
scene.addEntityProcessor(TestService);
|
||||
const consumer = scene.addEntityProcessor(ConsumerSystem);
|
||||
|
||||
expect(consumer.getInitializeValue()).toBe(42);
|
||||
});
|
||||
|
||||
test('属性注入可以与构造函数注入混合使用', () => {
|
||||
@Injectable()
|
||||
@ECSSystem('A')
|
||||
class ServiceA extends EntitySystem implements IService {
|
||||
public valueA = 'A';
|
||||
constructor() {
|
||||
super(Matcher.empty());
|
||||
}
|
||||
override dispose() {}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@ECSSystem('B')
|
||||
class ServiceB extends EntitySystem implements IService {
|
||||
public valueB = 'B';
|
||||
constructor() {
|
||||
super(Matcher.empty());
|
||||
}
|
||||
override dispose() {}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@ECSSystem('Mixed')
|
||||
class MixedSystem extends EntitySystem implements IService {
|
||||
@InjectProperty(ServiceB)
|
||||
serviceB!: ServiceB;
|
||||
|
||||
constructor(@Inject(ServiceA) public serviceA: ServiceA) {
|
||||
super(Matcher.empty());
|
||||
}
|
||||
|
||||
protected override onInitialize(): void {
|
||||
expect(this.serviceA).toBeInstanceOf(ServiceA);
|
||||
expect(this.serviceB).toBeInstanceOf(ServiceB);
|
||||
expect(this.serviceA.valueA).toBe('A');
|
||||
expect(this.serviceB.valueB).toBe('B');
|
||||
}
|
||||
|
||||
override dispose() {}
|
||||
}
|
||||
|
||||
scene.registerSystems([ServiceA, ServiceB, MixedSystem]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -464,7 +464,7 @@ describe('Incremental Serialization System', () => {
|
||||
const incremental = scene.serializeIncremental();
|
||||
const binary = IncrementalSerializer.serializeIncremental(incremental, { format: 'binary' });
|
||||
|
||||
expect(Buffer.isBuffer(binary)).toBe(true);
|
||||
expect(binary instanceof Uint8Array).toBe(true);
|
||||
|
||||
const deserialized = IncrementalSerializer.deserializeIncremental(binary);
|
||||
expect(deserialized.version).toBe(incremental.version);
|
||||
|
||||
@@ -557,14 +557,14 @@ describe('ECS Serialization System', () => {
|
||||
// 二进制序列化
|
||||
const binaryData = scene1.serialize({ format: 'binary' });
|
||||
|
||||
// 验证是Buffer类型
|
||||
expect(Buffer.isBuffer(binaryData)).toBe(true);
|
||||
// 验证是Uint8Array类型
|
||||
expect(binaryData instanceof Uint8Array).toBe(true);
|
||||
|
||||
// JSON序列化对比
|
||||
const jsonData = scene1.serialize({ format: 'json', pretty: false });
|
||||
|
||||
// 二进制应该更小
|
||||
const binarySize = (binaryData as Buffer).length;
|
||||
const binarySize = (binaryData as Uint8Array).length;
|
||||
const jsonSize = (jsonData as string).length;
|
||||
console.log(`Binary size: ${binarySize} bytes, JSON size: ${jsonSize} bytes`);
|
||||
expect(binarySize).toBeLessThan(jsonSize);
|
||||
|
||||
@@ -42,8 +42,7 @@ describe('WorldManager', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
// WorldManager不再是单例,直接创建新实例
|
||||
// 测试时不创建默认World
|
||||
worldManager = new WorldManager({ createDefaultWorld: false });
|
||||
worldManager = new WorldManager();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -60,8 +59,8 @@ describe('WorldManager', () => {
|
||||
|
||||
describe('实例化', () => {
|
||||
test('可以创建多个独立的WorldManager实例', () => {
|
||||
const manager1 = new WorldManager({ createDefaultWorld: false });
|
||||
const manager2 = new WorldManager({ createDefaultWorld: false });
|
||||
const manager1 = new WorldManager();
|
||||
const manager2 = new WorldManager();
|
||||
|
||||
expect(manager1).not.toBe(manager2);
|
||||
|
||||
@@ -77,8 +76,7 @@ describe('WorldManager', () => {
|
||||
const config: IWorldManagerConfig = {
|
||||
maxWorlds: 10,
|
||||
autoCleanup: true,
|
||||
debug: false,
|
||||
createDefaultWorld: false
|
||||
debug: false
|
||||
};
|
||||
|
||||
const instance = new WorldManager(config);
|
||||
@@ -123,7 +121,7 @@ describe('WorldManager', () => {
|
||||
});
|
||||
|
||||
test('超出最大World数量应该抛出错误', () => {
|
||||
const limitedManager = new WorldManager({ maxWorlds: 2, createDefaultWorld: false });
|
||||
const limitedManager = new WorldManager({ maxWorlds: 2 });
|
||||
|
||||
limitedManager.createWorld('world1');
|
||||
limitedManager.createWorld('world2');
|
||||
@@ -430,8 +428,7 @@ describe('WorldManager', () => {
|
||||
const invalidConfig: IWorldManagerConfig = {
|
||||
maxWorlds: -1,
|
||||
autoCleanup: true,
|
||||
debug: true,
|
||||
createDefaultWorld: false
|
||||
debug: true
|
||||
};
|
||||
|
||||
const manager = new WorldManager(invalidConfig);
|
||||
@@ -445,8 +442,7 @@ describe('WorldManager', () => {
|
||||
const config: IWorldManagerConfig = {
|
||||
maxWorlds: 3,
|
||||
autoCleanup: true,
|
||||
debug: true,
|
||||
createDefaultWorld: false
|
||||
debug: true
|
||||
};
|
||||
|
||||
const manager = new WorldManager(config);
|
||||
|
||||
Reference in New Issue
Block a user