更新network库及core库优化

This commit is contained in:
YHH
2025-08-12 09:39:07 +08:00
parent c178e2fbcc
commit 9f76d37a82
117 changed files with 17988 additions and 4099 deletions

View File

@@ -0,0 +1,179 @@
/**
* 客户端网络行为基类
*
* 类似Unity Mirror的NetworkBehaviour提供网络功能
*/
import { Component, Entity } from '@esengine/ecs-framework';
import { NetworkValue } from '@esengine/ecs-framework-network-shared';
import { NetworkClient } from './NetworkClient';
import { NetworkIdentity } from './NetworkIdentity';
/**
* 客户端网络行为基类
*/
export abstract class ClientNetworkBehaviour extends Component {
/** 网络标识组件 */
protected networkIdentity: NetworkIdentity | null = null;
/** 网络客户端实例 */
protected networkClient: NetworkClient | null = null;
/**
* 组件初始化
*/
initialize(): void {
// 获取网络标识组件
this.networkIdentity = this.entity.getComponent(NetworkIdentity);
if (!this.networkIdentity) {
throw new Error('NetworkBehaviour requires NetworkIdentity component');
}
// 从全局获取网络客户端实例
this.networkClient = this.getNetworkClient();
}
/**
* 获取网络客户端实例
*/
protected getNetworkClient(): NetworkClient | null {
// 这里需要实现从全局管理器获取客户端实例的逻辑
// 暂时返回null在实际使用时需要通过单例模式或依赖注入获取
return null;
}
/**
* 是否为本地玩家
*/
get isLocalPlayer(): boolean {
return this.networkIdentity?.isLocalPlayer ?? false;
}
/**
* 是否为服务器权威
*/
get hasAuthority(): boolean {
return this.networkIdentity?.hasAuthority ?? false;
}
/**
* 网络ID
*/
get networkId(): string {
return this.networkIdentity?.networkId ?? '';
}
/**
* 是否已连接
*/
get isConnected(): boolean {
return this.networkClient?.isInRoom() ?? false;
}
/**
* 发送RPC到服务器
*/
protected async sendServerRpc(methodName: string, ...args: NetworkValue[]): Promise<NetworkValue> {
if (!this.networkClient || !this.networkIdentity) {
throw new Error('Network client or identity not available');
}
return this.networkClient.sendRpc(this.networkIdentity.networkId, methodName, args, true);
}
/**
* 发送不可靠RPC到服务器
*/
protected async sendServerRpcUnreliable(methodName: string, ...args: NetworkValue[]): Promise<void> {
if (!this.networkClient || !this.networkIdentity) {
throw new Error('Network client or identity not available');
}
await this.networkClient.sendRpc(this.networkIdentity.networkId, methodName, args, false);
}
/**
* 更新SyncVar
*/
protected async updateSyncVar(fieldName: string, value: NetworkValue): Promise<void> {
if (!this.networkClient || !this.networkIdentity) {
throw new Error('Network client or identity not available');
}
await this.networkClient.updateSyncVar(this.networkIdentity.networkId, fieldName, value);
}
/**
* 当收到RPC调用时
*/
onRpcReceived(methodName: string, args: NetworkValue[]): void {
// 尝试调用对应的方法
const method = (this as any)[methodName];
if (typeof method === 'function') {
try {
method.apply(this, args);
} catch (error) {
console.error(`Error calling RPC method ${methodName}:`, error);
}
} else {
console.warn(`RPC method ${methodName} not found on ${this.constructor.name}`);
}
}
/**
* 当SyncVar更新时
*/
onSyncVarChanged(fieldName: string, oldValue: NetworkValue, newValue: NetworkValue): void {
// 子类可以重写此方法来处理SyncVar变化
}
/**
* 当获得权威时
*/
onStartAuthority(): void {
// 子类可以重写此方法
}
/**
* 当失去权威时
*/
onStopAuthority(): void {
// 子类可以重写此方法
}
/**
* 当成为本地玩家时
*/
onStartLocalPlayer(): void {
// 子类可以重写此方法
}
/**
* 当不再是本地玩家时
*/
onStopLocalPlayer(): void {
// 子类可以重写此方法
}
/**
* 网络启动时调用
*/
onNetworkStart(): void {
// 子类可以重写此方法
}
/**
* 网络停止时调用
*/
onNetworkStop(): void {
// 子类可以重写此方法
}
/**
* 组件销毁
*/
onDestroy(): void {
this.networkIdentity = null;
this.networkClient = null;
}
}

View File

@@ -0,0 +1,638 @@
/**
* 网络客户端主类
*
* 管理连接、认证、房间加入等功能
*/
import { Scene, EntityManager, Emitter, ITimer, Core } from '@esengine/ecs-framework';
import {
NetworkIdentity as SharedNetworkIdentity,
NetworkValue,
RpcMessage,
SyncVarMessage
} from '@esengine/ecs-framework-network-shared';
import {
ClientTransport,
WebSocketClientTransport,
HttpClientTransport,
ConnectionState,
ClientMessage,
ClientTransportConfig,
WebSocketClientConfig,
HttpClientConfig
} from '../transport';
/**
* 网络客户端配置
*/
export interface NetworkClientConfig {
/** 传输类型 */
transport: 'websocket' | 'http';
/** 传输配置 */
transportConfig: WebSocketClientConfig | HttpClientConfig;
/** 是否启用预测 */
enablePrediction?: boolean;
/** 预测缓冲区大小 */
predictionBuffer?: number;
/** 是否启用插值 */
enableInterpolation?: boolean;
/** 插值延迟(毫秒) */
interpolationDelay?: number;
/** 网络对象同步间隔(毫秒) */
syncInterval?: number;
/** 是否启用调试 */
debug?: boolean;
}
/**
* 用户信息
*/
export interface UserInfo {
/** 用户ID */
userId: string;
/** 用户名 */
username: string;
/** 用户数据 */
data?: NetworkValue;
}
/**
* 房间信息
*/
export interface RoomInfo {
/** 房间ID */
roomId: string;
/** 房间名称 */
name: string;
/** 当前人数 */
playerCount: number;
/** 最大人数 */
maxPlayers: number;
/** 房间元数据 */
metadata?: NetworkValue;
/** 是否私有房间 */
isPrivate?: boolean;
}
/**
* 认证消息
*/
export interface AuthMessage {
action: string;
username: string;
password?: string;
userData?: NetworkValue;
}
/**
* 房间消息
*/
export interface RoomMessage {
action: string;
roomId?: string;
name?: string;
maxPlayers?: number;
metadata?: NetworkValue;
isPrivate?: boolean;
password?: string;
}
/**
* 网络客户端事件
*/
export interface NetworkClientEvents {
/** 连接建立 */
'connected': () => void;
/** 连接断开 */
'disconnected': (reason: string) => void;
/** 认证成功 */
'authenticated': (userInfo: UserInfo) => void;
/** 加入房间成功 */
'joined-room': (roomInfo: RoomInfo) => void;
/** 离开房间 */
'left-room': (roomId: string) => void;
/** 房间列表更新 */
'room-list-updated': (rooms: RoomInfo[]) => void;
/** 玩家加入房间 */
'player-joined': (userId: string, userInfo: UserInfo) => void;
/** 玩家离开房间 */
'player-left': (userId: string) => void;
/** 网络对象创建 */
'network-object-created': (networkId: string, data: NetworkValue) => void;
/** 网络对象销毁 */
'network-object-destroyed': (networkId: string) => void;
/** SyncVar 更新 */
'syncvar-updated': (networkId: string, fieldName: string, value: NetworkValue) => void;
/** RPC 调用 */
'rpc-received': (networkId: string, methodName: string, args: NetworkValue[]) => void;
/** 错误发生 */
'error': (error: Error) => void;
}
/**
* 网络客户端主类
*/
export class NetworkClient {
private transport: ClientTransport;
private config: NetworkClientConfig;
private currentUser: UserInfo | null = null;
private currentRoom: RoomInfo | null = null;
private availableRooms: Map<string, RoomInfo> = new Map();
private networkObjects: Map<string, SharedNetworkIdentity> = new Map();
private pendingRpcs: Map<string, { resolve: Function; reject: Function; timeout: ITimer<any> }> = new Map();
private scene: Scene | null = null;
private eventEmitter: Emitter<keyof NetworkClientEvents, any>;
constructor(config: NetworkClientConfig) {
this.eventEmitter = new Emitter();
this.config = {
enablePrediction: true,
predictionBuffer: 64,
enableInterpolation: true,
interpolationDelay: 100,
syncInterval: 50,
debug: false,
...config
};
this.transport = this.createTransport();
this.setupTransportEvents();
}
/**
* 创建传输层
*/
private createTransport(): ClientTransport {
switch (this.config.transport) {
case 'websocket':
return new WebSocketClientTransport(this.config.transportConfig as WebSocketClientConfig);
case 'http':
return new HttpClientTransport(this.config.transportConfig as HttpClientConfig);
default:
throw new Error(`Unsupported transport type: ${this.config.transport}`);
}
}
/**
* 设置传输层事件监听
*/
private setupTransportEvents(): void {
this.transport.on('connected', () => {
this.eventEmitter.emit('connected');
});
this.transport.on('disconnected', (reason) => {
this.handleDisconnected(reason);
});
this.transport.on('message', (message) => {
this.handleMessage(message);
});
this.transport.on('error', (error) => {
this.eventEmitter.emit('error', error);
});
}
/**
* 连接到服务器
*/
async connect(): Promise<void> {
return this.transport.connect();
}
/**
* 断开连接
*/
async disconnect(): Promise<void> {
await this.transport.disconnect();
this.cleanup();
}
/**
* 用户认证
*/
async authenticate(username: string, password?: string, userData?: NetworkValue): Promise<UserInfo> {
if (!this.transport.isConnected()) {
throw new Error('Not connected to server');
}
const authMessage: AuthMessage = {
action: 'login',
username,
password,
userData
};
const response = await this.sendRequestWithResponse('system', authMessage as any);
if (response.success && response.userInfo) {
this.currentUser = response.userInfo as UserInfo;
this.eventEmitter.emit('authenticated', this.currentUser);
return this.currentUser;
} else {
throw new Error(response.error || 'Authentication failed');
}
}
/**
* 获取房间列表
*/
async getRoomList(): Promise<RoomInfo[]> {
if (!this.isAuthenticated()) {
throw new Error('Not authenticated');
}
const roomMessage: RoomMessage = {
action: 'list-rooms'
};
const response = await this.sendRequestWithResponse('system', roomMessage as any);
if (response.success && response.rooms) {
this.availableRooms.clear();
response.rooms.forEach((room: RoomInfo) => {
this.availableRooms.set(room.roomId, room);
});
this.eventEmitter.emit('room-list-updated', response.rooms);
return response.rooms;
} else {
throw new Error(response.error || 'Failed to get room list');
}
}
/**
* 创建房间
*/
async createRoom(name: string, maxPlayers: number = 8, metadata?: NetworkValue, isPrivate = false): Promise<RoomInfo> {
if (!this.isAuthenticated()) {
throw new Error('Not authenticated');
}
const roomMessage: RoomMessage = {
action: 'create-room',
name,
maxPlayers,
metadata,
isPrivate
};
const response = await this.sendRequestWithResponse('system', roomMessage as any);
if (response.success && response.room) {
this.currentRoom = response.room as RoomInfo;
this.eventEmitter.emit('joined-room', this.currentRoom);
return this.currentRoom;
} else {
throw new Error(response.error || 'Failed to create room');
}
}
/**
* 加入房间
*/
async joinRoom(roomId: string, password?: string): Promise<RoomInfo> {
if (!this.isAuthenticated()) {
throw new Error('Not authenticated');
}
const roomMessage: RoomMessage = {
action: 'join-room',
roomId,
password
};
const response = await this.sendRequestWithResponse('system', roomMessage as any);
if (response.success && response.room) {
this.currentRoom = response.room as RoomInfo;
this.eventEmitter.emit('joined-room', this.currentRoom);
return this.currentRoom;
} else {
throw new Error(response.error || 'Failed to join room');
}
}
/**
* 离开房间
*/
async leaveRoom(): Promise<void> {
if (!this.currentRoom) {
return;
}
const roomMessage: RoomMessage = {
action: 'leave-room',
roomId: this.currentRoom.roomId
};
try {
await this.sendRequestWithResponse('system', roomMessage as any);
} finally {
const roomId = this.currentRoom.roomId;
this.currentRoom = null;
this.networkObjects.clear();
this.eventEmitter.emit('left-room', roomId);
}
}
/**
* 发送RPC调用
*/
async sendRpc(networkId: string, methodName: string, args: NetworkValue[] = [], reliable = true): Promise<NetworkValue> {
if (!this.isInRoom()) {
throw new Error('Not in a room');
}
const rpcMessage: any = {
networkId,
methodName,
args,
isServer: false,
messageId: this.generateMessageId()
};
if (reliable) {
return this.sendRequestWithResponse('rpc', rpcMessage);
} else {
await this.transport.sendMessage({
type: 'rpc',
data: rpcMessage as NetworkValue,
reliable: false
});
return {};
}
}
/**
* 更新SyncVar
*/
async updateSyncVar(networkId: string, fieldName: string, value: NetworkValue): Promise<void> {
if (!this.isInRoom()) {
throw new Error('Not in a room');
}
const syncMessage: any = {
networkId,
propertyName: fieldName,
value,
isServer: false
};
await this.transport.sendMessage({
type: 'syncvar',
data: syncMessage as NetworkValue,
reliable: true
});
}
/**
* 设置ECS场景
*/
setScene(scene: Scene): void {
this.scene = scene;
}
/**
* 获取当前用户信息
*/
getCurrentUser(): UserInfo | null {
return this.currentUser;
}
/**
* 获取当前房间信息
*/
getCurrentRoom(): RoomInfo | null {
return this.currentRoom;
}
/**
* 获取连接状态
*/
getConnectionState(): ConnectionState {
return this.transport.getState();
}
/**
* 是否已认证
*/
isAuthenticated(): boolean {
return this.currentUser !== null && this.transport.isConnected();
}
/**
* 是否在房间中
*/
isInRoom(): boolean {
return this.isAuthenticated() && this.currentRoom !== null;
}
/**
* 获取网络对象
*/
getNetworkObject(networkId: string): SharedNetworkIdentity | null {
return this.networkObjects.get(networkId) || null;
}
/**
* 获取所有网络对象
*/
getAllNetworkObjects(): SharedNetworkIdentity[] {
return Array.from(this.networkObjects.values());
}
/**
* 处理断开连接
*/
private handleDisconnected(reason: string): void {
this.cleanup();
this.eventEmitter.emit('disconnected', reason);
}
/**
* 处理接收到的消息
*/
private handleMessage(message: ClientMessage): void {
try {
switch (message.type) {
case 'system':
this.handleSystemMessage(message);
break;
case 'rpc':
this.handleRpcMessage(message);
break;
case 'syncvar':
this.handleSyncVarMessage(message);
break;
case 'custom':
this.handleCustomMessage(message);
break;
}
} catch (error) {
console.error('Error handling message:', error);
this.eventEmitter.emit('error', error as Error);
}
}
/**
* 处理系统消息
*/
private handleSystemMessage(message: ClientMessage): void {
const data = message.data as any;
// 处理响应消息
if (message.messageId && this.pendingRpcs.has(message.messageId)) {
const pending = this.pendingRpcs.get(message.messageId)!;
pending.timeout.stop();
this.pendingRpcs.delete(message.messageId);
if (data.success) {
pending.resolve(data);
} else {
pending.reject(new Error(data.error || 'Request failed'));
}
return;
}
// 处理广播消息
switch (data.action) {
case 'player-joined':
this.eventEmitter.emit('player-joined', data.userId, data.userInfo);
break;
case 'player-left':
this.eventEmitter.emit('player-left', data.userId);
break;
case 'network-object-created':
this.handleNetworkObjectCreated(data);
break;
case 'network-object-destroyed':
this.handleNetworkObjectDestroyed(data);
break;
}
}
/**
* 处理RPC消息
*/
private handleRpcMessage(message: ClientMessage): void {
const rpcData = message.data as any;
this.eventEmitter.emit('rpc-received', rpcData.networkId, rpcData.methodName, rpcData.args || []);
}
/**
* 处理SyncVar消息
*/
private handleSyncVarMessage(message: ClientMessage): void {
const syncData = message.data as any;
this.eventEmitter.emit('syncvar-updated', syncData.networkId, syncData.propertyName, syncData.value);
}
/**
* 处理自定义消息
*/
private handleCustomMessage(message: ClientMessage): void {
// 可扩展的自定义消息处理
}
/**
* 处理网络对象创建
*/
private handleNetworkObjectCreated(data: any): void {
const networkObject = new SharedNetworkIdentity();
this.networkObjects.set(data.networkId, networkObject);
this.eventEmitter.emit('network-object-created', data.networkId, data.data || {});
}
/**
* 处理网络对象销毁
*/
private handleNetworkObjectDestroyed(data: any): void {
this.networkObjects.delete(data.networkId);
this.eventEmitter.emit('network-object-destroyed', data.networkId);
}
/**
* 发送请求并等待响应
*/
private sendRequestWithResponse(type: ClientMessage['type'], data: NetworkValue, timeout = 30000): Promise<any> {
return new Promise((resolve, reject) => {
const messageId = this.generateMessageId();
const timeoutTimer = Core.schedule(timeout / 1000, false, this, () => {
this.pendingRpcs.delete(messageId);
reject(new Error('Request timeout'));
});
this.pendingRpcs.set(messageId, {
resolve,
reject,
timeout: timeoutTimer
});
this.transport.sendMessage({
type,
data,
messageId,
reliable: true
}).catch(reject);
});
}
/**
* 生成消息ID
*/
private generateMessageId(): string {
return Date.now().toString(36) + Math.random().toString(36).substr(2);
}
/**
* 清理资源
*/
private cleanup(): void {
this.currentUser = null;
this.currentRoom = null;
this.availableRooms.clear();
this.networkObjects.clear();
// 取消所有待处理的RPC
this.pendingRpcs.forEach(pending => {
pending.timeout.stop();
pending.reject(new Error('Connection closed'));
});
this.pendingRpcs.clear();
}
/**
* 销毁客户端
*/
destroy(): void {
this.disconnect();
this.transport.destroy();
// 清理事件监听器由于Emitter没有clear方法我们重新创建一个
this.eventEmitter = new Emitter();
}
/**
* 类型安全的事件监听
*/
on<K extends keyof NetworkClientEvents>(event: K, listener: NetworkClientEvents[K]): void {
this.eventEmitter.addObserver(event, listener, this);
}
/**
* 移除事件监听
*/
off<K extends keyof NetworkClientEvents>(event: K, listener: NetworkClientEvents[K]): void {
this.eventEmitter.removeObserver(event, listener);
}
/**
* 类型安全的事件触发
*/
emit<K extends keyof NetworkClientEvents>(event: K, ...args: Parameters<NetworkClientEvents[K]>): void {
this.eventEmitter.emit(event, ...args);
}
}

View File

@@ -0,0 +1,378 @@
/**
* 客户端网络标识组件
*
* 标识网络对象并管理其状态
*/
import { Component, Entity } from '@esengine/ecs-framework';
import { NetworkValue } from '@esengine/ecs-framework-network-shared';
import { ClientNetworkBehaviour } from './ClientNetworkBehaviour';
/**
* 网络权威类型
*/
export enum NetworkAuthority {
/** 服务器权威 */
SERVER = 'server',
/** 客户端权威 */
CLIENT = 'client',
/** 所有者权威 */
OWNER = 'owner'
}
/**
* SyncVar信息
*/
export interface SyncVarInfo {
/** 字段名 */
fieldName: string;
/** 当前值 */
currentValue: NetworkValue;
/** 上一个值 */
previousValue: NetworkValue;
/** 最后更新时间 */
lastUpdateTime: number;
/** 是否已变更 */
isDirty: boolean;
}
/**
* 网络标识组件
*/
export class NetworkIdentity extends Component {
/** 网络ID */
private _networkId: string = '';
/** 所有者用户ID */
private _ownerId: string = '';
/** 是否为本地玩家 */
private _isLocalPlayer: boolean = false;
/** 权威类型 */
private _authority: NetworkAuthority = NetworkAuthority.SERVER;
/** 是否有权威 */
private _hasAuthority: boolean = false;
/** 网络行为组件列表 */
private networkBehaviours: ClientNetworkBehaviour[] = [];
/** SyncVar信息映射 */
private syncVars: Map<string, SyncVarInfo> = new Map();
/** 预测状态 */
private predictionEnabled: boolean = false;
/** 插值状态 */
private interpolationEnabled: boolean = true;
/**
* 网络ID
*/
get networkId(): string {
return this._networkId;
}
set networkId(value: string) {
this._networkId = value;
}
/**
* 所有者用户ID
*/
get ownerId(): string {
return this._ownerId;
}
set ownerId(value: string) {
this._ownerId = value;
}
/**
* 是否为本地玩家
*/
get isLocalPlayer(): boolean {
return this._isLocalPlayer;
}
set isLocalPlayer(value: boolean) {
if (this._isLocalPlayer !== value) {
this._isLocalPlayer = value;
this.notifyLocalPlayerChanged();
}
}
/**
* 权威类型
*/
get authority(): NetworkAuthority {
return this._authority;
}
set authority(value: NetworkAuthority) {
if (this._authority !== value) {
this._authority = value;
this.updateAuthorityStatus();
}
}
/**
* 是否有权威
*/
get hasAuthority(): boolean {
return this._hasAuthority;
}
/**
* 是否启用预测
*/
get isPredictionEnabled(): boolean {
return this.predictionEnabled;
}
set isPredictionEnabled(value: boolean) {
this.predictionEnabled = value;
}
/**
* 是否启用插值
*/
get isInterpolationEnabled(): boolean {
return this.interpolationEnabled;
}
set isInterpolationEnabled(value: boolean) {
this.interpolationEnabled = value;
}
/**
* 组件初始化
*/
initialize(): void {
this.collectNetworkBehaviours();
this.notifyNetworkStart();
}
/**
* 收集网络行为组件
*/
private collectNetworkBehaviours(): void {
// 暂时留空,等待实际集成时实现
this.networkBehaviours = [];
}
/**
* 更新权威状态
*/
private updateAuthorityStatus(): void {
const oldHasAuthority = this._hasAuthority;
// 根据权威类型计算是否有权威
switch (this._authority) {
case NetworkAuthority.SERVER:
this._hasAuthority = false; // 客户端永远没有服务器权威
break;
case NetworkAuthority.CLIENT:
this._hasAuthority = true; // 客户端权威
break;
case NetworkAuthority.OWNER:
this._hasAuthority = this._isLocalPlayer; // 本地玩家才有权威
break;
}
// 通知权威变化
if (oldHasAuthority !== this._hasAuthority) {
this.notifyAuthorityChanged();
}
}
/**
* 通知权威变化
*/
private notifyAuthorityChanged(): void {
this.networkBehaviours.forEach(behaviour => {
if (this._hasAuthority) {
behaviour.onStartAuthority();
} else {
behaviour.onStopAuthority();
}
});
}
/**
* 通知本地玩家状态变化
*/
private notifyLocalPlayerChanged(): void {
this.updateAuthorityStatus(); // 本地玩家状态影响权威
this.networkBehaviours.forEach(behaviour => {
if (this._isLocalPlayer) {
behaviour.onStartLocalPlayer();
} else {
behaviour.onStopLocalPlayer();
}
});
}
/**
* 通知网络启动
*/
private notifyNetworkStart(): void {
this.networkBehaviours.forEach(behaviour => {
behaviour.onNetworkStart();
});
}
/**
* 通知网络停止
*/
private notifyNetworkStop(): void {
this.networkBehaviours.forEach(behaviour => {
behaviour.onNetworkStop();
});
}
/**
* 处理RPC调用
*/
handleRpcCall(methodName: string, args: NetworkValue[]): void {
// 将RPC调用分发给所有网络行为组件
this.networkBehaviours.forEach(behaviour => {
behaviour.onRpcReceived(methodName, args);
});
}
/**
* 注册SyncVar
*/
registerSyncVar(fieldName: string, initialValue: NetworkValue): void {
this.syncVars.set(fieldName, {
fieldName,
currentValue: initialValue,
previousValue: initialValue,
lastUpdateTime: Date.now(),
isDirty: false
});
}
/**
* 更新SyncVar
*/
updateSyncVar(fieldName: string, newValue: NetworkValue): void {
const syncVar = this.syncVars.get(fieldName);
if (!syncVar) {
console.warn(`SyncVar ${fieldName} not registered on ${this._networkId}`);
return;
}
const oldValue = syncVar.currentValue;
syncVar.previousValue = oldValue;
syncVar.currentValue = newValue;
syncVar.lastUpdateTime = Date.now();
syncVar.isDirty = true;
// 通知所有网络行为组件
this.networkBehaviours.forEach(behaviour => {
behaviour.onSyncVarChanged(fieldName, oldValue, newValue);
});
}
/**
* 获取SyncVar值
*/
getSyncVar(fieldName: string): NetworkValue | undefined {
return this.syncVars.get(fieldName)?.currentValue;
}
/**
* 获取所有SyncVar
*/
getAllSyncVars(): Map<string, SyncVarInfo> {
return new Map(this.syncVars);
}
/**
* 获取脏SyncVar
*/
getDirtySyncVars(): SyncVarInfo[] {
return Array.from(this.syncVars.values()).filter(syncVar => syncVar.isDirty);
}
/**
* 清除脏标记
*/
clearDirtyFlags(): void {
this.syncVars.forEach(syncVar => {
syncVar.isDirty = false;
});
}
/**
* 序列化网络状态
*/
serializeState(): NetworkValue {
const state: any = {
networkId: this._networkId,
ownerId: this._ownerId,
isLocalPlayer: this._isLocalPlayer,
authority: this._authority,
syncVars: {}
};
// 序列化SyncVar
this.syncVars.forEach((syncVar, fieldName) => {
state.syncVars[fieldName] = syncVar.currentValue;
});
return state;
}
/**
* 反序列化网络状态
*/
deserializeState(state: any): void {
if (state.networkId) this._networkId = state.networkId;
if (state.ownerId) this._ownerId = state.ownerId;
if (typeof state.isLocalPlayer === 'boolean') this.isLocalPlayer = state.isLocalPlayer;
if (state.authority) this.authority = state.authority;
// 反序列化SyncVar
if (state.syncVars) {
Object.entries(state.syncVars).forEach(([fieldName, value]) => {
if (this.syncVars.has(fieldName)) {
this.updateSyncVar(fieldName, value as NetworkValue);
}
});
}
}
/**
* 设置预测状态
*/
setPredictionState(enabled: boolean): void {
this.predictionEnabled = enabled;
}
/**
* 设置插值状态
*/
setInterpolationState(enabled: boolean): void {
this.interpolationEnabled = enabled;
}
/**
* 检查是否可以发送RPC
*/
canSendRpc(): boolean {
return this._hasAuthority || this._isLocalPlayer;
}
/**
* 检查是否可以更新SyncVar
*/
canUpdateSyncVar(): boolean {
return this._hasAuthority;
}
/**
* 组件销毁
*/
onDestroy(): void {
this.notifyNetworkStop();
this.networkBehaviours = [];
this.syncVars.clear();
}
}

View File

@@ -0,0 +1,7 @@
/**
* 核心模块导出
*/
export * from './NetworkClient';
export * from './ClientNetworkBehaviour';
export * from './NetworkIdentity';