使用Lerna 和 monorepo管理项目结构

This commit is contained in:
YHH
2025-08-07 13:29:12 +08:00
parent 4479f0fab0
commit ea8523be35
135 changed files with 7058 additions and 372 deletions

View File

@@ -0,0 +1,161 @@
import { Component } from '@esengine/ecs-framework';
import { INetworkSyncable } from './INetworkSyncable';
/**
* 网络组件基类
*
* 继承核心ECS的Component类添加网络同步功能。
* 用于需要网络同步的组件,提供帧同步框架所需的网络状态管理。
*
* @example
* ```typescript
* import { NetworkComponent } from '@esengine/ecs-framework-network';
* import { ProtoSerializable, ProtoFloat } from '@esengine/ecs-framework-network';
*
* @ProtoSerializable('Position')
* class PositionComponent extends NetworkComponent {
* @ProtoFloat(1)
* public x: number = 0;
*
* @ProtoFloat(2)
* public y: number = 0;
*
* constructor(x: number = 0, y: number = 0) {
* super();
* this.x = x;
* this.y = y;
* }
* }
* ```
*/
export abstract class NetworkComponent extends Component implements INetworkSyncable {
/**
* 脏字段标记集合
*
* 记录已修改但尚未同步的字段编号
*/
private _dirtyFields: Set<number> = new Set();
/**
* 字段变化时间戳
*
* 记录每个字段最后修改的时间
*/
private _fieldTimestamps: Map<number, number> = new Map();
/**
* 获取网络同步状态
*
* 序列化当前组件状态为网络传输格式
* @returns 序列化的网络状态数据
*/
public getNetworkState(): Uint8Array {
const { isProtoSerializable } = require('./Serialization/ProtobufDecorators');
const { ProtobufSerializer } = require('./Serialization/ProtobufSerializer');
if (!isProtoSerializable(this)) {
throw new Error(`组件 ${this.constructor.name} 不支持网络同步,请添加@ProtoSerializable装饰器`);
}
try {
const serializer = ProtobufSerializer.getInstance();
const serializedData = serializer.serialize(this);
return serializedData.data;
} catch (error) {
throw new Error(`获取网络状态失败: ${error}`);
}
}
/**
* 应用网络状态
*
* 从网络数据恢复组件状态
* @param data - 网络状态数据
*/
public applyNetworkState(data: Uint8Array): void {
const { isProtoSerializable } = require('./Serialization/ProtobufDecorators');
const { ProtobufSerializer } = require('./Serialization/ProtobufSerializer');
if (!isProtoSerializable(this)) {
throw new Error(`组件 ${this.constructor.name} 不支持网络同步,请添加@ProtoSerializable装饰器`);
}
try {
const serializer = ProtobufSerializer.getInstance();
const serializedData = {
type: 'protobuf' as const,
componentType: this.constructor.name,
data: data,
size: data.length
};
serializer.deserialize(this, serializedData);
// 应用后清理脏字段标记
this.markClean();
} catch (error) {
throw new Error(`应用网络状态失败: ${error}`);
}
}
/**
* 获取变化的字段编号列表
*
* @returns 变化字段的编号数组
*/
public getDirtyFields(): number[] {
return Array.from(this._dirtyFields);
}
/**
* 标记所有字段为干净状态
*
* 清除所有脏字段标记
*/
public markClean(): void {
this._dirtyFields.clear();
}
/**
* 标记字段为脏状态
*
* 用于标记字段已修改,需要网络同步
* @param fieldNumber - 字段编号
*/
public markFieldDirty(fieldNumber: number): void {
this._dirtyFields.add(fieldNumber);
this._fieldTimestamps.set(fieldNumber, Date.now());
}
/**
* 检查字段是否为脏状态
*
* @param fieldNumber - 字段编号
* @returns 是否为脏状态
*/
public isFieldDirty(fieldNumber: number): boolean {
return this._dirtyFields.has(fieldNumber);
}
/**
* 获取字段最后修改时间
*
* @param fieldNumber - 字段编号
* @returns 最后修改时间戳如果字段从未修改则返回0
*/
public getFieldTimestamp(fieldNumber: number): number {
return this._fieldTimestamps.get(fieldNumber) || 0;
}
/**
* 获取所有脏字段及其时间戳
*
* @returns 脏字段和时间戳的映射
*/
public getDirtyFieldsWithTimestamps(): Map<number, number> {
const result = new Map<number, number>();
for (const fieldNumber of this._dirtyFields) {
result.set(fieldNumber, this._fieldTimestamps.get(fieldNumber) || 0);
}
return result;
}
}