308 lines
8.6 KiB
TypeScript
308 lines
8.6 KiB
TypeScript
|
|
import { NetConfig, DefaultNetConfig } from './NetConfig';
|
|||
|
|
import { NetEvent } from './NetEvent';
|
|||
|
|
import { PlatformAdapter, ClientConfig } from './PlatformAdapter';
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 网络管理器单例
|
|||
|
|
* 负责管理网络连接和消息通信
|
|||
|
|
*/
|
|||
|
|
export class NetManager {
|
|||
|
|
private static _instance: NetManager | null = null;
|
|||
|
|
|
|||
|
|
/** TSRPC Client 实例 (HttpClient) */
|
|||
|
|
private _client: any = null;
|
|||
|
|
|
|||
|
|
/** 是否已连接 */
|
|||
|
|
private _isConnected: boolean = false;
|
|||
|
|
|
|||
|
|
/** 网络配置 */
|
|||
|
|
private _config: NetConfig | null = null;
|
|||
|
|
|
|||
|
|
/** 重连计数 */
|
|||
|
|
private _reconnectCount: number = 0;
|
|||
|
|
|
|||
|
|
/** 重连定时器 */
|
|||
|
|
private _reconnectTimer: any = null;
|
|||
|
|
|
|||
|
|
/** 事件监听器 */
|
|||
|
|
private _eventListeners: Map<string, Function[]> = new Map();
|
|||
|
|
|
|||
|
|
private constructor() {}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取单例实例
|
|||
|
|
*/
|
|||
|
|
static getInstance(): NetManager {
|
|||
|
|
if (!this._instance) {
|
|||
|
|
this._instance = new NetManager();
|
|||
|
|
}
|
|||
|
|
return this._instance;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 设置服务协议 (必须在 init 之前调用)
|
|||
|
|
* @param serviceProto 从 shared 目录导入的协议定义
|
|||
|
|
*/
|
|||
|
|
setServiceProto(serviceProto: any): void {
|
|||
|
|
PlatformAdapter.setServiceProto(serviceProto);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 初始化网络管理器
|
|||
|
|
* @param config 网络配置
|
|||
|
|
*/
|
|||
|
|
init(config: NetConfig): void {
|
|||
|
|
this._config = {
|
|||
|
|
...DefaultNetConfig,
|
|||
|
|
...config
|
|||
|
|
} as NetConfig;
|
|||
|
|
|
|||
|
|
console.log('[NetManager] Initialized with config:', this._config);
|
|||
|
|
console.log('[NetManager] Platform:', PlatformAdapter.getPlatformInfo());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 连接服务器
|
|||
|
|
*/
|
|||
|
|
async connect(): Promise<boolean> {
|
|||
|
|
try {
|
|||
|
|
console.log('[NetManager] Connecting to server:', this._config.serverUrl);
|
|||
|
|
|
|||
|
|
// 创建客户端配置
|
|||
|
|
const clientConfig: ClientConfig = {
|
|||
|
|
server: this._config.serverUrl,
|
|||
|
|
json: true,
|
|||
|
|
timeout: this._config.timeout
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 根据平台创建对应的客户端
|
|||
|
|
this._client = PlatformAdapter.createClient(clientConfig);
|
|||
|
|
|
|||
|
|
// HttpClient 不需要显式连接,创建即可使用
|
|||
|
|
// 如果未来需要 WebSocket 支持,可以在这里添加 connect() 调用
|
|||
|
|
|
|||
|
|
this._isConnected = true;
|
|||
|
|
this._reconnectCount = 0;
|
|||
|
|
|
|||
|
|
this.emit(NetEvent.Connected);
|
|||
|
|
console.log('[NetManager] Client created successfully');
|
|||
|
|
|
|||
|
|
// client 可能不需要显式连接
|
|||
|
|
// 对于 WsClient 需要调用 connect()
|
|||
|
|
|
|||
|
|
this._isConnected = true;
|
|||
|
|
this._reconnectCount = 0;
|
|||
|
|
|
|||
|
|
this.emit(NetEvent.Connected);
|
|||
|
|
console.log('[NetManager] Connected successfully');
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('[NetManager] Connection failed:', error);
|
|||
|
|
this.emit(NetEvent.Error, error);
|
|||
|
|
|
|||
|
|
// 尝试重连
|
|||
|
|
if (this._config.autoReconnect) {
|
|||
|
|
this.scheduleReconnect();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 断开连接
|
|||
|
|
*/
|
|||
|
|
disconnect(): void {
|
|||
|
|
if (!this._isConnected) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
// HttpClient 无需显式断开连接
|
|||
|
|
// 如果使用 WebSocket,可以在这里调用 disconnect()
|
|||
|
|
|
|||
|
|
this._isConnected = false;
|
|||
|
|
this._client = null;
|
|||
|
|
if(this._reconnectTimer){
|
|||
|
|
this._reconnectTimer = null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// TODO: 调用客户端的断开连接方法
|
|||
|
|
if (this._client && typeof this._client.disconnect === 'function') {
|
|||
|
|
this._client.disconnect();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this._isConnected = false;
|
|||
|
|
this._client = null;
|
|||
|
|
|
|||
|
|
this.emit(NetEvent.Disconnected);
|
|||
|
|
console.log('[NetManager] Disconnected');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 调用 API
|
|||
|
|
* @param apiName API 名称
|
|||
|
|
* @param req 请求参数
|
|||
|
|
*/
|
|||
|
|
async callApi<Req, Res>(apiName: string, req: Req): Promise<Res | null> {
|
|||
|
|
if (!this._isConnected || !this._client) {
|
|||
|
|
console.error('[NetManager] Not connected');
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
console.log(`[NetManager] Calling API: ${apiName}`, req);
|
|||
|
|
|
|||
|
|
// TODO: 根据实际的协议定义调用 API
|
|||
|
|
const result = await this._client.callApi(apiName, req);
|
|||
|
|
|
|||
|
|
if (result.isSucc) {
|
|||
|
|
console.log(`[NetManager] API ${apiName} success:`, result.res);
|
|||
|
|
return result.res;
|
|||
|
|
} else {
|
|||
|
|
console.error(`[NetManager] API ${apiName} failed:`, result.err);
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error(`[NetManager] API ${apiName} error:`, error);
|
|||
|
|
this.emit(NetEvent.Error, error);
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 监听消息
|
|||
|
|
* @param msgName 消息名称
|
|||
|
|
* @param handler 处理函数
|
|||
|
|
*/
|
|||
|
|
listenMsg(msgName: string, handler: Function): void {
|
|||
|
|
if (!this._client) {
|
|||
|
|
console.error('[NetManager] Client not initialized');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log(`[NetManager] Listening message: ${msgName}`);
|
|||
|
|
|
|||
|
|
// TODO: 根据实际的 TSRPC 客户端实现监听消息
|
|||
|
|
if (typeof this._client.listenMsg === 'function') {
|
|||
|
|
this._client.listenMsg(msgName, handler);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 发送消息
|
|||
|
|
* @param msgName 消息名称
|
|||
|
|
* @param msg 消息内容
|
|||
|
|
*/
|
|||
|
|
sendMsg(msgName: string, msg: any): void {
|
|||
|
|
if (!this._isConnected || !this._client) {
|
|||
|
|
console.error('[NetManager] Not connected');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log(`[NetManager] Sending message: ${msgName}`, msg);
|
|||
|
|
|
|||
|
|
// TODO: 根据实际的 TSRPC 客户端实现发送消息
|
|||
|
|
if (typeof this._client.sendMsg === 'function') {
|
|||
|
|
this._client.sendMsg(msgName, msg);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 安排重连
|
|||
|
|
*/
|
|||
|
|
private scheduleReconnect(): void {
|
|||
|
|
if (!this._config) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (this._reconnectCount >= (this._config.maxReconnectTimes || 5)) {
|
|||
|
|
console.error('[NetManager] Max reconnect times reached');
|
|||
|
|
this.emit(NetEvent.ReconnectFailed);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this._reconnectCount++;
|
|||
|
|
console.log(`[NetManager] Scheduling reconnect (${this._reconnectCount}/${this._config.maxReconnectTimes})...`);
|
|||
|
|
|
|||
|
|
this.emit(NetEvent.Reconnecting, this._reconnectCount);
|
|||
|
|
|
|||
|
|
this._reconnectTimer = setTimeout(() => {
|
|||
|
|
this.reconnect();
|
|||
|
|
}, this._config.reconnectInterval || 3000);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 重新连接
|
|||
|
|
*/
|
|||
|
|
private async reconnect(): Promise<void> {
|
|||
|
|
console.log('[NetManager] Reconnecting...');
|
|||
|
|
|
|||
|
|
const success = await this.connect();
|
|||
|
|
|
|||
|
|
if (success) {
|
|||
|
|
this.emit(NetEvent.ReconnectSuccess);
|
|||
|
|
} else if (this._config?.autoReconnect) {
|
|||
|
|
this.scheduleReconnect();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 监听网络事件
|
|||
|
|
* @param event 事件名称
|
|||
|
|
* @param callback 回调函数
|
|||
|
|
*/
|
|||
|
|
on(event: NetEvent, callback: Function): void {
|
|||
|
|
if (!this._eventListeners.has(event)) {
|
|||
|
|
this._eventListeners.set(event, []);
|
|||
|
|
}
|
|||
|
|
this._eventListeners.get(event)!.push(callback);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 取消监听网络事件
|
|||
|
|
* @param event 事件名称
|
|||
|
|
* @param callback 回调函数
|
|||
|
|
*/
|
|||
|
|
off(event: NetEvent, callback: Function): void {
|
|||
|
|
const listeners = this._eventListeners.get(event);
|
|||
|
|
if (listeners) {
|
|||
|
|
const index = listeners.indexOf(callback);
|
|||
|
|
if (index > -1) {
|
|||
|
|
listeners.splice(index, 1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 触发事件
|
|||
|
|
* @param event 事件名称
|
|||
|
|
* @param args 事件参数
|
|||
|
|
*/
|
|||
|
|
private emit(event: NetEvent, ...args: any[]): void {
|
|||
|
|
const listeners = this._eventListeners.get(event);
|
|||
|
|
if (listeners) {
|
|||
|
|
listeners.forEach(callback => {
|
|||
|
|
try {
|
|||
|
|
callback(...args);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('[NetManager] Event callback error:', error);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取连接状态
|
|||
|
|
*/
|
|||
|
|
get isConnected(): boolean {
|
|||
|
|
return this._isConnected;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取客户端实例
|
|||
|
|
*/
|
|||
|
|
get client(): any {
|
|||
|
|
return this._client;
|
|||
|
|
}
|
|||
|
|
}
|