actor_agent.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. package user
  2. import (
  3. actorRemote "f1-game/internal/actor_remote"
  4. "f1-game/internal/code"
  5. "f1-game/internal/constant"
  6. "f1-game/internal/data"
  7. "f1-game/internal/extend/token"
  8. nameActor "f1-game/internal/name/actor"
  9. nameLocal "f1-game/internal/name/local"
  10. nameRemote "f1-game/internal/name/remote"
  11. "f1-game/internal/pb"
  12. "f1-game/internal/sessions"
  13. "f1-game/nodes/gate/cache"
  14. cstring "github.com/cherry-game/cherry/extend/string"
  15. cfacade "github.com/cherry-game/cherry/facade"
  16. clog "github.com/cherry-game/cherry/logger"
  17. "github.com/cherry-game/cherry/net/parser/pomelo"
  18. cproto "github.com/cherry-game/cherry/net/proto"
  19. cprofile "github.com/cherry-game/cherry/profile"
  20. "go.uber.org/zap/zapcore"
  21. )
  22. type (
  23. actorAgent struct {
  24. pomelo.ActorBase
  25. agent *pomelo.Agent
  26. }
  27. )
  28. func newChildAgent(agent *pomelo.Agent) *actorAgent {
  29. return &actorAgent{
  30. agent: agent,
  31. }
  32. }
  33. func (p *actorAgent) AliasID() string {
  34. return p.agent.SID()
  35. }
  36. func (p *actorAgent) OnInit() {
  37. p.agent.AddOnClose(p.OnSessionClose)
  38. p.Local().Register(nameLocal.User_Login, p.login)
  39. p.Remote().Register(nameRemote.User_SetSession, p.setSession)
  40. }
  41. func (p *actorAgent) login(session *cproto.Session, req *pb.UserLoginRequest) {
  42. if p.agent == nil {
  43. p.ResponseCode(session, code.AccountLoginBindUserError)
  44. return
  45. }
  46. // debug模式是前端选服,验证gameNodeID 是否传值
  47. if cprofile.Debug() {
  48. if req.GameNodeID == "" {
  49. p.ResponseCode(session, code.NodeGameNodeIDIsEmpty)
  50. return
  51. }
  52. }
  53. // 验证token
  54. userToken, errCode := p.validateToken(req.Token)
  55. if code.IsFail(errCode) {
  56. p.ResponseCode(session, errCode)
  57. return
  58. }
  59. // 验证pid 是否配置
  60. sdkRow := data.SDK.Get(userToken.PID)
  61. if sdkRow == nil {
  62. p.ResponseCode(session, code.AccountLoginPIDError)
  63. return
  64. }
  65. // 根据pid openid获取uid
  66. uid, errCode := actorRemote.CenterPlayer.GetUID(sdkRow.SdkID, userToken.PID, userToken.OpenID)
  67. if uid < 1 || code.IsFail(errCode) {
  68. p.ResponseCode(session, errCode)
  69. return
  70. }
  71. // 检查game节点是否可以进入
  72. errCode = checkNodeState(constant.NodeGame, req.GameNodeID, nameActor.GameOps, uid, session.Ip)
  73. if code.IsFail(errCode) {
  74. p.ResponseCode(session, errCode)
  75. return
  76. }
  77. // uid和session绑定
  78. oldAgent, err := pomelo.Bind(session.Sid, uid)
  79. if err != nil {
  80. clog.Warn(err)
  81. p.ResponseCode(session, code.AccountLoginBindUserError)
  82. return
  83. }
  84. // 踢掉旧的agent
  85. if oldAgent != nil {
  86. oldAgent.Kick(upa.duplicateLoginCode, true)
  87. }
  88. p.kickGateSession(uid)
  89. // 在agent存储当前player相关的信息,用于路由、日志记录等
  90. p.agent.Session().Set(sessions.GameNodeID, cstring.ToString(req.GameNodeID))
  91. p.agent.Session().Set(sessions.PID, cstring.ToString(userToken.PID))
  92. p.agent.Session().Set(sessions.OpenID, userToken.OpenID)
  93. response := &pb.UserLoginResponse{
  94. Uid: uid,
  95. Pid: userToken.PID,
  96. OpenID: userToken.OpenID,
  97. GameNodeID: req.GameNodeID,
  98. Params: req.GetParams(), // TODO 后续可以针对 pid读取一些参数返回给客户端
  99. }
  100. if clog.Enable(zapcore.DebugLevel) {
  101. clog.Debugf("user login. gameNodeID = %s, pid = %d, open_id = %s, response = %v",
  102. req.GameNodeID,
  103. userToken.PID,
  104. userToken.OpenID,
  105. response,
  106. )
  107. }
  108. p.Response(session, response)
  109. }
  110. func (p *actorAgent) setSession(req *pb.StrStrList) {
  111. if p.agent == nil {
  112. clog.Warnf("agent is nil. sid = %s", p.AliasID())
  113. return
  114. }
  115. for _, param := range req.List {
  116. if cstring.IsBlank(param.Value) {
  117. p.agent.Session().Remove(param.Key)
  118. } else {
  119. p.agent.Session().Set(param.Key, param.Value)
  120. }
  121. }
  122. // 更新agnet缓存
  123. cache.UpdateAgent(p.agent)
  124. // 推送session到目标节点
  125. for _, param := range req.List {
  126. if parserFunc, found := upa.GetSyncParser(param.Key); found {
  127. parserFunc(p, p.agent.Session(), true)
  128. }
  129. }
  130. }
  131. func (p *actorAgent) validateToken(base64Token string) (*token.Token, int32) {
  132. userToken, ok := token.DecodeToken(base64Token)
  133. if !ok || userToken.PID < 1 || len(userToken.OpenID) < 1 {
  134. clog.Warnf("base64Token = %s", base64Token)
  135. return nil, code.AccountUnmarshalError
  136. }
  137. sdkRow := data.SDK.Get(userToken.PID)
  138. if sdkRow == nil {
  139. return nil, code.PIDError
  140. }
  141. statusCode, ok := token.Validate(userToken, sdkRow.Salt)
  142. if !ok {
  143. return nil, statusCode
  144. }
  145. return userToken, code.OK
  146. }
  147. func (p *actorAgent) kickGateSession(uid cfacade.UID) {
  148. // 遍历所有网关节点,踢除旧的session
  149. uids := []int64{uid}
  150. sessions.KickUIDS(uids, upa.duplicateLoginCode, true, p.App().NodeID())
  151. }
  152. func (p *actorAgent) OnSessionClose(_ *pomelo.Agent) {
  153. cache.RemoveAgent(p.agent)
  154. // 推送session到目标节点
  155. for _, parserFunc := range upa.nodeSyncMap {
  156. parserFunc(p, p.agent.Session(), false)
  157. }
  158. // 释放agenet
  159. p.agent = nil
  160. // 自己退出
  161. p.Exit()
  162. }
  163. func (p *actorAgent) GetPlayerID() int64 {
  164. return sessions.GetPlayerID(p.agent.Session())
  165. }
  166. func (p *actorAgent) GetGameNodeID() string {
  167. return sessions.GetGameNodeID(p.agent.Session())
  168. }
  169. func (p *actorAgent) GetMapNodeID() string {
  170. return sessions.GetMapNodeID(p.agent.Session())
  171. }