Leaf and Cocos Creator game (i) use PROTOBUF to complete communication

Source: Internet
Author: User
Tags golang ide

Project Purpose:

    • Develop an interactive mini-game, limited to service-side experience less, so began to learn the leaf framework, the client with Cocos Creator.
    • This kind of learning case on the network is less, so want to learn, while sharing to the post-scholar, I would like to encourage myself!

Environment Construction:

    • Golang Environment Building and Cocos Creator Environment Building online tutorial a lot, no longer repeat, Golang IDE can use Goland.

    • Leaf Frame Address: https://github.com/name5566/leaf.git

    • Leaf Getting Started Tutorial: https://github.com/name5566/leaf/blob/master/TUTORIAL_ZH.md

    • Example Gihub Address:
      Server:https://github.com/ddkgo/leafserverexample.git
      Client:https://github.com/ddkgo/leafservercocosclient.git

    • Leafserverexample Construction:
      Get:
      git clone https://github.com/ddkgo/LeafServerExample.git
      Set the Leafserverexample directory to the GOPATH environment variable to get the Leaf:
      go get github.com/name5566/leaf
      Get PROTOBUF Support:
      go get github.com/golang/protobuf/proto

Body:

The server receives and processes messages:

1. Create a Msgpro.proto:

syntax = "proto3";package msg;message Hello {    int32 id = 1;    string name = 2;}

Compile the Msgpro.proto file (not known about this?) Please read the article "using Protobuf in Golang") to get the MsgPro.pb.go file with the following command:
protoc --go_out=. msgPro.proto
Place the MsgPro.pb.go under the Leafserverexample src/msg folder.

2. Edit the Msg.go file:

package msgimport (    "github.com/name5566/leaf/network/protobuf")// 使用 Protobuf 消息处理器var Processor = protobuf.NewProcessor()func init() {    Processor.Register(&Hello{})}

3. Next process the routing of the Hello message:

Route the Hello message to the game module. Open Leafserverexample gate/router.go, typing the following code:

package gateimport (    "server/msg"    "server/game")func init() {    // 这里指定消息 Hello 路由到 game 模块    msg.Processor.SetRouter(&msg.Hello{}, game.ChanRPC)}

4. Processing messages:

The Hello message is processed in the game module. Open Leafserverexample game/internal/handler.go, typing the following code:

package internalimport (    "server/msg"    "reflect"    "github.com/name5566/leaf/gate"    "github.com/name5566/leaf/log"    "github.com/golang/protobuf/proto")func init() {    // 向当前模块(game 模块)注册 Hello 消息的消息处理函数 handleHello    handler(&msg.Hello{}, handleHello)}func handler(m interface{}, h interface{}) {    skeleton.RegisterChanRPC(reflect.TypeOf(m), h)}func handleHello(args []interface{}) {    // 收到的 Hello 消息    m := args[0].(*msg.Hello)    // 消息的发送者    a := args[1].(gate.Agent)    // 输出收到的消息的内容    log.Debug("hello %v", m.GetName())    retBuf :=&msg.Hello{        Name: *proto.String("client"),    }    // 给发送者回应一个 Hello 消息    a.WriteMsg(retBuf)}

Client receives and processes messages:

Get Protobufjs, under the Leafservercocosclient directory:
npm install protobufjs

1.proto compiled into a static file:

Copy the Msgpro.proto into the Leafservercocosclient Node_modules.bin folder and compile the proto file into a static file using:

pbjs -t static-module -w commonjs -o protocol.js msgPro.protopbts -o protocol.d.ts protocol.js

Copy the Protocol.js and protocol.d.ts to the Leafservercocosclient Assets\script\protocol folder.

2. Create the WebSocket and connect:

New Netcontrol class:

const {Ccclass, property} = cc._decorator;//defines the global variable import * as Onfire from "./libs/onfire/onfire.js"; Class library for handling events import {Netconfig} from './netconfig ' @ccclassexport class Netcontrol extends CC. Component {Private _sock:websocket = NULL//The object of the current WebSocket connect () {if (This._sock ==null | | this._so Ck.readystate!==1) {//Current interface not open/reconnect This._sock = new WebSocket (netconfig.host+ ":" +netco            Nfig.port) This._sock.onopen = This._onopen.bind (this);            This._sock.onclose = This._onclose.bind (this);        This._sock.onmessage = This._onmessage.bind (this);    } return this; } _onopen () {Onfire.fire ("OnOpen")} _onclose (Err) {Onfire.fire ("OnClose", err) let self = th IS-let Revar = setinterval (function () {/////WebSocket after the re-connection is determined, and if the re-connection succeeds, the loop if is broken (self._sock.read Ystate = = 1) {clearinterval (revar)} Self._sock = newWebSocket (netconfig.host+ ":" +netconfig.port)}, 5000)//every 5 seconds try to re-connect} _onmessage (obj) {onfire.fire ("O        Nmessage ", obj)} send (msg) {if (this._sock.readystate = = 1) {this._sock.send (msg);        }} protobufaddtag (Tag:number,buffer:uint8array) {Let addtag_buffer=new Uint8array (buffer.length+2) Let tagbinary = This.binary (tag,2) addtag_buffer.set (tagbinary,0) Addtag_buffer.set (Buffer.subarray (0,buffer        . length), 2) return Addtag_buffer} parseprotobufid (obj,callback:function) {Let Blob:blob = Obj.data        Let reader = new FileReader ();        Reader.readasarraybuffer (BLOB);            Reader.onload = function (e) {Let unit16 = new Uint16array (e.target.result) Let id = unit16[0] Console.log ("Receive Message ID =" +id) Let Dataunit8array = new Uint8array (e.target.result) d Ataunit8array = Dataunit8array.slice (2) Callback (iD,dataunit8array)}} binary (Num:number, bits:number) {Let Resarry = [] Let Xresarry        = [] Let i=0;        for (;num>0;) {resarry.push (num% 2) NUM=NUM/2 i++;            } for (Let j=i-1;j>=0;j--) Xresarry.push (Resarry[j]) if (Bits < xresarry.length) {                Console.log ("Number of bits less than bits")} if (bits) {for (Let R = Xresarry.length; r < Bits; r++) {        Xresarry.unshift (0)}}//return Xresarry.join (). Replace (/,/g, '); Return Xresarry}}

Because in the Leaf, the default Protobuf Processor defines a complete PROTOBUF message in the following format:

-------------------------| id | protobuf message |-------------------------

So you need to add a header ID when sending a message:

sendHello(name : string){     let protocolId = 0     let message = msg.Hello.create({ id:0,name:name })     let buffer  = msg.Hello.encode(message).finish()     //leaf 前两位为协议序号,故需包装一下     let addtag_buffer = this.netControl.protoBufAddtag(protocolId,buffer)     this.netControl.send(addtag_buffer);     console.log("sendToWS");}

When the message returned by the leaf is received:

   onMessage(obj){        //leaf 前两位为协议序号,需要解一下啊协议序号        this.netControl.parseProtoBufId(obj,this.OnGameMessage.bind(this))      }

The same top two is the leaf auto-plus ID that needs to be processed:

    parseProtoBufId(obj,callback:Function){        let blob:Blob = obj.data        let reader = new FileReader();        reader.readAsArrayBuffer(blob);        reader.onload = function(e) {            let unit16 = new Uint16Array(e.target.result)            let id = unit16[0]            console.log("receive message id = "+id)            let dataUnit8Array = new Uint8Array(e.target.result)            dataUnit8Array = dataUnit8Array.slice(2)                        callback(id,dataUnit8Array)        }            }

Specific HelloWorld class:

Import {Netcontrol} from './netcontrol ' import * as Onfire from './libs/onfire/onfire ' import {msg} from './protocol/prot Ocol.js "Const {Ccclass, property} = Cc._decorator@ccclassexport Default class Helloworld extends CC. Component {@property (cc). Label) label:cc.    Label = null;    @property text:string = ' Hello '; Private Msssagefire Private Netcontrol:netcontrol = null private proto OnLoad () {This.netcontrol = new net        Control ()} start () {//init logic this.label.string = This.text;        This.netControl.connect ();    This.msssagefire=onfire.on ("OnMessage", This.onMessage.bind (This))} Onbtnsendhello () {This.sendhello ("DDK") } Sendhello (name:string) {Let ProtocolId = 0 let message = Msg. Hello.create ({id:0,name:name}) let buffer = Msg. Hello.encode (Message). Finish ()//leaf the first two bits is the protocol number, so you need to pack let Addtag_buffer = This.netControl.protoBufAddtag (pro Tocolid,buffer) this.netcOntrol.send (Addtag_buffer);    Console.log ("Sendtows"); } onMessage (obj) {//leaf The first two bits is the protocol number, need to solve the protocol sequence number This.netControl.parseProtoBufId (Obj,this. Ongamemessage.bind (This)}} ongamemessage (Id:number,data:uint8array) {if (id===0) {Console.log (            "Get Hello message!"); Let gamemsg = Msg.        Hello.decode (data) Console.log (GAMEMSG)}} OnDestroy () {onfire.un (this.msssagefire); }}

:

Server

Client

Goland Build Setting:

Reference:

Using Protobuf in the Leaf

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.