mongodb的安裝及配置,參考下文:
https://blog.csdn.net/heshushun/article/details/77776706
proto註冊協議擴充:
1.服務端:
編譯 lobby.proto 檔案(對此不瞭解?請先閱讀《在 Golang 中使用 Protobuf》一文)得到 lobby.pb.go 檔案,命令如下:
protoc --go_out=. lobby.proto
將lobby.pb.go 放在LeafServerExample src/msg檔案夾下。
2.用戶端:
把lobby.proto 複製到LeafServerCocosClient node_modules.bin檔案夾下,把proto檔案編譯成靜態檔案使用:
pbjs -t static-module -w commonjs -o protocol.js lobby.protopbts -o protocol.d.ts protocol.js
把protocol.js 和protocol.d.ts拷貝到LeafServerCocosClient assets\script\protocol檔案夾中.
3.lobby.proto:
syntax = "proto3";package msg;enum Result { REGISTER_SUCCESS=0; REGISTER_FAIL=1; LOGIN_SUCCESS=2; LOGIN_FAIL=3;}message Test { string Test = 2;}// 使用者登陸協議message UserLogin { string LoginName = 1; // 使用者名稱 string LoginPW =2; // 密碼}// 註冊協議message UserRegister { string LoginName =1; // 使用者名稱 string LoginPW =2; // 密碼}// 訊息返回協議message UserResult { Result RetResult =1; string ErrorInfo = 2;}// 玩家有角色的情況message UserST { string UID =1; // 帳號ID string ServerID =2; // 伺服器ID string RoleUID =3; // 角色UID string RoleName =4; // 角色名稱字 string RoleLev =5; // 角色等級 string Coin =6; // 金幣 // 其他的暫時不做定義}
向當前模組(game 模組)註冊 訊息處理函數
func init() { handler(&msg.UserLogin{}, handleUserLogin) handler(&msg.UserRegister{}, handleUserRegister)}
處理相關訊息
func handleUserRegister(args []interface{}) { m := args[0].(*msg.UserRegister) a := args[1].(gate.Agent) name :=m.GetLoginName() pwd :=m.GetLoginPW() log.Debug("receive UserRegister name=%v", m.GetLoginName()) reg := regexp.MustCompile(`/^[a-zA-Z\d]\w{2,10}[a-zA-Z\d]$/`) matched := reg.FindString(name) if(matched!=" "){ log.Debug("UserRegister name is licit", ) } err := mongodbmgr.Find("game","login",bson.M{"name":name,}) if err == nil { fmt.Println(err) log.Debug("UserRegister find in fail", ) retBuf := &msg.UserResult{ RetResult: msg.Result_REGISTER_FAIL, ErrorInfo:"帳號已存在!", } a.WriteMsg(retBuf) } err =mongodbmgr.Insert("game","login",bson.M{"name":name,"password":pwd}) if err != nil { fmt.Println(err) log.Debug("UserRegister write in fail", ) retBuf := &msg.UserResult{ RetResult: msg.Result_REGISTER_FAIL, ErrorInfo:"註冊失敗,請稍後再試!", } a.WriteMsg(retBuf) } else{ log.Debug("UserRegister write in success", ) retBuf := &msg.UserResult{ RetResult: msg.Result_REGISTER_SUCCESS, } a.WriteMsg(retBuf) }}
func handleUserLogin(args []interface{}) { m := args[0].(*msg.UserLogin) a := args[1].(gate.Agent) log.Debug("receive UserLogin name=%v", m.GetLoginName()) retBuf := &msg.UserResult{ RetResult: msg.Result_LOGIN_SUCCESS, ErrorInfo:"登陸失敗,請稍後再試!", } a.WriteMsg(retBuf)}
初始化時串連mongodb
package mongodbmgrimport ( "fmt" "github.com/name5566/leaf/db/mongodb" "github.com/name5566/leaf/log" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson")// 串連訊息var dialContext = new(mongodb.DialContext)func init() { Connect()}func Connect() { c, err := mongodb.Dial("localhost", 10) if err != nil { fmt.Println(err) return } //defer c.Close() // index c.EnsureUniqueIndex("game", "login", []string{"name"}) log.Release("mongodb Connect success") dialContext = c Test()}func Test() { err :=Find("game","login",bson.M{"name":"hello"}) if err == nil { log.Debug("Test have data,regFail!", ) }else{ err =Insert("game","login",bson.M{"name":"hello","password":"123456"}) if err != nil { fmt.Println(err) log.Debug("Test write in fail", ) } }}func Example() { c, err := mongodb.Dial("localhost", 10) if err != nil { fmt.Println(err) return } defer c.Close() // session s := c.Ref() defer c.UnRef(s) err = s.DB("test").C("counters").RemoveId("test") if err != nil && err != mgo.ErrNotFound { fmt.Println(err) return } // auto increment err = c.EnsureCounter("test", "counters", "test") if err != nil { fmt.Println(err) return } for i := 0; i < 3; i++ { id, err := c.NextSeq("test", "counters", "test") if err != nil { fmt.Println(err) return } fmt.Println(id) } // index c.EnsureUniqueIndex("test", "counters", []string{"key1"}) // Output: // 1 // 2 // 3}func Find(db string, collection string, docs interface{}) error{ c:=dialContext s := c.Ref() defer c.UnRef(s) type person struct { Id_ bson.ObjectId `bson:"_id"` Name string `bson:"name"` }; user:=new(person); err := s.DB(db).C(collection).Find(docs).One(&user) //idStr:=user.Id_.Hex() //fmt.Println(idStr) if err != nil { fmt.Println(err) return err } return err;}// goroutine safefunc Insert(db string, collection string, docs interface{}) error { c:=dialContext s := c.Ref() defer c.UnRef(s) //// 建立索引 //index := mgo.Index{ // Key: []string{"name"}, // 索引欄位, 預設升序,若需降序在欄位前加- // Unique: true, // 唯一索引 同mysql唯一索引 // DropDups: true, // 索引重複替換舊文檔,Unique為true時失效 // Background: true, // 後台建立索引 //} //if err := s.DB(db).C(collection).EnsureIndex(index); err != nil { // fmt.Println(err) // return err //} //if err := s.DB(db).C(collection).EnsureIndexKey("$2dsphere:location"); err != nil { // 建立一個範圍索引 // fmt.Println(err) // return err //} err := s.DB(db).C(collection).Insert(docs) if err != nil { fmt.Println(err) return err } return err}
Cocos creator用戶端註冊及登陸
簡單的合法性判斷工具類
import messageDialog from './MessageDialog';interface CheckRet{ ret:boolean, msg:string}interface message{ title:string, text:string}export default class Utils { //檢測使用者名稱是否合法 static check_usr(str:string):CheckRet{ let c=<CheckRet>{}; var b :RegExp=/^[a-zA-Z\d]\w{2,10}[a-zA-Z\d]$/; if (b.test(str)) { c.ret = true; c.msg = "用戶名合法"; } else { c.ret = false; c.msg = "用戶名不合法"; } return c; } //判斷密碼輸入是否合法,一個是長度,一個是沒有特殊字元 static check_psw(str:string):CheckRet{ let c=<CheckRet>{}; if(str.length > 5 && str.length<21){ c.ret = true; c.msg = ""; }else { c.ret = false; c.msg = "密碼長度不合規範"; } var b:RegExp =/^[a-zA-Z\d]\w{2,10}[a-zA-Z\d]$/; if (b.test(str)) { c.ret = true; c.msg = ""; }else { c.ret = false; c.msg = "密碼字元不合規範"; } return c; } //判斷手機號碼格式是否合法 static check_tel(str:string):CheckRet{ let c=<CheckRet>{}; var regx=/^(?:13\d|15\d|18[123456789])-?\d{5}(\d{3}|\*{3})$/; if(regx.test(str)){ c.ret = true; c.msg = ""; }else{ c.ret = false; c.msg = "手機號不合規範"; } return c; } //判斷郵箱地址格式是否合法 static check_mail(str:string):CheckRet{ let c=<CheckRet>{}; var regm = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;//驗證Mail的Regex,^[a-zA-Z0-9_-]:開頭必須為字母,底線,數字, if (str.match(regm)){ c.ret = true; c.msg = ""; } else{ c.ret = false; c.msg = "郵箱地址不合規範"; } return c; } static showTips(title:string,text:string){ messageDialog.getInstance().showTips({title:title,text:text}) }}
註冊流程
import NetMessageCtrl from './NetMessageCtrl';import Utils from './Utils';const {ccclass, property} = cc._decorator@ccclassexport default class Register extends cc.Component { @property(cc.EditBox) Name: cc.EditBox = null; @property(cc.EditBox) Pwd: cc.EditBox = null; onLoad(){ } onBtnPanel(){ this.node.parent.active = false } onBtnComfirm(){ var name = this.Name.string; var pwd = this.Pwd.string; if(name && pwd){ let check = Utils.check_usr(name) let checkPwd = Utils.check_psw(name) if(check.ret){ if(checkPwd.ret){ NetMessageCtrl.getInstance().sendRegister(name,pwd); } else{ Utils.showTips("提示",checkPwd.msg) } } else{ Utils.showTips("提示",check.msg) } } else{ Utils.showTips("提示","請輸入完整註冊資料") } }}
處理收到的回信
dealMessage(id: number,data: Uint8Array ){ switch(id){ case netConfig.ProtocolId.Test: this.dealTest(data) break; case netConfig.ProtocolId.UserResult: this.dealUserResult(data) break; default: break; } } //註冊登陸登一系列使用者行為的結果都通過netConfig.ProtocolId.UserResult協議返回 dealUserResult(data: Uint8Array){ console.log("get UserResult message!"); let gameMsg = msg.UserResult.decode(data); console.log(gameMsg); }
Example gihub地址:
server:https://github.com/ddkgo/LeafServerExample.git
client:https://github.com/ddkgo/LeafServerCocosClient.git