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.proto
pbts -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 mongodbmgr
import (
"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 safe
func 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的正则表达式,^[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
@ccclass
export 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