xy пре 3 дана
родитељ
комит
4388b76a65

+ 4 - 0
bin/client_msg/common.proto

@@ -210,6 +210,10 @@ message ResMatchLudo {
   MsgError err_msg = 2;
   RoomInfo room = 3;
 }
+//被踢登陆
+message BeKickLogin {
+  MsgError err_msg = 1;
+}
 //error
 message MsgError {
   int32 error_code = 1;

+ 120 - 0
src/server/game/agentManager/agentManager.go

@@ -0,0 +1,120 @@
+package agentmanager
+
+import (
+	"time"
+
+	"github.com/name5566/leaf/gate"
+	"github.com/name5566/leaf/log"
+)
+
+var (
+	// 未认证连接池
+	pendingConns = make(map[gate.Agent]*PendingConn)
+	// 已认证用户
+	authedUsers = make(map[string]gate.Agent) // key: userID
+)
+
+const (
+	ConnStatusUnauth = iota // 未认证
+	ConnStatusAuthed        // 已认证
+)
+
+// 未认证连接管理
+type PendingConn struct {
+	Agent      gate.Agent
+	CreateTime int64
+	Status     int
+}
+
+func NewAgent(args []interface{}) {
+	agent := args[0].(gate.Agent)
+	//将新连接放入未认证池
+	pendingConns[agent] = &PendingConn{
+		Agent:      agent,
+		CreateTime: time.Now().Unix(),
+		Status:     ConnStatusUnauth,
+	}
+	go checkTimeout(agent)
+}
+
+func CloseAgent(args []interface{}) {
+	agent := args[0].(gate.Agent)
+	// 清理未认证连接
+	_, exists := pendingConns[agent]
+	if exists {
+		delete(pendingConns, agent)
+	}
+	// 清理已认证连接
+	for userID, a := range authedUsers {
+		if a == agent {
+			// a.SetUserData(&common.UserData{
+			// 	Id:       userID,
+			// 	Nickname: userID,
+			// 	Status:   0,
+			// })
+			delete(authedUsers, userID)
+			break
+		}
+	}
+}
+
+// 定时检查超时连接
+func checkTimeout(agent gate.Agent) {
+	timeout := 30 * time.Second
+	timer := time.NewTimer(timeout)
+	defer timer.Stop()
+
+	select {
+	case <-timer.C:
+		// 检查是否仍在未认证池中
+		if conn, exists := pendingConns[agent]; exists {
+			if conn.Status == ConnStatusUnauth {
+				// 超时未认证,关闭连接
+				log.Debug("Connection timeout without auth, closing...")
+				agent.Close()
+				delete(pendingConns, agent)
+			}
+		}
+	}
+}
+
+// 是否有账号登陆
+func IsAuthedUsers(userID string, agent gate.Agent) (bool, gate.Agent) {
+	// 处理可能的重复登录
+	if oldAgent, exists := authedUsers[userID]; exists && oldAgent != agent {
+		return true, oldAgent
+	}
+	return false, nil
+}
+
+// 踢出玩家
+func KickAgent(userID string) {
+	// 处理可能的重复登录
+	if oldAgent, exists := authedUsers[userID]; exists {
+		oldAgent.Close()
+		delete(authedUsers, userID)
+	}
+}
+
+// 设置认证状态
+func AgentConnStatusAuthed(agent gate.Agent) {
+	pendingConns[agent].Status = ConnStatusAuthed
+}
+
+// 添加到用户列表
+func AddAuthedUsers(userID string, agent gate.Agent) {
+	authedUsers[userID] = agent
+}
+
+func GetAgentByUserID(userID string) gate.Agent {
+	return authedUsers[userID]
+}
+
+func GetUserIDByAgent(agent gate.Agent) string {
+	for k, v := range authedUsers {
+		if v == agent {
+			return k
+		}
+	}
+	return ""
+}

+ 3 - 109
src/server/game/internal/chanrpc.go

@@ -1,127 +1,21 @@
 package internal
 
 import (
-	redismgr "server/db/redis"
-	"server/msg"
-	"server/user"
-	"time"
+	agentmanager "server/game/agentManager"
 
-	"github.com/name5566/leaf/gate"
 	"github.com/name5566/leaf/log"
 )
 
 func init() {
 	skeleton.RegisterChanRPC("NewAgent", rpcNewAgent)
 	skeleton.RegisterChanRPC("CloseAgent", rpcCloseAgent)
-	skeleton.RegisterChanRPC("handleAuth", handleAuth)
 }
 
 func rpcNewAgent(args []interface{}) {
-	agent := args[0].(gate.Agent)
-	// 将新连接放入未认证池
-	pendingConns[agent] = &PendingConn{
-		Agent:      agent,
-		CreateTime: time.Now().Unix(),
-		Status:     ConnStatusUnauth,
-	}
-	// go checkTimeout(agent)
+	agentmanager.NewAgent(args)
 }
 
 func rpcCloseAgent(args []interface{}) {
 	log.Debug("rpcCloseAgent")
-
-	agent := args[0].(gate.Agent)
-	// 清理未认证连接
-	_, exists := pendingConns[agent]
-	if exists {
-		delete(pendingConns, agent)
-	}
-	// 清理已认证连接
-	for userID, a := range authedUsers {
-		if a == agent {
-			// a.SetUserData(&common.UserData{
-			// 	Id:       userID,
-			// 	Nickname: userID,
-			// 	Status:   0,
-			// })
-			delete(authedUsers, userID)
-			break
-		}
-	}
-}
-
-// 处理认证消息
-func handleAuth(args []interface{}) {
-	// 收到的登录消息
-	m := args[0].(*msg.ReqLogin)
-	// 消息的发送者
-	a := args[1].(gate.Agent)
-
-	log.Debug("handleAuth: nikeName=%v, userId=%v", m.Password, m.Account)
-	UserId, err := redismgr.GetUserIDFromRedisByAP(m.Account, m.Password)
-	if err != nil {
-		a.WriteMsg(&msg.ResLogin{
-			NikeName: "",
-			UserId:   "",
-			ErrMsg: &msg.MsgError{
-				ErrorCode: 101,
-				ErrorMsg:  "Password or Account is error!",
-			},
-		})
-		return
-	}
-	// 找到未认证连接
-	if pending, exists := pendingConns[a]; exists {
-		// 认证成功,移动到已认证池
-		delete(pendingConns, a)
-		authedUsers[UserId] = a
-		pending.Status = ConnStatusAuthed
-
-		// 处理可能的重复登录
-		if oldAgent, exists := authedUsers[UserId]; exists && oldAgent != a {
-			oldAgent.Close()
-			delete(authedUsers, UserId)
-		}
-		// 获取用户信息 ,如果新用户则创建一个
-		userData := user.GetUserInfoById(UserId)
-		a.SetUserData(&msg.UserInfo{
-			UserId: userData.UserId,
-			MHead:  userData.MHead,
-			MCoin:  userData.MCoin,
-			Name:   userData.Name,
-			RoomId: userData.RoomId,
-		})
-
-		// 发送登录成功响应
-		a.WriteMsg(&msg.ResLogin{
-			UserInfo: &msg.UserInfo{
-				UserId: userData.UserId,
-				MHead:  userData.MHead,
-				MCoin:  userData.MCoin,
-				Name:   userData.Name,
-				RoomId: userData.RoomId,
-			},
-			ErrMsg: nil,
-		})
-	}
-}
-
-// 定时检查超时连接
-func checkTimeout(agent gate.Agent) {
-	timeout := 30 * time.Second
-	timer := time.NewTimer(timeout)
-	defer timer.Stop()
-
-	select {
-	case <-timer.C:
-		// 检查是否仍在未认证池中
-		if conn, exists := pendingConns[agent]; exists {
-			if conn.Status == ConnStatusUnauth {
-				// 超时未认证,关闭连接
-				log.Debug("Connection timeout without auth, closing...")
-				agent.Close()
-				delete(pendingConns, agent)
-			}
-		}
-	}
+	agentmanager.CloseAgent(args)
 }

+ 0 - 33
src/server/game/internal/module.go

@@ -3,29 +3,9 @@ package internal
 import (
 	"server/base"
 
-	"github.com/name5566/leaf/gate"
 	"github.com/name5566/leaf/module"
 )
 
-const (
-	ConnStatusUnauth = iota // 未认证
-	ConnStatusAuthed        // 已认证
-)
-
-// 未认证连接管理
-type PendingConn struct {
-	Agent      gate.Agent
-	CreateTime int64
-	Status     int
-}
-
-var (
-	// 未认证连接池
-	pendingConns = make(map[gate.Agent]*PendingConn)
-	// 已认证用户
-	authedUsers = make(map[string]gate.Agent) // key: userID
-)
-
 var (
 	skeleton = base.NewSkeleton()
 	ChanRPC  = skeleton.ChanRPCServer
@@ -42,16 +22,3 @@ func (m *Module) OnInit() {
 func (m *Module) OnDestroy() {
 
 }
-
-func GetAgentByUserID(userID string) gate.Agent {
-	return authedUsers[userID]
-}
-
-func GetUserIDByAgent(agent gate.Agent) string {
-	for k, v := range authedUsers {
-		if v == agent {
-			return k
-		}
-	}
-	return ""
-}

+ 2 - 2
src/server/game/ludo/battle.go

@@ -205,7 +205,7 @@ func (room_info *RoomInfoWrapper) time_out_tuo_guan() {
 		if room_info.IsOverGame() { //宣布游戏结束
 			room_info.notify_settlement()
 		} else {
-			room_info.tick_color_of_room(cur_color)
+			room_info.kick_color_of_room(cur_color)
 		}
 	} else {
 		room_info.tuo_guan_opt()
@@ -268,7 +268,7 @@ func (room_info *RoomInfoWrapper) notify_update_room_info() {
 }
 
 // 将玩家从房间踢出
-func (room_info *RoomInfoWrapper) tick_color_of_room(color msg.RoleType) {
+func (room_info *RoomInfoWrapper) kick_color_of_room(color msg.RoleType) {
 	message := &msg.NotifyPlayerStatus{
 		Color:  color,
 		Status: msg.PlayerStatus_COLOR_KICK,

+ 1 - 1
src/server/game/ludo/color_send.go

@@ -28,7 +28,7 @@ func (room_info *RoomInfoWrapper) send_role_move(color msg.RoleType, role_id str
 			enemys := room_info.getRolesByColorRoles(color, des_road_roles)
 			if len(enemys) > 0 { //说明目标路上有其他敌人
 				//将所有敌人踢回阵营,然后再加一轮筛子操作
-				room_info.tickRolesBackHome(enemys)
+				room_info.kickRolesBackHome(enemys)
 				message.Kick = enemys
 			}
 		}

+ 2 - 2
src/server/game/ludo/ludo.go

@@ -1,7 +1,7 @@
 package ludo
 
 import (
-	"server/game/internal"
+	agentmanager "server/game/agentManager"
 	"server/msg"
 	"server/tools"
 	"sync"
@@ -104,7 +104,7 @@ func startGame(room_info *msg.RoomInfo) *RoomInfoWrapper {
 }
 
 func getAgentByUserId(userId string) gate.Agent {
-	ag := internal.GetAgentByUserID(userId)
+	ag := agentmanager.GetAgentByUserID(userId)
 	if ag == nil {
 		log.Error("agent is nil userId = %s ", userId)
 		return nil

+ 2 - 2
src/server/game/ludo/ludo_room_data.go

@@ -202,7 +202,7 @@ func (room_info *RoomInfoWrapper) getRolesByColorRoles(color msg.RoleType, roles
 }
 
 // 将一批角色踢回家
-func (room_info *RoomInfoWrapper) tickRolesBackHome(roles []*msg.RoleData) {
+func (room_info *RoomInfoWrapper) kickRolesBackHome(roles []*msg.RoleData) {
 	for i := range roles {
 		role_data := roles[i]
 		role_data.Step = 0
@@ -304,7 +304,7 @@ func (room_info *RoomInfoWrapper) setCurColorOpt(opt *msg.NotifyPlayerOpt) {
 }
 
 // 将玩家踢出房间
-func (room_info *RoomInfoWrapper) tickColor(color msg.RoleType) {
+func (room_info *RoomInfoWrapper) kickColor(color msg.RoleType) {
 	color_data := room_info.getColorDataByColor(color)
 	color_data.IsKick = true
 }

+ 27 - 1
src/server/go.mod

@@ -6,14 +6,40 @@ require (
 	github.com/go-sql-driver/mysql v1.8.1
 	github.com/gomodule/redigo v2.0.0+incompatible
 	github.com/name5566/leaf v0.0.0-20221021105039-af71eb082cda
-	google.golang.org/protobuf v1.36.2
+	google.golang.org/protobuf v1.36.6
 	gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
 )
 
 require (
 	filippo.io/edwards25519 v1.1.0 // indirect
+	github.com/bytedance/sonic v1.13.3 // indirect
+	github.com/bytedance/sonic/loader v0.2.4 // indirect
+	github.com/cloudwego/base64x v0.1.5 // indirect
+	github.com/cloudwego/iasm v0.2.0 // indirect
+	github.com/gabriel-vasile/mimetype v1.4.9 // indirect
+	github.com/gin-contrib/sse v1.1.0 // indirect
+	github.com/gin-gonic/gin v1.10.1 // indirect
+	github.com/go-playground/locales v0.14.1 // indirect
+	github.com/go-playground/universal-translator v0.18.1 // indirect
+	github.com/go-playground/validator/v10 v10.26.0 // indirect
+	github.com/goccy/go-json v0.10.5 // indirect
 	github.com/golang/protobuf v1.5.4 // indirect
 	github.com/gorilla/websocket v1.5.3 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
+	github.com/klauspost/cpuid/v2 v2.2.10 // indirect
+	github.com/leodido/go-urn v1.4.0 // indirect
+	github.com/mattn/go-isatty v0.0.20 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/pelletier/go-toml/v2 v2.2.4 // indirect
+	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
+	github.com/ugorji/go/codec v1.2.14 // indirect
+	golang.org/x/arch v0.17.0 // indirect
+	golang.org/x/crypto v0.38.0 // indirect
+	golang.org/x/net v0.40.0 // indirect
+	golang.org/x/sys v0.33.0 // indirect
+	golang.org/x/text v0.25.0 // indirect
 	gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
 )

+ 74 - 0
src/server/go.sum

@@ -1,26 +1,95 @@
 filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
 filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
+github.com/bytedance/sonic v1.13.3 h1:MS8gmaH16Gtirygw7jV91pDCN33NyMrPbN7qiYhEsF0=
+github.com/bytedance/sonic v1.13.3/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
+github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
+github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
+github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
+github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
+github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
+github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
+github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
+github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
+github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
+github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
+github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
+github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
+github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
+github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
+github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
+github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
 github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
 github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
+github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
+github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
 github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
 github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
 github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
 github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
 github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
 github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
+github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
+github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
 github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
 github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
+github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 github.com/name5566/leaf v0.0.0-20221021105039-af71eb082cda h1:5S+9luohX8Whu/4VreRe4E0bHSSuJ4hyIGJc1nvNQzQ=
 github.com/name5566/leaf v0.0.0-20221021105039-af71eb082cda/go.mod h1:JrOIxq3vDxvtuEI7Kmm2yqkuBfuT9DMLFMnCyYHLaKM=
+github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
+github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
+github.com/ugorji/go/codec v1.2.14 h1:yOQvXCBc3Ij46LRkRoh4Yd5qK6LVOgi0bYOXfb7ifjw=
+github.com/ugorji/go/codec v1.2.14/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+golang.org/x/arch v0.17.0 h1:4O3dfLzd+lQewptAHqjewQZQDyEdejz3VwgeYwkZneU=
+golang.org/x/arch v0.17.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
+golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
+golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
+golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
+golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
+golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
+golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU=
 google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
+google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -28,3 +97,8 @@ gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3
 gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

+ 29 - 9
src/server/hall/internal/handler.go

@@ -3,6 +3,8 @@ package internal
 import (
 	"reflect"
 	redismgr "server/db/redis"
+
+	agentmanager "server/game/agentManager"
 	"server/game/ludo"
 	"server/msg"
 
@@ -23,8 +25,8 @@ func init() {
 func enterHall(args []interface{}) {
 	m := args[0].(*msg.EnterHall)
 	a := args[1].(gate.Agent)
-
-	_, err_info := redismgr.GetUserInfoFromRedis(m.UserId)
+	agentmanager.AgentConnStatusAuthed(a)
+	user_info, err_info := redismgr.GetUserInfoFromRedis(m.UserId)
 	if err_info != nil {
 		a.WriteMsg(&msg.ResEnterHall{
 			Success: false,
@@ -35,8 +37,26 @@ func enterHall(args []interface{}) {
 		})
 		return
 	}
-	ud := a.UserData()
-	room_id := ud.(*msg.UserInfo).RoomId
+	//如果玩家其他玩家登陆了账号
+	if isLogin, otherAgent := agentmanager.IsAuthedUsers(m.UserId, a); isLogin && otherAgent != nil {
+		otherAgent.WriteMsg(&msg.BeKickLogin{
+			ErrMsg: &msg.MsgError{
+				//你的账号被其他人登陆
+				ErrorMsg:  "Your account has been logged in by someone else",
+				ErrorCode: 101,
+			},
+		})
+		agentmanager.KickAgent(m.UserId)
+	}
+	agentmanager.AddAuthedUsers(m.UserId, a)
+	a.SetUserData(&msg.UserInfo{
+		UserId: user_info.UserId,
+		MHead:  user_info.MHead,
+		MCoin:  user_info.MCoin,
+		Name:   user_info.Name,
+		RoomId: user_info.RoomId,
+	})
+	room_id := user_info.RoomId
 	var user_room *msg.RoomInfo = nil
 	//如果玩家在某个游戏里,就进行重连
 	if room_id != 0 {
@@ -47,11 +67,11 @@ func enterHall(args []interface{}) {
 			user_room = wrapper.RoomInfo
 		} else {
 			redismgr.SaveUserInfoToRedis(&msg.UserInfo{
-				UserId: ud.(*msg.UserInfo).UserId,
-				Name:   ud.(*msg.UserInfo).Name,
-				MCoin:  ud.(*msg.UserInfo).MCoin,
-				MHead:  ud.(*msg.UserInfo).MHead,
-				RoomId: ud.(*msg.UserInfo).RoomId,
+				UserId: user_info.UserId,
+				Name:   user_info.Name,
+				MCoin:  user_info.MCoin,
+				MHead:  user_info.MHead,
+				RoomId: user_info.RoomId,
 			})
 		}
 		//进行重连逻辑

+ 74 - 25
src/server/msg/common.pb.go

@@ -1875,6 +1875,51 @@ func (x *ResMatchLudo) GetRoom() *RoomInfo {
 	return nil
 }
 
+// 被踢登陆
+type BeKickLogin struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	ErrMsg        *MsgError              `protobuf:"bytes,1,opt,name=err_msg,json=errMsg,proto3" json:"err_msg,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *BeKickLogin) Reset() {
+	*x = BeKickLogin{}
+	mi := &file_common_proto_msgTypes[23]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *BeKickLogin) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*BeKickLogin) ProtoMessage() {}
+
+func (x *BeKickLogin) ProtoReflect() protoreflect.Message {
+	mi := &file_common_proto_msgTypes[23]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use BeKickLogin.ProtoReflect.Descriptor instead.
+func (*BeKickLogin) Descriptor() ([]byte, []int) {
+	return file_common_proto_rawDescGZIP(), []int{23}
+}
+
+func (x *BeKickLogin) GetErrMsg() *MsgError {
+	if x != nil {
+		return x.ErrMsg
+	}
+	return nil
+}
+
 // error
 type MsgError struct {
 	state         protoimpl.MessageState `protogen:"open.v1"`
@@ -1886,7 +1931,7 @@ type MsgError struct {
 
 func (x *MsgError) Reset() {
 	*x = MsgError{}
-	mi := &file_common_proto_msgTypes[23]
+	mi := &file_common_proto_msgTypes[24]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -1898,7 +1943,7 @@ func (x *MsgError) String() string {
 func (*MsgError) ProtoMessage() {}
 
 func (x *MsgError) ProtoReflect() protoreflect.Message {
-	mi := &file_common_proto_msgTypes[23]
+	mi := &file_common_proto_msgTypes[24]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1911,7 +1956,7 @@ func (x *MsgError) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use MsgError.ProtoReflect.Descriptor instead.
 func (*MsgError) Descriptor() ([]byte, []int) {
-	return file_common_proto_rawDescGZIP(), []int{23}
+	return file_common_proto_rawDescGZIP(), []int{24}
 }
 
 func (x *MsgError) GetErrorCode() int32 {
@@ -1937,7 +1982,7 @@ type ResHeartBeat struct {
 
 func (x *ResHeartBeat) Reset() {
 	*x = ResHeartBeat{}
-	mi := &file_common_proto_msgTypes[24]
+	mi := &file_common_proto_msgTypes[25]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -1949,7 +1994,7 @@ func (x *ResHeartBeat) String() string {
 func (*ResHeartBeat) ProtoMessage() {}
 
 func (x *ResHeartBeat) ProtoReflect() protoreflect.Message {
-	mi := &file_common_proto_msgTypes[24]
+	mi := &file_common_proto_msgTypes[25]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1962,7 +2007,7 @@ func (x *ResHeartBeat) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ResHeartBeat.ProtoReflect.Descriptor instead.
 func (*ResHeartBeat) Descriptor() ([]byte, []int) {
-	return file_common_proto_rawDescGZIP(), []int{24}
+	return file_common_proto_rawDescGZIP(), []int{25}
 }
 
 func (x *ResHeartBeat) GetMsg() string {
@@ -1981,7 +2026,7 @@ type ReqHeartBeat struct {
 
 func (x *ReqHeartBeat) Reset() {
 	*x = ReqHeartBeat{}
-	mi := &file_common_proto_msgTypes[25]
+	mi := &file_common_proto_msgTypes[26]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -1993,7 +2038,7 @@ func (x *ReqHeartBeat) String() string {
 func (*ReqHeartBeat) ProtoMessage() {}
 
 func (x *ReqHeartBeat) ProtoReflect() protoreflect.Message {
-	mi := &file_common_proto_msgTypes[25]
+	mi := &file_common_proto_msgTypes[26]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -2006,7 +2051,7 @@ func (x *ReqHeartBeat) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ReqHeartBeat.ProtoReflect.Descriptor instead.
 func (*ReqHeartBeat) Descriptor() ([]byte, []int) {
-	return file_common_proto_rawDescGZIP(), []int{25}
+	return file_common_proto_rawDescGZIP(), []int{26}
 }
 
 func (x *ReqHeartBeat) GetMsg() string {
@@ -2139,7 +2184,9 @@ const file_common_proto_rawDesc = "" +
 	"\fResMatchLudo\x12\x18\n" +
 	"\asuccess\x18\x01 \x01(\bR\asuccess\x12\"\n" +
 	"\aerr_msg\x18\x02 \x01(\v2\t.MsgErrorR\x06errMsg\x12\x1d\n" +
-	"\x04room\x18\x03 \x01(\v2\t.RoomInfoR\x04room\"F\n" +
+	"\x04room\x18\x03 \x01(\v2\t.RoomInfoR\x04room\"1\n" +
+	"\vBeKickLogin\x12\"\n" +
+	"\aerr_msg\x18\x01 \x01(\v2\t.MsgErrorR\x06errMsg\"F\n" +
 	"\bMsgError\x12\x1d\n" +
 	"\n" +
 	"error_code\x18\x01 \x01(\x05R\terrorCode\x12\x1b\n" +
@@ -2198,7 +2245,7 @@ func file_common_proto_rawDescGZIP() []byte {
 }
 
 var file_common_proto_enumTypes = make([]protoimpl.EnumInfo, 7)
-var file_common_proto_msgTypes = make([]protoimpl.MessageInfo, 26)
+var file_common_proto_msgTypes = make([]protoimpl.MessageInfo, 27)
 var file_common_proto_goTypes = []any{
 	(RoleType)(0),                // 0: roleType
 	(OptType)(0),                 // 1: OptType
@@ -2230,9 +2277,10 @@ var file_common_proto_goTypes = []any{
 	(*LeaveHall)(nil),            // 27: LeaveHall
 	(*MatchLudo)(nil),            // 28: MatchLudo
 	(*ResMatchLudo)(nil),         // 29: ResMatchLudo
-	(*MsgError)(nil),             // 30: MsgError
-	(*ResHeartBeat)(nil),         // 31: ResHeartBeat
-	(*ReqHeartBeat)(nil),         // 32: ReqHeartBeat
+	(*BeKickLogin)(nil),          // 30: BeKickLogin
+	(*MsgError)(nil),             // 31: MsgError
+	(*ResHeartBeat)(nil),         // 32: ResHeartBeat
+	(*ReqHeartBeat)(nil),         // 33: ReqHeartBeat
 }
 var file_common_proto_depIdxs = []int32{
 	0,  // 0: round.m_color:type_name -> roleType
@@ -2253,7 +2301,7 @@ var file_common_proto_depIdxs = []int32{
 	0,  // 15: SendColorSz.color:type_name -> roleType
 	0,  // 16: SendRoleMove.color:type_name -> roleType
 	0,  // 17: NotifyPlayerSzNumber.color:type_name -> roleType
-	30, // 18: NotifyPlayerSzNumber.err_msg:type_name -> MsgError
+	31, // 18: NotifyPlayerSzNumber.err_msg:type_name -> MsgError
 	0,  // 19: NotifyPlayerMove.color:type_name -> roleType
 	11, // 20: NotifyPlayerMove.step:type_name -> MoveStepData
 	9,  // 21: NotifyPlayerMove.kick:type_name -> RoleData
@@ -2268,19 +2316,20 @@ var file_common_proto_depIdxs = []int32{
 	10, // 30: NotifySettlement.finish_colors:type_name -> ColorData
 	8,  // 31: NotifyUpdateRoomInfo.room_info:type_name -> RoomInfo
 	20, // 32: ResLogin.userInfo:type_name -> UserInfo
-	30, // 33: ResLogin.err_msg:type_name -> MsgError
-	30, // 34: ResRegister.err_msg:type_name -> MsgError
-	30, // 35: ResEnterHall.err_msg:type_name -> MsgError
+	31, // 33: ResLogin.err_msg:type_name -> MsgError
+	31, // 34: ResRegister.err_msg:type_name -> MsgError
+	31, // 35: ResEnterHall.err_msg:type_name -> MsgError
 	8,  // 36: ResEnterHall.reconnect_room_info:type_name -> RoomInfo
 	2,  // 37: MatchLudo.select_room_type:type_name -> roomType
 	0,  // 38: MatchLudo.select_color:type_name -> roleType
-	30, // 39: ResMatchLudo.err_msg:type_name -> MsgError
+	31, // 39: ResMatchLudo.err_msg:type_name -> MsgError
 	8,  // 40: ResMatchLudo.room:type_name -> RoomInfo
-	41, // [41:41] is the sub-list for method output_type
-	41, // [41:41] is the sub-list for method input_type
-	41, // [41:41] is the sub-list for extension type_name
-	41, // [41:41] is the sub-list for extension extendee
-	0,  // [0:41] is the sub-list for field type_name
+	31, // 41: BeKickLogin.err_msg:type_name -> MsgError
+	42, // [42:42] is the sub-list for method output_type
+	42, // [42:42] is the sub-list for method input_type
+	42, // [42:42] is the sub-list for extension type_name
+	42, // [42:42] is the sub-list for extension extendee
+	0,  // [0:42] is the sub-list for field type_name
 }
 
 func init() { file_common_proto_init() }
@@ -2294,7 +2343,7 @@ func file_common_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: unsafe.Slice(unsafe.StringData(file_common_proto_rawDesc), len(file_common_proto_rawDesc)),
 			NumEnums:      7,
-			NumMessages:   26,
+			NumMessages:   27,
 			NumExtensions: 0,
 			NumServices:   0,
 		},

+ 1 - 1
src/server/msg/msg.go

@@ -40,7 +40,7 @@ func init() {
 	Processor.Register(&MatchLudo{})
 	Processor.Register(&ResMatchLudo{})
 	Processor.Register(&NotifyUpdateRoomInfo{})
-
+	Processor.Register(&BeKickLogin{})
 	Processor.Range(func(id uint16, t reflect.Type) {
 		log.Debug("消息ID: %d, 消息类型: %s\n", id, t.Elem().Name())
 		msgList = append(msgList, MsgInfo{

+ 119 - 0
src/server/webserver/main.go

@@ -0,0 +1,119 @@
+package main
+
+import (
+	"net/http"
+	redismgr "server/db/redis"
+	"server/msg"
+	"server/user"
+
+	"github.com/gin-gonic/gin"
+	"github.com/gin-gonic/gin/binding"
+	"github.com/name5566/leaf/log"
+)
+
+func ParseProtoBuf(c *gin.Context) {
+	var req msg.ReqLogin
+	if err := c.ShouldBindBodyWith(&req, binding.ProtoBuf); err != nil {
+		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
+			"error":   "Invalid protobuf data",
+			"details": err.Error(),
+		})
+		return
+	}
+	c.Set("protobuf_data", &req)
+	c.Next()
+}
+
+func main() {
+	r := gin.Default()
+
+	// r.GET("/", func(c *gin.Context) {
+	// 	c.String(200, "Hello, Gin!")
+	// })
+
+	// r.GET("/json", func(c *gin.Context) {
+	// 	c.JSON(200, gin.H{"message": "Hello, JSON!"})
+	// })
+
+	// r.GET("/test", func(c *gin.Context) {
+	// 	c.Redirect(http.StatusMovedPermanently, "http://www.google.com/")
+	// })
+
+	r.POST("/ReqLogin", ParseProtoBuf, ReqLogin)
+	r.POST("/ReqRegister", ParseProtoBuf, ReqRegister)
+	r.Run(":8080") // 默认监听 :8080
+}
+
+func ReqRegister(c *gin.Context) {
+	req := c.MustGet("protobuf_data").(*msg.ReqRegister)
+
+	log.Debug(req.Account, req.Password)
+
+	userId, _ := redismgr.GetUserIDFromRedisByAP(req.Account, req.Password)
+
+	if userId != "" {
+		c.ProtoBuf(http.StatusOK, &msg.ResRegister{
+			Success: false,
+			ErrMsg: &msg.MsgError{
+				ErrorCode: 101,
+				ErrorMsg:  " Account is exist!",
+			},
+		})
+		return
+	}
+
+	userId, Success := redismgr.SetUserIDFromRedisByAP(req.Account, req.Password)
+	if !Success {
+		c.ProtoBuf(http.StatusOK, &msg.ResRegister{
+			Success: false,
+			ErrMsg: &msg.MsgError{
+				ErrorCode: 102,
+				ErrorMsg:  "server registerHandler error",
+			},
+		})
+		return
+	}
+
+	redismgr.SaveUserInfoToRedis(&msg.UserInfo{
+		UserId: userId,
+		MCoin:  0,
+		MHead:  req.MHead,
+		Name:   req.NikeName,
+	})
+	c.ProtoBuf(http.StatusOK, &msg.ResRegister{
+		Success: true,
+		ErrMsg:  nil,
+	})
+}
+
+func ReqLogin(c *gin.Context) {
+	req := c.MustGet("protobuf_data").(*msg.ReqLogin)
+	// 返回 protobuf 响应
+	c.ProtoBuf(http.StatusOK, req)
+
+	UserId, err := redismgr.GetUserIDFromRedisByAP(req.Account, req.Password)
+	if err != nil {
+
+		c.ProtoBuf(http.StatusOK, &msg.ResLogin{
+			NikeName: "",
+			UserId:   "",
+			ErrMsg: &msg.MsgError{
+				ErrorCode: 101,
+				ErrorMsg:  "Password or Account is error!",
+			},
+		})
+		return
+	}
+	// 获取用户信息 ,如果新用户则创建一个
+	userData := user.GetUserInfoById(UserId)
+	c.ProtoBuf(http.StatusOK, &msg.ResLogin{
+		UserInfo: &msg.UserInfo{
+			UserId: userData.UserId,
+			MHead:  userData.MHead,
+			MCoin:  userData.MCoin,
+			Name:   userData.Name,
+			RoomId: userData.RoomId,
+		},
+		ErrMsg: nil,
+	})
+}