Compare commits
3 Commits
96e0ac9782
...
f0de649733
Author | SHA1 | Date | |
---|---|---|---|
f0de649733 | |||
c2901b2e37 | |||
787ac75484 |
@ -8,6 +8,7 @@
|
||||
|
||||
2. 登陆界面
|
||||
1. 连接网关并实现登陆功能。(已完成)
|
||||
2. 编写单独的消息解码器,派发消息时是已解码的消息。
|
||||
2. 编写单独的消息解码器,派发消息时是已解码的消息。(已完成)
|
||||
3. 登陆成功后关闭登陆界面,进入大厅界面。
|
||||
4. 网络断开时弹出转圈圈界面。
|
||||
5. ai 生成更宽一点的登陆界面,以及登陆注册 ui,转圈圈图标。
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { _decorator, Button, Component, EditBox, Label, Node } from 'cc'
|
||||
import { WsClient } from '../network/wsclient'
|
||||
import { WsConfig } from '../network/wsconfig'
|
||||
import { PbHelper } from '../network/pbHelper'
|
||||
import { ReqUserLogin, ServiceTypeId, MsgId, RspUserLogin } from '../network/pbExport'
|
||||
import { EventType } from '../constant'
|
||||
import * as pb from '../network/pbExport'
|
||||
import { MessageDispatcher } from '../network/messageDispatcher'
|
||||
const { ccclass, property } = _decorator
|
||||
|
||||
@ccclass('loginPanel')
|
||||
@ -21,11 +20,11 @@ export class loginPanel extends Component {
|
||||
start() {
|
||||
this.loginButton.node.on(Button.EventType.CLICK, this.onLoginButtonClick, this)
|
||||
// 监听websocket消息事件
|
||||
window.addEventListener(EventType.Ws, this.onMessage.bind(this))
|
||||
MessageDispatcher.Instance.On(pb.MsgId.RspUserLoginId, this.onLogin.bind(this))
|
||||
}
|
||||
|
||||
protected onDestroy(): void {
|
||||
window.removeEventListener(EventType.Ws, this.onMessage.bind(this))
|
||||
MessageDispatcher.Instance.Off(pb.MsgId.RspUserLoginId, this.onLogin.bind(this))
|
||||
}
|
||||
|
||||
// 登录按钮点击处理函数
|
||||
@ -40,40 +39,30 @@ export class loginPanel extends Component {
|
||||
this.statusLable.string = '请输入密码'
|
||||
return
|
||||
}
|
||||
const ws = WsClient.Instance()
|
||||
const ws = WsClient.Instance
|
||||
console.log(typeof ws)
|
||||
if (!ws.IsConnected) {
|
||||
await ws.ConnectAsync(WsConfig.Address[1].Address[0])
|
||||
if (!ws.IsConnected) {
|
||||
if (!WsClient.Instance.IsConnected) {
|
||||
await WsClient.Instance.ConnectAsync(WsConfig.Address[1].Address[0])
|
||||
if (!WsClient.Instance.IsConnected) {
|
||||
this.statusLable.string = '连接网络失败'
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
console.log('登陆帐号:', username, '密码:', pwd)
|
||||
|
||||
const req = new ReqUserLogin()
|
||||
req.username = username
|
||||
req.password = pwd
|
||||
req.version = '20250601123030'
|
||||
const buffer = ReqUserLogin.encode(req).finish()
|
||||
ws.Send(ServiceTypeId.STI_Login, MsgId.ReqUserLoginId, buffer)
|
||||
// console.log('登陆帐号:', username, '密码:', pwd)
|
||||
this.reqLogin(username, pwd)
|
||||
}
|
||||
|
||||
private onMessage(event: CustomEvent) {
|
||||
try {
|
||||
const [msgid, buffer] = PbHelper.DecodeClient(event.detail)
|
||||
switch (msgid) {
|
||||
case MsgId.RspUserLoginId:
|
||||
const rsp = PbHelper.Decode(RspUserLogin, buffer)
|
||||
console.log('收到返回消息:', rsp)
|
||||
default:
|
||||
// console.log('收到非json消息:', event.detail)
|
||||
}
|
||||
} catch (error) {
|
||||
// console.log('解析错误失败:', error)
|
||||
console.log(PbHelper.Uint8ToHex(event.detail))
|
||||
}
|
||||
private reqLogin(username, password: string) {
|
||||
const req = new pb.ReqUserLogin()
|
||||
req.username = username
|
||||
req.password = password
|
||||
req.version = '20250601123030'
|
||||
const buffer = pb.ReqUserLogin.encode(req).finish()
|
||||
WsClient.Instance.Send(pb.ServiceTypeId.STI_Login, pb.MsgId.ReqUserLoginId, buffer)
|
||||
}
|
||||
|
||||
private onLogin(rsp: typeof pb.RspUserLogin.prototype) {
|
||||
console.log('收到返回消息:', rsp)
|
||||
}
|
||||
|
||||
update(deltaTime: number) {}
|
||||
|
50
assets/scripts/network/messageDecoder.ts
Normal file
50
assets/scripts/network/messageDecoder.ts
Normal file
@ -0,0 +1,50 @@
|
||||
// MessageDecoder.ts
|
||||
import * as pb from './pbExport'
|
||||
|
||||
export class MessageDecoder {
|
||||
// 消息ID与消息类的映射表
|
||||
private static _messageClasses: Map<number, (buffer: Uint8Array) => any> = new Map()
|
||||
|
||||
/**
|
||||
* 注册消息类(启动时调用)
|
||||
* @param msgId 消息ID
|
||||
* @param decoder 解码函数(如 pb.ReqUserLogin.decode)
|
||||
*/
|
||||
public static Register<T>(msgId: number, decoder: (buffer: Uint8Array) => T): void {
|
||||
this._messageClasses.set(msgId, decoder)
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码消息(根据ID动态实例化对应消息类)
|
||||
* @param msgId 消息ID
|
||||
* @param buffer 原始消息(Uint8Array)
|
||||
* @returns 解码后的消息对象
|
||||
*/
|
||||
public static Decode(msgId: number, buffer: Uint8Array): [any, Error] {
|
||||
try {
|
||||
const decoder = this._messageClasses.get(msgId)
|
||||
if (!decoder) {
|
||||
return [null, new Error(`未注册的消息ID: ${msgId}`)]
|
||||
}
|
||||
// 实例化消息类并解码数据
|
||||
const instance = decoder(buffer)
|
||||
return [instance, null]
|
||||
} catch (err) {
|
||||
return [null, new Error(`解消息: ${msgId} 失败。err:${err}`)]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 字节流转换成Hex码
|
||||
* @param buffer 原始消息(Uint8Array)
|
||||
* @returns 字节流转换成Hex码
|
||||
*/
|
||||
public static Uint8ToHex(buffer: Uint8Array): string {
|
||||
return Array.from(buffer)
|
||||
.map((byte) => byte.toString(16).padStart(2, '0'))
|
||||
.join(' ')
|
||||
}
|
||||
}
|
||||
|
||||
MessageDecoder.Register(pb.MsgId.ReqUserLoginId, pb.ReqUserLogin.decode)
|
||||
MessageDecoder.Register(pb.MsgId.RspUserLoginId, pb.RspUserLogin.decode)
|
71
assets/scripts/network/messageDispatcher.ts
Normal file
71
assets/scripts/network/messageDispatcher.ts
Normal file
@ -0,0 +1,71 @@
|
||||
// MessageDispatcher.ts
|
||||
|
||||
/** 消息处理器类型 */
|
||||
export type MessageHandler = (data: any) => void
|
||||
|
||||
export class MessageDispatcher {
|
||||
private static _instance: MessageDispatcher
|
||||
private _handlers: Map<number, MessageHandler[]> = new Map()
|
||||
|
||||
/** 单例模式 */
|
||||
public static get Instance(): MessageDispatcher {
|
||||
if (!this._instance) {
|
||||
this._instance = new MessageDispatcher()
|
||||
}
|
||||
return this._instance
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册消息处理器(允许多个 Handler)
|
||||
* @param msgId 消息ID
|
||||
* @param handler 回调函数
|
||||
*/
|
||||
public On(msgId: number, handler: MessageHandler): void {
|
||||
if (!this._handlers.has(msgId)) {
|
||||
this._handlers.set(msgId, [])
|
||||
}
|
||||
this._handlers.get(msgId)?.push(handler) // 添加到队列
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除指定的消息处理器(通过函数引用精准匹配)
|
||||
* @param msgId 消息ID
|
||||
* @param handler 要移除的回调函数
|
||||
*/
|
||||
public Off(msgId: number, handler: MessageHandler): void {
|
||||
const handlers = this._handlers.get(msgId)
|
||||
if (!handlers) return
|
||||
|
||||
// 过滤掉指定的 handler
|
||||
const newHandlers = handlers.filter((h) => h !== handler)
|
||||
this._handlers.set(msgId, newHandlers)
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息派发器中handler数量
|
||||
* @param msgId 消息ID
|
||||
* @returns 返回消息派发器中handler数量
|
||||
*/
|
||||
public Size(msgId: number): number {
|
||||
if (msgId === 0) {
|
||||
return this._handlers.size
|
||||
}
|
||||
const handlers = this._handlers.get(msgId)
|
||||
if (handlers) {
|
||||
return handlers.length
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 派发消息(按注册顺序执行所有 Handler)
|
||||
* @param msgId 消息ID
|
||||
* @param msg 消息数据
|
||||
*/
|
||||
public Dispatch(msgId: number, msg: any): void {
|
||||
const handlers = this._handlers.get(msgId)
|
||||
if (handlers) {
|
||||
handlers.forEach((handler) => handler(msg)) // 顺序执行
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import { ClientMsg } from '../network/pbExport'
|
||||
import { EventType } from '../constant'
|
||||
import { PbHelper } from '../network/pbHelper'
|
||||
import { MessageDispatcher } from '../network/messageDispatcher'
|
||||
import { MessageDecoder } from '../network/messageDecoder'
|
||||
|
||||
export class WsClient {
|
||||
private socket: WebSocket | null = null
|
||||
@ -11,13 +11,20 @@ export class WsClient {
|
||||
private isConnected: boolean = false
|
||||
|
||||
private static instance: WsClient = null
|
||||
private static netEvent: EventTarget = null
|
||||
|
||||
// 单例
|
||||
public static Instance(): WsClient {
|
||||
public static get Instance(): WsClient {
|
||||
if (!this.instance) this.instance = new WsClient()
|
||||
return this.instance
|
||||
}
|
||||
|
||||
// 网络事件中心
|
||||
public static EventMgr(): EventTarget {
|
||||
if (!this.netEvent) this.netEvent = new EventTarget()
|
||||
return this.netEvent
|
||||
}
|
||||
|
||||
// 是否连接
|
||||
public get IsConnected(): boolean {
|
||||
return this.isConnected
|
||||
@ -112,8 +119,14 @@ export class WsClient {
|
||||
const buffer = await event.data.arrayBuffer()
|
||||
const uint8Array = new Uint8Array(buffer)
|
||||
// console.log('收到消息:', uint8Array)
|
||||
console.log('收到消息:', PbHelper.Uint8ToHex(uint8Array))
|
||||
window.dispatchEvent(new CustomEvent(EventType.Ws, { detail: uint8Array }))
|
||||
const cMsg = ClientMsg.decode(uint8Array)
|
||||
// console.log('收到消息:', MessageDecoder.Uint8ToHex(uint8Array))
|
||||
const [msg, err] = MessageDecoder.Decode(cMsg.msgId, cMsg.data)
|
||||
if (err) {
|
||||
console.error(err)
|
||||
return
|
||||
}
|
||||
MessageDispatcher.Instance.Dispatch(cMsg.msgId, msg)
|
||||
} catch (error) {
|
||||
console.error('解析网络消息失败:', error)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user