Files
esengine/packages/network/src/NetworkManager.ts

449 lines
11 KiB
TypeScript
Raw Normal View History

/**
*
*
*
* - /
* -
* - SyncVar
* - RPC
*/
import { createLogger, Component } from '@esengine/ecs-framework';
import {
NetworkConfig,
NetworkSide,
NetworkConnectionState,
NetworkStats,
NetworkEventHandlers,
SyncVarMessage,
RpcMessage,
NetworkMessage
} from './types/NetworkTypes';
import { NetworkRegistry } from './core/NetworkRegistry';
import { SyncVarManager } from './core/SyncVarManager';
import { RpcManager } from './core/RpcManager';
import { NetworkIdentity } from './NetworkIdentity';
import { NetworkBehaviour } from './NetworkBehaviour';
import { TsrpcTransport, TransportEventHandlers } from './transport/TsrpcTransport';
const logger = createLogger('NetworkManager');
export class NetworkManager extends Component {
private static _instance: NetworkManager | null = null;
/** 当前网络端类型 */
private networkSide: NetworkSide = 'client';
/** 连接状态 */
private connectionState: NetworkConnectionState = 'disconnected';
/** 网络配置 */
private config: NetworkConfig = {
port: 7777,
host: 'localhost',
maxConnections: 100,
syncRate: 20,
compression: false
};
/** 网络统计信息 */
private stats: NetworkStats = {
connectionCount: 0,
bytesSent: 0,
bytesReceived: 0,
messagesSent: 0,
messagesReceived: 0,
averageLatency: 0
};
/** 事件处理器 */
private eventHandlers: Partial<NetworkEventHandlers> = {};
/** 同步定时器 */
private syncTimer: NodeJS.Timeout | null = null;
/** TSRPC传输层 */
private transport: TsrpcTransport | null = null;
public static get instance(): NetworkManager | null {
return NetworkManager._instance;
}
public static get isServer(): boolean {
return NetworkManager._instance?.networkSide === 'server' ||
NetworkManager._instance?.networkSide === 'host';
}
public static get isClient(): boolean {
return NetworkManager._instance?.networkSide === 'client' ||
NetworkManager._instance?.networkSide === 'host';
}
public static get isConnected(): boolean {
return NetworkManager._instance?.connectionState === 'connected';
}
constructor() {
super();
if (NetworkManager._instance) {
throw new Error('NetworkManager 已存在实例,请使用 NetworkManager.instance');
}
NetworkManager._instance = this;
}
/**
*
* @param config
*/
public async startServer(config?: Partial<NetworkConfig>): Promise<void> {
if (this.connectionState !== 'disconnected') {
throw new Error('网络管理器已在运行中');
}
this.networkSide = 'server';
this.config = { ...this.config, ...config };
this.connectionState = 'connecting';
try {
// 初始化TSRPC传输层
await this.initializeTransport();
// 启动TSRPC服务端
await this.transport!.startServer();
this.connectionState = 'connected';
this.startSyncLoop();
logger.info(`服务端已启动,端口: ${this.config.port}`);
this.eventHandlers.onConnected?.();
} catch (error) {
this.connectionState = 'disconnected';
logger.error('启动服务端失败:', error);
this.eventHandlers.onError?.(error as Error);
throw error;
}
}
/**
*
* @param host
* @param port
*/
public async connectToServer(host?: string, port?: number): Promise<void> {
if (this.connectionState !== 'disconnected') {
throw new Error('已经连接或正在连接中');
}
this.networkSide = 'client';
this.config.host = host || this.config.host;
this.config.port = port || this.config.port;
this.connectionState = 'connecting';
try {
// 初始化TSRPC传输层
await this.initializeTransport();
// 连接到TSRPC服务端
await this.transport!.connectToServer();
this.connectionState = 'connected';
this.startSyncLoop();
logger.info(`已连接到服务端: ${this.config.host}:${this.config.port}`);
this.eventHandlers.onConnected?.();
} catch (error) {
this.connectionState = 'disconnected';
logger.error('连接服务端失败:', error);
this.eventHandlers.onError?.(error as Error);
throw error;
}
}
/**
*
*/
public async disconnect(): Promise<void> {
if (this.connectionState === 'disconnected') {
return;
}
this.connectionState = 'disconnected';
this.stopSyncLoop();
// 关闭TSRPC传输层连接
if (this.transport) {
await this.transport.disconnect();
}
logger.info('网络连接已断开');
this.eventHandlers.onDisconnected?.();
}
/**
*
* @param entity NetworkIdentity
* @returns ID
*/
public registerNetworkObject(entity: any): number {
const networkIdentity = entity.getComponent?.(NetworkIdentity);
if (!networkIdentity) {
throw new Error('实体必须包含 NetworkIdentity 组件才能注册为网络对象');
}
// 注册到网络注册表
const networkId = NetworkRegistry.instance.register(networkIdentity);
// 注册所有网络组件到管理器
const networkBehaviours = entity.getComponents?.()?.filter((c: any) => c instanceof NetworkBehaviour) || [];
for (const behaviour of networkBehaviours) {
SyncVarManager.instance.registerComponent(behaviour as NetworkBehaviour);
RpcManager.instance.registerComponent(behaviour as NetworkBehaviour);
}
logger.debug(`注册网络对象: ${entity.name}, ID: ${networkId}`);
return networkId;
}
/**
* RPC
*/
public sendClientRpc(
networkId: number,
componentType: string,
methodName: string,
args: any[] = [],
targetClient?: number
): void {
if (!NetworkManager.isServer) {
logger.warn('ClientRpc 只能在服务端调用');
return;
}
const message: RpcMessage = {
type: 'rpc',
networkId,
data: {
componentType,
methodName,
args
},
methodName,
args,
isClientRpc: true,
timestamp: Date.now()
};
this.sendMessage(message, targetClient);
}
/**
*
*/
public sendCommand(
networkId: number,
componentType: string,
methodName: string,
args: any[] = []
): void {
if (!NetworkManager.isClient) {
logger.warn('Command 只能在客户端调用');
return;
}
const message: RpcMessage = {
type: 'rpc',
networkId,
data: {
componentType,
methodName,
args
},
methodName,
args,
isClientRpc: false,
timestamp: Date.now()
};
this.sendMessage(message);
}
/**
*
*/
public on<K extends keyof NetworkEventHandlers>(
event: K,
handler: NetworkEventHandlers[K]
): void {
this.eventHandlers[event] = handler;
}
/**
*
*/
public getStats(): NetworkStats {
return { ...this.stats };
}
/**
*
*/
public getConnectionState(): NetworkConnectionState {
return this.connectionState;
}
/**
*
*/
public destroy(): void {
this.disconnect();
NetworkManager._instance = null;
}
/**
*
*/
private async initializeTransport(): Promise<void> {
if (this.transport) {
return; // 已经初始化
}
// 创建TSRPC传输层
this.transport = new TsrpcTransport(this.config);
// 设置传输层事件处理器
const transportHandlers: TransportEventHandlers = {
onConnected: () => {
logger.debug('传输层连接已建立');
},
onDisconnected: (reason) => {
logger.debug(`传输层连接已断开: ${reason}`);
if (this.connectionState === 'connected') {
this.connectionState = 'disconnected';
this.eventHandlers.onDisconnected?.(reason);
}
},
onClientConnected: (clientId) => {
logger.debug(`客户端 ${clientId} 已连接到传输层`);
this.eventHandlers.onClientConnected?.(clientId);
},
onClientDisconnected: (clientId, reason) => {
logger.debug(`客户端 ${clientId} 已从传输层断开: ${reason}`);
this.eventHandlers.onClientDisconnected?.(clientId, reason);
// 清理断开连接的客户端对象
NetworkRegistry.instance.cleanupDisconnectedClient(clientId);
},
onMessage: (message, fromClientId) => {
this.handleMessage(message);
},
onError: (error) => {
logger.error('传输层错误:', error);
this.eventHandlers.onError?.(error);
}
};
this.transport.setEventHandlers(transportHandlers);
logger.debug('TSRPC传输层已初始化');
}
/**
*
*/
private startSyncLoop(): void {
if (this.syncTimer) {
return;
}
const interval = 1000 / (this.config.syncRate || 20);
this.syncTimer = setInterval(() => {
this.processSyncVars();
}, interval);
logger.debug(`同步循环已启动,频率: ${this.config.syncRate} Hz`);
}
/**
*
*/
private stopSyncLoop(): void {
if (this.syncTimer) {
clearInterval(this.syncTimer);
this.syncTimer = null;
logger.debug('同步循环已停止');
}
}
/**
* SyncVar
*/
private processSyncVars(): void {
if (!NetworkManager.isServer) {
return; // 只有服务端发送同步消息
}
const syncVarMessages = SyncVarManager.instance.getPendingMessages();
for (const message of syncVarMessages) {
this.sendMessage(message).catch(error => {
logger.error('发送SyncVar消息失败:', error);
});
}
// 处理 RPC 消息
const rpcMessages = RpcManager.instance.getPendingRpcMessages();
for (const message of rpcMessages) {
this.sendMessage(message).catch(error => {
logger.error('发送RPC消息失败:', error);
});
}
}
/**
*
*/
private async sendMessage(message: NetworkMessage, targetClient?: number): Promise<void> {
if (!this.transport) {
logger.warn('传输层未初始化,无法发送消息');
return;
}
try {
await this.transport.sendMessage(message, targetClient);
this.stats.messagesSent++;
logger.debug(`发送消息: ${message.type}, 网络ID: ${message.networkId}`);
} catch (error) {
logger.error('发送消息失败:', error);
}
}
/**
*
*/
public handleIncomingMessage(message: NetworkMessage): void {
this.handleMessage(message);
}
/**
*
*/
private handleMessage(message: NetworkMessage): void {
this.stats.messagesReceived++;
switch (message.type) {
case 'syncvar':
SyncVarManager.instance.handleSyncVarMessage(message as SyncVarMessage);
break;
case 'rpc':
RpcManager.instance.handleRpcMessage(message as RpcMessage);
break;
default:
logger.warn(`未知消息类型: ${message.type}`);
}
}
}