场景自定义序列化支持

This commit is contained in:
YHH
2025-10-08 18:34:15 +08:00
parent c631290049
commit 06b3f92007
11 changed files with 2610 additions and 4 deletions

View File

@@ -0,0 +1,223 @@
/**
* 实体序列化器
*
* 负责实体的序列化和反序列化操作
*/
import { Entity } from '../Entity';
import { Component } from '../Component';
import { ComponentType } from '../Core/ComponentStorage';
import { ComponentSerializer, SerializedComponent } from './ComponentSerializer';
/**
* 序列化后的实体数据
*/
export interface SerializedEntity {
/**
* 实体ID
*/
id: number;
/**
* 实体名称
*/
name: string;
/**
* 实体标签
*/
tag: number;
/**
* 激活状态
*/
active: boolean;
/**
* 启用状态
*/
enabled: boolean;
/**
* 更新顺序
*/
updateOrder: number;
/**
* 组件列表
*/
components: SerializedComponent[];
/**
* 子实体列表
*/
children: SerializedEntity[];
/**
* 父实体ID如果有
*/
parentId?: number;
}
/**
* 实体序列化器类
*/
export class EntitySerializer {
/**
* 序列化单个实体
*
* @param entity 要序列化的实体
* @param includeChildren 是否包含子实体默认true
* @returns 序列化后的实体数据
*/
public static serialize(entity: Entity, includeChildren: boolean = true): SerializedEntity {
const serializedComponents = ComponentSerializer.serializeComponents(
Array.from(entity.components)
);
const serializedEntity: SerializedEntity = {
id: entity.id,
name: entity.name,
tag: entity.tag,
active: entity.active,
enabled: entity.enabled,
updateOrder: entity.updateOrder,
components: serializedComponents,
children: []
};
// 序列化父实体引用
if (entity.parent) {
serializedEntity.parentId = entity.parent.id;
}
// 序列化子实体
if (includeChildren) {
for (const child of entity.children) {
serializedEntity.children.push(this.serialize(child, true));
}
}
return serializedEntity;
}
/**
* 反序列化实体
*
* @param serializedEntity 序列化的实体数据
* @param componentRegistry 组件类型注册表
* @param idGenerator 实体ID生成器用于生成新ID或保持原ID
* @param preserveIds 是否保持原始ID默认false
* @returns 反序列化后的实体
*/
public static deserialize(
serializedEntity: SerializedEntity,
componentRegistry: Map<string, ComponentType>,
idGenerator: () => number,
preserveIds: boolean = false
): Entity {
// 创建实体使用原始ID或新生成的ID
const entityId = preserveIds ? serializedEntity.id : idGenerator();
const entity = new Entity(serializedEntity.name, entityId);
// 恢复实体属性
entity.tag = serializedEntity.tag;
entity.active = serializedEntity.active;
entity.enabled = serializedEntity.enabled;
entity.updateOrder = serializedEntity.updateOrder;
// 反序列化组件
const components = ComponentSerializer.deserializeComponents(
serializedEntity.components,
componentRegistry
);
for (const component of components) {
entity.addComponent(component);
}
// 反序列化子实体
for (const childData of serializedEntity.children) {
const childEntity = this.deserialize(
childData,
componentRegistry,
idGenerator,
preserveIds
);
entity.addChild(childEntity);
}
return entity;
}
/**
* 批量序列化实体
*
* @param entities 实体数组
* @param includeChildren 是否包含子实体
* @returns 序列化后的实体数据数组
*/
public static serializeEntities(
entities: Entity[],
includeChildren: boolean = true
): SerializedEntity[] {
const result: SerializedEntity[] = [];
for (const entity of entities) {
// 只序列化顶层实体(没有父实体的实体)
// 子实体会在父实体序列化时一并处理
if (!entity.parent || !includeChildren) {
result.push(this.serialize(entity, includeChildren));
}
}
return result;
}
/**
* 批量反序列化实体
*
* @param serializedEntities 序列化的实体数据数组
* @param componentRegistry 组件类型注册表
* @param idGenerator 实体ID生成器
* @param preserveIds 是否保持原始ID
* @returns 反序列化后的实体数组
*/
public static deserializeEntities(
serializedEntities: SerializedEntity[],
componentRegistry: Map<string, ComponentType>,
idGenerator: () => number,
preserveIds: boolean = false
): Entity[] {
const result: Entity[] = [];
for (const serialized of serializedEntities) {
const entity = this.deserialize(
serialized,
componentRegistry,
idGenerator,
preserveIds
);
result.push(entity);
}
return result;
}
/**
* 创建实体的深拷贝
*
* @param entity 要拷贝的实体
* @param componentRegistry 组件类型注册表
* @param idGenerator ID生成器
* @returns 拷贝后的新实体
*/
public static clone(
entity: Entity,
componentRegistry: Map<string, ComponentType>,
idGenerator: () => number
): Entity {
const serialized = this.serialize(entity, true);
return this.deserialize(serialized, componentRegistry, idGenerator, false);
}
}