支持二进制序列化

This commit is contained in:
YHH
2025-10-08 20:42:55 +08:00
parent 06b3f92007
commit 69c46f32eb
9 changed files with 205 additions and 288 deletions

View File

@@ -501,21 +501,26 @@ export class Scene implements IScene {
/**
* 序列化场景
*
* 将场景及其所有实体、组件序列化为JSON字符串
* 将场景及其所有实体、组件序列化为JSON字符串或二进制Buffer
*
* @param options 序列化选项
* @returns 序列化后的JSON字符串
* @returns 序列化后的数据(JSON字符串或二进制Buffer
*
* @example
* ```typescript
* const saveData = scene.serialize({
* components: [PlayerComponent, PositionComponent],
* // JSON格式
* const jsonData = scene.serialize({
* format: 'json',
* pretty: true
* });
*
* // 二进制格式(更小、更快)
* const binaryData = scene.serialize({
* format: 'binary'
* });
* ```
*/
public serialize(options?: SceneSerializationOptions): string {
public serialize(options?: SceneSerializationOptions): string | Buffer {
return SceneSerializer.serialize(this, options);
}
@@ -524,19 +529,23 @@ export class Scene implements IScene {
*
* 从序列化数据恢复场景状态
*
* @param saveData 序列化的数据
* @param saveData 序列化的数据JSON字符串或二进制Buffer
* @param options 反序列化选项
*
* @example
* ```typescript
* scene.deserialize(saveData, {
* strategy: 'replace',
* preserveIds: false,
* componentRegistry: ComponentTypeRegistry.getRegistry()
* // 从JSON恢复自动从ComponentRegistry获取组件类型
* scene.deserialize(jsonData, {
* strategy: 'replace'
* });
*
* // 从二进制恢复
* scene.deserialize(binaryData, {
* strategy: 'replace'
* });
* ```
*/
public deserialize(saveData: string, options?: SceneDeserializationOptions): void {
public deserialize(saveData: string | Buffer, options?: SceneDeserializationOptions): void {
SceneSerializer.deserialize(this, saveData, options);
}
}

View File

@@ -1,194 +0,0 @@
/**
* 全局组件类型注册表
*
* 用于序列化系统的组件类型查找和管理
*/
import { Component } from '../Component';
import { ComponentType } from '../Core/ComponentStorage';
import { getComponentTypeName } from '../Decorators';
/**
* 全局组件类型注册表
*
* 维护组件类型名称到构造函数的映射,用于序列化/反序列化
*/
export class ComponentTypeRegistry {
/**
* 组件类型映射表
* Map<类型名称, 构造函数>
*/
private static registry = new Map<string, ComponentType>();
/**
* 注册组件类型
*
* @param componentClass 组件构造函数
* @param typeName 组件类型名称(可选,默认使用类名或@ECSComponent装饰器指定的名称
*
* @example
* ```typescript
* @ECSComponent('Player')
* @Serializable({ version: 1 })
* class PlayerComponent extends Component {
* @Serialize() name: string = '';
* }
*
* // 注册组件
* ComponentTypeRegistry.register(PlayerComponent);
* ```
*/
public static register(componentClass: ComponentType, typeName?: string): void {
const name = typeName || getComponentTypeName(componentClass);
if (this.registry.has(name)) {
console.warn(`Component type "${name}" is already registered, overwriting...`);
}
this.registry.set(name, componentClass);
}
/**
* 批量注册组件类型
*
* @param componentClasses 组件构造函数数组
*
* @example
* ```typescript
* ComponentTypeRegistry.registerMany([
* PlayerComponent,
* PositionComponent,
* VelocityComponent
* ]);
* ```
*/
public static registerMany(componentClasses: ComponentType[]): void {
for (const componentClass of componentClasses) {
this.register(componentClass);
}
}
/**
* 获取组件类型
*
* @param typeName 组件类型名称
* @returns 组件构造函数如果未找到则返回undefined
*/
public static get(typeName: string): ComponentType | undefined {
return this.registry.get(typeName);
}
/**
* 检查组件类型是否已注册
*
* @param typeName 组件类型名称
* @returns 如果已注册返回true
*/
public static has(typeName: string): boolean {
return this.registry.has(typeName);
}
/**
* 取消注册组件类型
*
* @param typeName 组件类型名称
* @returns 如果成功取消注册返回true
*/
public static unregister(typeName: string): boolean {
return this.registry.delete(typeName);
}
/**
* 清空注册表
*/
public static clear(): void {
this.registry.clear();
}
/**
* 获取所有已注册的组件类型名称
*
* @returns 组件类型名称数组
*/
public static getAllTypeNames(): string[] {
return Array.from(this.registry.keys());
}
/**
* 获取所有已注册的组件类型
*
* @returns 组件构造函数数组
*/
public static getAllTypes(): ComponentType[] {
return Array.from(this.registry.values());
}
/**
* 获取注册表的Map副本
*
* @returns 组件类型注册表的副本
*/
public static getRegistry(): Map<string, ComponentType> {
return new Map(this.registry);
}
/**
* 获取注册的组件数量
*
* @returns 已注册的组件类型数量
*/
public static get size(): number {
return this.registry.size;
}
/**
* 从组件实例获取类型名称
*
* @param component 组件实例
* @returns 组件类型名称
*/
public static getTypeName(component: Component): string {
return getComponentTypeName(component.constructor as ComponentType);
}
/**
* 根据组件类查找已注册的类型名称
*
* @param componentClass 组件构造函数
* @returns 类型名称如果未注册则返回undefined
*/
public static findTypeName(componentClass: ComponentType): string | undefined {
const typeName = getComponentTypeName(componentClass);
// 检查是否已注册
if (this.registry.get(typeName) === componentClass) {
return typeName;
}
// 遍历查找
for (const [name, cls] of this.registry) {
if (cls === componentClass) {
return name;
}
}
return undefined;
}
/**
* 自动发现并注册所有装饰的组件
*
* 注意:此方法需要组件类已经被加载到内存中
*
* @param components 组件类数组
*/
public static autoRegister(components: ComponentType[]): void {
for (const component of components) {
try {
this.register(component);
} catch (error) {
console.error(`Failed to auto-register component ${component.name}:`, error);
}
}
}
}

View File

@@ -7,11 +7,11 @@
import type { IScene } from '../IScene';
import { Entity } from '../Entity';
import { Component } from '../Component';
import { ComponentType } from '../Core/ComponentStorage';
import { ComponentType, ComponentRegistry } from '../Core/ComponentStorage';
import { EntitySerializer, SerializedEntity } from './EntitySerializer';
import { getComponentTypeName } from '../Decorators';
import { getSerializationMetadata } from './SerializationDecorators';
import { ComponentTypeRegistry } from './ComponentTypeRegistry';
import * as msgpack from 'msgpack-lite';
/**
* 场景序列化格式
@@ -154,9 +154,9 @@ export class SceneSerializer {
*
* @param scene 要序列化的场景
* @param options 序列化选项
* @returns 序列化后的数据JSON字符串或二进制数据
* @returns 序列化后的数据JSON字符串或二进制Buffer
*/
public static serialize(scene: IScene, options?: SceneSerializationOptions): string {
public static serialize(scene: IScene, options?: SceneSerializationOptions): string | Buffer {
const opts: SceneSerializationOptions = {
systems: false,
format: 'json',
@@ -206,8 +206,8 @@ export class SceneSerializer {
? JSON.stringify(serializedScene, null, 2)
: JSON.stringify(serializedScene);
} else {
// 二进制格式(未来实现
throw new Error('Binary serialization format is not yet implemented');
// 二进制格式(使用 MessagePack
return msgpack.encode(serializedScene);
}
}
@@ -215,12 +215,12 @@ export class SceneSerializer {
* 反序列化场景
*
* @param scene 目标场景
* @param saveData 序列化的数据
* @param saveData 序列化的数据JSON字符串或二进制Buffer
* @param options 反序列化选项
*/
public static deserialize(
scene: IScene,
saveData: string,
saveData: string | Buffer,
options?: SceneDeserializationOptions
): void {
const opts: SceneDeserializationOptions = {
@@ -232,7 +232,13 @@ export class SceneSerializer {
// 解析数据
let serializedScene: SerializedScene;
try {
serializedScene = JSON.parse(saveData);
if (typeof saveData === 'string') {
// JSON格式
serializedScene = JSON.parse(saveData);
} else {
// 二进制格式MessagePack
serializedScene = msgpack.decode(saveData);
}
} catch (error) {
throw new Error(`Failed to parse save data: ${error}`);
}
@@ -455,7 +461,7 @@ export class SceneSerializer {
* 从所有已注册的组件类型构建注册表
*/
private static getGlobalComponentRegistry(): Map<string, ComponentType> {
return ComponentTypeRegistry.getRegistry();
return ComponentRegistry.getAllComponentNames() as Map<string, ComponentType>;
}
/**

View File

@@ -49,6 +49,3 @@ export type {
ComponentMigrationFunction,
SceneMigrationFunction
} from './VersionMigration';
// 组件类型注册表
export { ComponentTypeRegistry } from './ComponentTypeRegistry';

View File

@@ -198,6 +198,7 @@ export abstract class WorkerEntitySystem<TEntityData = any> extends EntitySystem
protected sharedBuffer: SharedArrayBuffer | null = null;
protected sharedFloatArray: Float32Array | null = null;
private platformAdapter: IPlatformAdapter;
private hasLoggedSyncMode = false;
constructor(matcher?: Matcher, config: WorkerSystemConfig = {}) {
super(matcher);
@@ -449,7 +450,10 @@ export abstract class WorkerEntitySystem<TEntityData = any> extends EntitySystem
}
} else {
// 同步处理最后的fallback
this.logger.info(`${this.systemName}: Worker不可用使用同步处理`);
if (!this.hasLoggedSyncMode) {
this.logger.info(`${this.systemName}: Worker不可用使用同步处理`);
this.hasLoggedSyncMode = true;
}
this.processSynchronously(entities);
this.isProcessing = false;
}

View File

@@ -29,7 +29,6 @@ export * from './ECS';
// TypeScript类型增强API
export * from './ECS/TypedEntity';
export * from './ECS/Systems/TypedEntitySystem';
export * from './ECS/Core/Query/TypedQuery';
// 事件系统
@@ -39,5 +38,8 @@ export { ECSEventType, EventPriority, EVENT_TYPES, EventTypeValidator } from './
export * from './Utils';
export * from './Types';
// 显式导出ComponentPool类解决与Types中ComponentPool接口的命名冲突
export { ComponentPool, ComponentPoolManager } from './ECS/Core/Storage';
// 平台适配
export * from './Platform';