client_login_logic.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package logic
  2. import (
  3. "call_center/call/rpc/internal/core"
  4. "call_center/call/rpc/pb"
  5. db "call_center/db/rpc/pb"
  6. "call_center/public/exception"
  7. "context"
  8. "log"
  9. "time"
  10. "call_center/call/rpc/internal/svc"
  11. "github.com/tal-tech/go-zero/core/logx"
  12. )
  13. type ClientLoginLogic struct {
  14. ctx context.Context
  15. svcCtx *svc.ServiceContext
  16. logx.Logger
  17. }
  18. func NewClientLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ClientLoginLogic {
  19. return &ClientLoginLogic{
  20. ctx: ctx,
  21. svcCtx: svcCtx,
  22. Logger: logx.WithContext(ctx),
  23. }
  24. }
  25. func (l *ClientLoginLogic) ClientLogin(req *pb.ClientMsgReq, stream pb.Call_ClientLoginServer) error {
  26. server := core.GetServer()
  27. idInfo := req.IdInfo
  28. if idInfo == nil {
  29. // 传参失效
  30. errStr := "<ClientLogin> req.IdInfo is nil"
  31. return exception.MakeError(int32(pb.EErrorCode_ERR_PARAM_ERROR), errStr)
  32. }
  33. if idInfo.Id != "" {
  34. // 重登
  35. p := server.GetPlayer(idInfo.Id)
  36. if p != nil {
  37. // 当前已连接,断开当前链接
  38. server.KickPlayer(idInfo.Id, int32(pb.ErrorReason_PLAYER_REPEAT_LOGIN))
  39. log.Println("<ClientLogin> player already conn, disconnect first, id:", idInfo.Id)
  40. }
  41. }
  42. // 客服stream注册
  43. player, err := server.OnPlayerConnect(server, stream)
  44. if player == nil {
  45. log.Println("<ClientLogin> OnPlayerConnect failed, err:", err)
  46. //return err
  47. return exception.MakeError(int32(pb.EErrorCode_ERR_PLAYER_CONN_ERR), err.Error())
  48. }
  49. // 初始化玩家信息
  50. stopChan := make(chan int32)
  51. player.Init(idInfo.GameId, true, stopChan)
  52. // 加入等待队列
  53. server.OnPlayerEnterWaitQueue(server, player)
  54. // 心跳ticker
  55. duration := time.Second * time.Duration(server.HeartBeatInterval)
  56. ticker := time.NewTicker(duration)
  57. var errCode pb.ErrorReason
  58. exception.Try(func() {
  59. defer func() {
  60. ticker.Stop()
  61. }()
  62. for {
  63. select {
  64. case <-stream.Context().Done():
  65. log.Println("<ClientLogin> heartbeat failed, id:", player.Id, " err:", stream.Context().Err())
  66. errCode = pb.ErrorReason_PLAYER_HEART_BEAT_FAILED
  67. return
  68. case <-ticker.C:
  69. // 超时未发言
  70. now := time.Now().Unix()
  71. lastTalkTimeStamp := player.LastTalkTimeStamp
  72. if now-lastTalkTimeStamp >= server.LastTalkIntervalLimit {
  73. log.Println("<ClientLogin> last talk interval limit, id:", player.Id)
  74. errCode = pb.ErrorReason_PLAYER_TALK_INTERVAL_LIMIT
  75. return
  76. }
  77. case stop := <-stopChan:
  78. // 登出信号
  79. errCode = pb.ErrorReason(stop)
  80. log.Println("<ClientLogin> player stop connect, code:", stop)
  81. return
  82. }
  83. }
  84. }).Catch(func(ex exception.Exception) {
  85. log.Println("<ClientLogin> error:", ex)
  86. }).Finally(func() {
  87. switch errCode {
  88. // 处理等待队列中的玩家
  89. case pb.ErrorReason_PLAYER_WAIT_QUEUE_OVERTIME, pb.ErrorReason_PLAYER_CALL_LOGOUT, pb.ErrorReason_PLAYER_REPEAT_LOGIN:
  90. server.OnPlayerQuitWaitQueue(server, player)
  91. break
  92. }
  93. // 记录日志
  94. service := server.GetServiceByPlayerId(player.Id)
  95. if service != nil {
  96. l.svcCtx.Db.ChatRecordToDb(player, service.Id, player.Id, db.EDbRecordState_E_DB_RECORD_STATE_DISCONNECT)
  97. }
  98. // 断开处理
  99. server.OnPlayerDisConnect(server, player.Id, errCode)
  100. })
  101. return nil
  102. }