npm install protobufjs@6.8.4 -g
npm install @egret/protobuf -g
package gameProto;
gameProto
为包名,必须添加包名,这个可以修改,需要同时修改接发消息的位置
pb-egret generate
这个会编译Laya可以使用的protobuf消息对象,更新proto文件需要重新生成
- 复制一次:
- 复制
protobuf/library/protobuf-library.min.js
到项目bin/libs
下 - 复制
protobuf/library/protobuf-library.d.ts
到项目libs
下
- 复制
- 每次更新复制:
- 复制
protobuf/bundles/protobuf-bundles.min.js
到项目bin/libs
下 - 复制
protobuf/bundles/rotobuf-bundles.d.ts
到项目libs
下
- 复制
勾选 protobuf-library.js
和 protobuf-bundles.js
库的顺序一定不能错!!在bin/index.js里查看,要先加载protobuf-library.js,然后再加载protobuf-bundles.js,不然会报错,找不到protobuf.roots初始化对象。
public static MESSAGEPROTOTYPE = {
HEARTBEAT:{
type:'HeartBeat',
id:0,
action:'-1'
},
REQ_LOGIN:{
type:'Req_Login',
id:0x0401,
action:'userAction'
},
RESP_LOGIN:{
type:'Resp_Login',
id:-0x0401,
action:'-1'
}
//...其他配置
}
读写都按配置都数组顺序处理
{
type:string,
write:string,
read:string,
constNumber:number,
costString:string,
key:string
}
- type: 处理类型
- write: 发送写处理函数
- read: 接受读处理函数
- constNumber: constNumber类型的处理值
- costString: costString类型处理值
- key:默认处理目标字段
- constNumber: 写处理使用constNumber字段,读处理忽略值
- constString: 写处理使用constString字段,读处理忽略值
- keyLength: 写处理使用消息体key字段对应值的length,读处理预先存下lenght,在读取key值内容时候使用
- keyInt: 写处理直接写入key字段对应读值,读处理直接读取值写入输出对象的key值
- key: 写处理直接写入key字段对应读值,读处理使用预存读长度值读取内容写入输出对象的key值
- keyBuffer: 写处理直接写入key字段的对应值的buffer,读处理使用当前容器的pos值和预存的长度值读取内容写入输出对象的key值
对应的结构
0xabef0101|包体长度|协议号|action长度|action名称|包体内容
public static PROTOBUFTEMPLATE = [
{
type:'constNumber',
write:'writeInt32',
read:'getInt32',
constNumber:0xabef0101,
key:'sign'
},
{
type:'keyLength',
write:'writeInt32',
read:'getInt32',
key:'data'
},
{
type:'keyInt',
write:'writeInt32',
read:'getInt32',
key:'id'
},
{
type:'keyLength',
write:'writeInt32',
read:'getInt32',
key:'action'
},
{
type:'key',
write:'writeUTFBytes',
read:'getUTFBytes',
key:'action'
},
{
type:'keyBuffer',
write:'writeArrayBuffer',
read:'getUint8Array',
key:'data'
}
]
msgOut(config:any,msg: any) {
const T = gameProto[config.type]
let message : typeof T = new gameProto[config.type]()
message = {
...msg
}
const data = new Laya.Byte(gameProto[config.type].encode(message).finish())
this.postOffice.sendProtoMessage({
data,
...config
})
}
例如 发出登陆消息 protobuf里的Reg_Login
消息,对应的配置为GameConstant.MESSAGEPROTOTYPE.REQ_LOGIN
this.msgOut(GameConstant.MESSAGEPROTOTYPE.REQ_LOGIN,{account:'abc',loginType:99})
Postoffice
会按配置处理消息发送ArrayBuffer
onMessageCallbck:(message)=>{
if(GameConstant.PROTOBUFMESSAGEIDLIST[`ID_${message.id}`] != undefined){
const key = fishingProto[GameConstant.PROTOBUFMESSAGEIDLIST[`ID_${message.id}`]]
message.obj = key.decode(message.data)
message.obj = {
...key.prototype,
...message.obj
}
}else{
console.log(`Unknow Proto Message ID : ${message.id}`)
}
console.log(message)
switch(message.id){
case GameConstant.MESSAGEPROTOTYPE.RESP_LOGIN.id:
console.log(message.obj.desc)
break
}
}
message
为Postoffice
按配置处理后的消息体,protobuf对应的内容在data
字段,按id
字段找到protobuf对象,处理后的对象为message.obj
,使用key.prototype
填入默认对象值,防止比如为0的默认值不存在。二级对象的默认值要用包内的指定对象类型的prototype填入。
初始化Postoffice的时候可以设置是否使用心跳
如果使用心跳,start链接的时候要提交心跳方法和失败回调