Laya ProtoBuffer

ProtoBuf 是 Protocol Buffer的简称,是Google旗下一款平台无关、可扩展的序列化结构数据格式,适用于数据存储,作为不同应用、语言之间相互通信的数据交换格式,序列化后的数据为二进制数据(pb格式的数据),类似XML、JSON。由于ProtoBuf的序列化效率和大小比较不错,网络通信上越来越多开始应用,结合WebSocket则是一种趋势。

protobufjs

protobufjs可以直接反射proto文件,不需要生成任何文件。

下载安装protobufjs

https://github.com/protobufjs/protobuf.js

使用NPM全局安装protobufjs

$ npm i -g protobufjs

$ npm i -g @egret/protobuf

将下载的protobuf.js文件放入bin/libs/文件夹下,然后在bin/index.html文件加载的index.js文件中添加loadLib("libs/protobuf.js"),即完成加载。

$ vim /bin/index.js
loadLib("libs/protobuf.js");

创建ProtoBuf协议文件

$ vim /bin/proto/msg.proto
syntax = "proto3";

package ns;
message Address{
    required string province = 1;
    required string city = 2;
    required string area = 3;
}

在Laya中使用protobuf.js

$ vim src/Test.ts
class Test{
    private pb = null;

    constructor(){
        Laya.init(Laya.Browser.clientWidth, Laya.Browser.clientHeight);
        Laya.Stat.show();
        this.initStage();
        this.run();
    }
    initStage():void{
        Laya.stage.autoSize = false;
        Laya.stage.frameRate = "slow";
        Laya.stage.screenMode = "horizontal";
        Laya.stage.scaleMode = "exactfit";
        Laya.stage.mouseEnabled = false;
        Laya.stage.alignH = "center";
        Laya.stage.alignV = "middle";
        Laya.stage.bgColor = "#808080";
    }
    run(){
        this.pb = Laya.Browser.window.protobuf;
        if(!this.pb){
            throw Error("your browser is not support protobuffer");
        }
        this.pb.load("proto/msg.proto", this.onProtoLoaded);
    }
    onProtoLoaded(error, root){
        if(error){
            throw error;
        }
        //查找
        let Message = root.lookup("ns.Address");
        console.log(Message);
        //创建
        let message = Message.create({province:"hunan"});
        console.log(message);//Address {province: "hunan"}
        //验证
        let errmsg = Message.verify(message);
        console.log(errmsg);//null
        if(errmsg){
            throw Error(errmsg);
        }
        //编码
        let buffer = Message.encode(message).finish();
        console.log(buffer);//Uint8Array(11) [10, 5, 104, 117, 110, 97, 110, 18, 0, 26, 0]
        //解码
        try{
            let message = Message.decode(buffer);
            console.log(message);//Address {province: "hunan", city: "", area: ""}
        }catch(e){
            if(e instanceof this.pb.util.ProtocolError){
                console.error("missing required field");
            }else{
                console.error("wire format is invalid");
            }
        }
    }
}
new Test();

封装

export default class Protobuf{
    /**
     * 单例模式
    */
    private static _instance:Protobuf;
    public static getInstance():Protobuf{
        if(!this._instance){
            this._instance = new Protobuf();
        }
        return this._instance;
    }    
    private constructor(){}

    /**
     * 获取protobuf文件中的消息类
     * @param protoUrl {string} protobuf文件地址
     * @param messageName {string} 消息类名
     * @param callback {Function} 回调函数
     * @param thisObj {any} this对象
     */
   public getMessage(protoUrl:string, messageName:string, callback:Function, thisObj:any = null):void{
       let pb = Laya.Browser.window.protobuf;
       if(!pb){
           throw Error("your browser is not support protobufjs");
       }
       pb.load(protoUrl, (error, root)=>{
           if(error){
               throw error;
           }
           let messageClass = root.lookup(messageName);
           callback && callback.apply(thisObj, [messageClass]);
       });
   }
   /**
    * 创建消息
    * @param messageClass {Message} 消息类
    * @param data {object} 消息字段集合
    */
   public create(messageClass, data:Object){
       return messageClass.create(data);
   }
   /**
    * 消息验证
    * @param messageClass {Message} 消息类
    * @param message {Object} 验证消息
    */
   public verify(messageClass, message){
       let errmsg = messageClass.verify(message);
       if(errmsg){
           throw new Error(errmsg);
       }
   }
   /**
    * 序列化编码生成protobuf
    * @param messageClass {Meesage} 消息类
    * @param message {object} 消息
    */
   public encode(messageClass, message){
       return messageClass.encode(message).finish();
   }
   /**
    * 反序列化解码生成对象
    * @param messageClass {Message} 消息类
    * @param buffer {} protobuf
    */
   public decode(messageClass, buffer){
       return messageClass.decode(buffer);
   }
}

测试

import Protobuf from "./libs/Protobuf";
class Test{
    private pb = null;

    constructor(){
        Laya.init(Laya.Browser.clientWidth, Laya.Browser.clientHeight);
        Laya.Stat.show();
        this.initStage();
        this.run();
    }
    initStage():void{
        Laya.stage.autoSize = false;
        Laya.stage.frameRate = "slow";
        Laya.stage.screenMode = "horizontal";
        Laya.stage.scaleMode = "exactfit";
        Laya.stage.mouseEnabled = false;
        Laya.stage.alignH = "center";
        Laya.stage.alignV = "middle";
        Laya.stage.bgColor = "#808080";
    }
    run(){
        Protobuf.getInstance().getMessage("proto/msg.proto", "ns.Address", (Message)=>{
            console.log(Message);//Type {options: undefined, name: "Address", parent: Namespace, resolved: false, comment: null, …}
            
            let data = {province:"", city:"", area:""};
            data.province = "hunan";
            data.city = "changsha";
            data.area = "yuelu";
            let message = Message.create(data);
            console.log(message);//Address {province: "hunan", city: "changsha", area: "yuelu"}

            let errmsg = Message.verify(message);
            console.log(errmsg);//null
            if(errmsg){
                throw new Error(errmsg);
            }

            let buffer = Message.encode(message).finish();
            console.log(buffer);//Uint8Array(24) [10, 5, 104, 117, 110, 97, 110, 18, 8, 99, 104, 97, 110, 103, 115, 104, 97, 26, 5, 121, 117, 101, 108, 117]

            let msg = Message.decode(buffer);
            console.log(msg);//Address {province: "hunan", city: "changsha", area: "yuelu"}
        });
    }
}
new Test();
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值