游戏《Protecive goddess》(一)"/>
creator游戏《Protecive goddess》(一)
本系列主要是对此次项目从0~1的一个复盘
一来方便自己后期回顾,暴露问题
二来希望可以给新入坑的朋友们一些帮助
不会讲的太细,主要是提供一个思路和大的框架,话不多说,我们开始吧。
项目中如果有不对的地方或者有更好的解决方案,欢迎大家指正!
一、sproto介绍
之前项目都是用的protobuf,此次使用sproto主要原因如下:
① 项目初期定的客户端跟服务器都是用lua开发
② 服务端基于skynet框架开发,而sproto正是由skynet提供的一套协议,它类似 protobuf ,但设计更加简洁,也更利于 lua 使用
官方介绍:
二、准备工作
sprotojs插件:
① 插件准备:文档中有案例介绍可以自行了解下,项目中只需要引入sproto.js、utils.js这两个文件
② 协议文件准备: 服务器会提供一个xxx.sproto源文件,将其转换为.spb就可以使用了
③ 协议加载:之前的一篇文章有过记录
三、协议解析
客户端跟服务器商定好每条消息的结构之后,便可以进行对应的 拆包 跟 封包 的工作了。
我们目前的消息结构如下
/* Head* 2 byte是包头,读取后面body的size* body* 2 byte eventid* 2 byte datasize* n byte data -- 这个data才是用sproto解析出来的,(pakename, data),pakename是对应的数据结构名字(或者说是table变量的变量名)*/
核心的拆包和封包代码如下,主要通过对协议加载得到的 m_sproto 进行 encode 和 decode,与之对应的还有 pencode 和 pdecode ,带p的意思是对封好的数据包进一步的压缩,以减少消息的包体。
文中的 sprotoMap 存储的是协议eventid与pakeName的相互映射
/*** 数据封包 发送* @param eventId * @param data */public static encodeBuffer(eventId: number, data: any) {let id: number = eventId;let protoName = sprotoMap[id.toString()]let dataArr = this.m_sproto.pencode(protoName, data);let dataBuff = this.arr2Buffer(dataArr); // printf.Log("eventId:", eventId, "protoName:" , protoName, " datass:" , datass)// printf.Log("dataBuff:", dataBuff, " dataBuff.byteLength:" , dataBuff.byteLength)let datasizeBuff = this.createBuffer(dataBuff.byteLength);let eventidBuff = this.createBuffer(eventId);let bodyBuff = this.ConnectArrayBuff(eventidBuff, datasizeBuff, dataBuff);let headBuff = this.createBuffer(bodyBuff.byteLength);return this.ConnectArrayBuff(headBuff, bodyBuff);}/*** 数据解包 派发* @param buffer */public static decodeBuffer(buffer) {let view: DataView = new DataView(buffer);let dataBuff = buffer.slice(6, buffer.length)let eventId = view.getInt16(2, false)let name = sprotoMap[eventId];let data = this.m_sproto.pdecode(name, new Uint8Array(dataBuff));let message = new sprotoMessage()message.pakeName = namemessage.body = datareturn message;}private static arr2Buffer(arr){let len = arr.length;let arrBuffer = new Uint8Array(len);for(let i=0; i<len; i++){arrBuffer[i] = arr[i];}return arrBuffer.buffer;}private static createBuffer(data) {var _typeBuff = new ArrayBuffer(2);var total = data;var view = new DataView(_typeBuff);view.setInt16(0, total, false);return _typeBuff;}/*** 字节头和数据组合成arrayBuff* @param args 字节头和数据buff*/private static ConnectArrayBuff(...args: any[]): ArrayBuffer {var length = 0;var buffer = null;for (let i = 0; i < args.length; i++) {buffer = args[i];length += buffer.byteLength;}var joined = new Uint8Array(length);var offset = 0;for (let i = 0; i < args.length; i++) {buffer = args[i];joined.set(new Uint8Array(buffer), offset);offset += buffer.byteLength;}return joined.buffer;};
更多推荐
creator游戏《Protecive goddess》(一)
发布评论