重构NetManager支持MessagePair,新增TSRPCWsClient。

This commit is contained in:
janing
2025-12-18 13:25:04 +08:00
parent c12e439add
commit fb940452db
41 changed files with 976 additions and 681 deletions

View File

@@ -0,0 +1,76 @@
/**
* 消息对定义基类
* 用于定义成对出现的请求和响应消息
*/
export abstract class MessagePair<TReq, TRes> {
/** 请求消息名称 */
abstract readonly requestName: string;
/** 响应消息名称 */
abstract readonly responseName: string;
/** 请求消息类型检查 */
abstract isValidRequest(msg: any): msg is TReq;
/** 响应消息类型检查 */
abstract isValidResponse(msg: any): msg is TRes;
}
/**
* 消息对注册表
* 用于管理所有的消息对
*/
export class MessagePairRegistry {
private static _instance: MessagePairRegistry;
private _pairs: Map<string, MessagePair<any, any>> = new Map();
static getInstance(): MessagePairRegistry {
if (!this._instance) {
this._instance = new MessagePairRegistry();
}
return this._instance;
}
/**
* 注册消息对
* @param pair 消息对实例
*/
register(pair: MessagePair<any, any>): void {
this._pairs.set(pair.requestName, pair);
console.log(`[MessagePairRegistry] Registered message pair: ${pair.requestName} -> ${pair.responseName}`);
}
/**
* 根据请求消息名获取响应消息名
* @param requestName 请求消息名
* @returns 响应消息名如果未找到返回null
*/
getResponseName(requestName: string): string | null {
const pair = this._pairs.get(requestName);
return pair ? pair.responseName : null;
}
/**
* 根据请求消息名获取消息对
* @param requestName 请求消息名
* @returns 消息对实例如果未找到返回null
*/
getPair(requestName: string): MessagePair<any, any> | null {
return this._pairs.get(requestName) || null;
}
/**
* 检查是否为已注册的请求消息
* @param msgName 消息名
*/
isRegisteredRequest(msgName: string): boolean {
return this._pairs.has(msgName);
}
/**
* 获取所有已注册的消息对
*/
getAllPairs(): MessagePair<any, any>[] {
return Array.from(this._pairs.values());
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "3ba46d91-073d-44d6-8157-05f1af758121",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,23 @@
import { MessagePairRegistry } from './MessagePairBase';
import { LoginMessagePair } from './Pair/LoginMessagePair';
import { MoveMessagePair } from './Pair/MoveMessagePair';
import { SendMessagePair } from './Pair/SendMessagePair';
/**
* 消息对初始化
* 在应用启动时调用此函数注册所有消息对
*/
export function initMessagePairs(): void {
const registry = MessagePairRegistry.getInstance();
// 注册登录消息对
registry.register(new LoginMessagePair());
// 注册移动消息对
registry.register(new MoveMessagePair());
// 注册发送消息对
registry.register(new SendMessagePair());
console.log('[MessagePairs] All message pairs registered successfully');
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "9b552413-09a9-4ec6-b389-ea371b734a41",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,84 @@
import { initMessagePairs } from './MessagePairInit';
import { MsgManager } from './MsgManager';
/**
* 消息系统使用示例
*/
export class MsgExample {
/**
* 初始化消息系统
* 应在游戏启动时调用
*/
static init(): void {
// 初始化消息对注册表
initMessagePairs();
console.log('[MsgExample] Message system initialized');
}
/**
* 登录示例
*/
static async loginExample(): Promise<void> {
const msgMgr = MsgManager.getInstance();
try {
const response = await msgMgr.login({
playerId: 'player123',
playerName: 'TestPlayer'
});
if (response && response.success) {
console.log('登录成功:', response.player);
} else {
console.log('登录失败:', response?.message);
}
} catch (error) {
console.error('登录请求异常:', error);
}
}
/**
* 移动示例
*/
static async moveExample(): Promise<void> {
const msgMgr = MsgManager.getInstance();
try {
const response = await msgMgr.move({
x: 100,
y: 200
});
if (response && response.success) {
console.log('移动成功:', response.position);
} else {
console.log('移动失败:', response?.message);
}
} catch (error) {
console.error('移动请求异常:', error);
}
}
/**
* 发送消息示例
*/
static async sendMessageExample(): Promise<void> {
const msgMgr = MsgManager.getInstance();
try {
const response = await msgMgr.send({
content: 'Hello, World!'
});
if (response) {
console.log('消息发送成功:', response.time);
} else {
console.log('消息发送失败');
}
} catch (error) {
console.error('发送消息异常:', error);
}
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "4c559445-88e3-4fe2-a87c-8c9ef390aa60",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,55 @@
import { NetManager } from '../../Framework/Net/NetManager';
import { MsgReqLogin } from '../../Shared/protocols/MsgReqLogin';
import { MsgReqMove } from '../../Shared/protocols/MsgReqMove';
import { MsgReqSend } from '../../Shared/protocols/MsgReqSend';
import { MsgResLogin } from '../../Shared/protocols/MsgResLogin';
import { MsgResMove } from '../../Shared/protocols/MsgResMove';
import { MsgResSend } from '../../Shared/protocols/MsgResSend';
import { LoginMessagePair } from './Pair/LoginMessagePair';
import { MoveMessagePair } from './Pair/MoveMessagePair';
import { SendMessagePair } from './Pair/SendMessagePair';
/**
* 消息管理器 - 提供类型安全的消息发送方法
*/
export class MsgManager {
private static _instance: MsgManager;
static getInstance(): MsgManager {
if (!this._instance) {
this._instance = new MsgManager();
}
return this._instance;
}
private get netManager(): NetManager {
return NetManager.getInstance();
}
/**
* 发送登录请求
* @param loginData 登录数据
* @returns 登录响应
*/
async login(loginData: MsgReqLogin): Promise<MsgResLogin | null> {
return this.netManager.callMsg(new LoginMessagePair(), loginData);
}
/**
* 发送移动请求
* @param moveData 移动数据
* @returns 移动响应
*/
async move(moveData: MsgReqMove): Promise<MsgResMove | null> {
return this.netManager.callMsg(new MoveMessagePair(), moveData);
}
/**
* 发送消息请求
* @param sendData 发送数据
* @returns 发送响应
*/
async send(sendData: MsgReqSend): Promise<MsgResSend | null> {
return this.netManager.callMsg(new SendMessagePair(), sendData);
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "871b5daf-492f-4ff7-adac-a13bbf6b82ce",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "6f3ea388-fd67-45a4-9bfc-cae858378b7a",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,21 @@
import { MsgReqLogin } from '../../../Shared/protocols/MsgReqLogin';
import { MsgResLogin } from '../../../Shared/protocols/MsgResLogin';
import { MessagePair } from '../MessagePairBase';
/**
* 登录消息对实现
*/
export class LoginMessagePair extends MessagePair<MsgReqLogin, MsgResLogin> {
readonly requestName = 'ReqLogin';
readonly responseName = 'ResLogin';
isValidRequest(msg: any): msg is MsgReqLogin {
return msg && typeof msg.playerId === 'string';
}
isValidResponse(msg: any): msg is MsgResLogin {
return msg &&
typeof msg.success === 'boolean' &&
typeof msg.message === 'string';
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "8a0f8893-e078-4885-8407-70944f67d185",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,23 @@
import { MsgReqMove } from '../../../Shared/protocols/MsgReqMove';
import { MsgResMove } from '../../../Shared/protocols/MsgResMove';
import { MessagePair } from '../MessagePairBase';
/**
* 移动消息对实现
*/
export class MoveMessagePair extends MessagePair<MsgReqMove, MsgResMove> {
readonly requestName = 'ReqMove';
readonly responseName = 'ResMove';
isValidRequest(msg: any): msg is MsgReqMove {
return msg &&
typeof msg.x === 'number' &&
typeof msg.y === 'number';
}
isValidResponse(msg: any): msg is MsgResMove {
return msg &&
typeof msg.success === 'boolean' &&
typeof msg.message === 'string';
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "f95aa765-9371-4644-9694-8eb8dd7d8930",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,19 @@
import { MsgReqSend } from '../../../Shared/protocols/MsgReqSend';
import { MsgResSend } from '../../../Shared/protocols/MsgResSend';
import { MessagePair } from '../MessagePairBase';
/**
* 发送消息对实现
*/
export class SendMessagePair extends MessagePair<MsgReqSend, MsgResSend> {
readonly requestName = 'ReqSend';
readonly responseName = 'ResSend';
isValidRequest(msg: any): msg is MsgReqSend {
return msg && typeof msg.content === 'string';
}
isValidResponse(msg: any): msg is MsgResSend {
return msg && msg.time instanceof Date;
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "d9ef0dad-c949-4a46-9306-d4a060a40a3b",
"files": [],
"subMetas": {},
"userData": {}
}