actor_group.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. package chat
  2. import (
  3. actorRemote "f1-game/internal/actor_remote"
  4. "f1-game/internal/code"
  5. "f1-game/internal/component/redis"
  6. "f1-game/internal/enum"
  7. nameActor "f1-game/internal/name/actor"
  8. nameRedis "f1-game/internal/name/redis"
  9. nameRemote "f1-game/internal/name/remote"
  10. nameRoute "f1-game/internal/name/route"
  11. "f1-game/internal/pb"
  12. "f1-game/internal/types"
  13. cherrySlice "github.com/cherry-game/cherry/extend/slice"
  14. ctime "github.com/cherry-game/cherry/extend/time"
  15. clog "github.com/cherry-game/cherry/logger"
  16. )
  17. type (
  18. actorGroup struct {
  19. RoomTypeList
  20. }
  21. )
  22. func NewActorGroup() *actorGroup {
  23. return &actorGroup{
  24. RoomTypeList: newRoomTypeList(enum.ChatType_Group),
  25. }
  26. }
  27. func (p *actorGroup) OnInit() {
  28. p.Remote().Register(nameRemote.Chat_GroupJoin, p.groupJoin)
  29. p.Remote().Register(nameRemote.Chat_GroupQuit, p.groupQuit)
  30. p.Remote().Register(nameRemote.Chat_GroupPlayerChange, p.groupPlayerChange)
  31. p.Remote().Register(nameRemote.Chat_Send, p.send)
  32. p.Remote().Register(nameRemote.Chat_Push, p.Push)
  33. p.Remote().Register(nameRemote.Chat_Destory, p.destory)
  34. p.Remote().Register(nameRemote.Chat_DelMsg, p.DelMsg)
  35. p.initCleanRoomTimer()
  36. }
  37. func (p *actorGroup) AliasID() string {
  38. return nameActor.Chat_Group
  39. }
  40. // 在列表同意加入群组
  41. func (p *actorGroup) groupJoin(req *pb.I64I64) int32 {
  42. var (
  43. chatID = req.Key
  44. playerID = req.Value
  45. )
  46. memberCount := redis.Chat.GetGroupMemberCount(chatID)
  47. if memberCount == 0 {
  48. // 群组解散没有成员了
  49. return code.ChatGroupNotFound
  50. }
  51. // 群组满员了
  52. if p.playerLimit > 0 && memberCount >= p.playerLimit {
  53. return code.ChatGroupMemberLimit
  54. }
  55. chatRoom := p.GetChatRoom(chatID)
  56. p.flushPlayerIDList(chatRoom)
  57. chatRoom.PlayerIDList.Add(playerID)
  58. redis.Chat.AddGroupMember(chatID, playerID)
  59. return code.OK
  60. }
  61. // 主动退出群组
  62. func (p *actorGroup) groupQuit(req *pb.I64I64) {
  63. var (
  64. chatID = req.Key
  65. playerID = req.Value
  66. chatRoom = p.GetChatRoom(chatID)
  67. )
  68. // 直接清理,下次会从redis中重新加载
  69. chatRoom.PlayerIDList.Clear()
  70. redis.Chat.DelGroupMember(chatID, playerID)
  71. }
  72. func (p *actorGroup) send(req *pb.ChatMsgList) {
  73. chatRoom := p.GetChatRoom(req.ChatID)
  74. p.flushPlayerIDList(chatRoom)
  75. p.AddChatMsg(req)
  76. // 通知该群成员有人发言
  77. p.Broadcast2Client(chatRoom, nameRoute.PushChat_MsgList, req)
  78. // update last send time
  79. chatRoom.LastSendTime = ctime.Now()
  80. }
  81. // 群组成员只有为空的时候从redis中加载
  82. func (p *actorGroup) flushPlayerIDList(chatRoom *ChatRoom) {
  83. if chatRoom.LastSendTime.NowDiffSecond() < 1 {
  84. return
  85. }
  86. if members, found := redis.Chat.GetGroupMembers(chatRoom.ChatID); found {
  87. chatRoom.PlayerIDList = types.NewList(members...)
  88. }
  89. }
  90. func (p *actorGroup) destory(req *pb.I64) {
  91. memberList, found := redis.Chat.GetGroupMembers(req.Value)
  92. if !found {
  93. return
  94. }
  95. if len(memberList) > 0 {
  96. rsp := &pb.I64Bool{
  97. Key: req.Value,
  98. Value: true,
  99. }
  100. // 通知所有成员销毁群组
  101. playerDataMap := redis.Game.GetPlayerDataMap(memberList, nameRedis.PlayerGameNodeFields...)
  102. for _, memberID := range memberList {
  103. playerData, found := playerDataMap[memberID]
  104. if !found {
  105. clog.Warnf("destory get playerData is nil, chatId: %d, memberID: %d", req.Value, memberID)
  106. continue
  107. }
  108. actorRemote.GamePlayer.Call(playerData.GameNodeID, playerData.PlayerID, nameRemote.Player_ChatGroupMemberRemove, rsp)
  109. }
  110. // 删除redis中的群组成员
  111. redis.Chat.DelAllGroupMembers(req.Value)
  112. }
  113. p.Destory(req)
  114. }
  115. // 群组玩家变更
  116. func (p *actorGroup) groupPlayerChange(req *pb.ChatGroupPlayerChange) {
  117. var (
  118. removeList []int64 // 移除的成员
  119. inviteList []int64 // 邀请的成员
  120. allIDList []int64 // 所有需要查询的成员ID列表
  121. )
  122. memberList, _ := redis.Chat.GetGroupMembers(req.ChatID)
  123. // 不在原成员列表中的PlayerID则发出邀请
  124. for _, playerID := range req.PlayerIDList {
  125. if _, ok := cherrySlice.Int64In(playerID, memberList); !ok {
  126. inviteList = append(inviteList, playerID)
  127. }
  128. }
  129. // 原成员列表的PlayerID在新成员列表中找不到的则移除
  130. for _, oldPlayerID := range memberList {
  131. // 过滤群组创建者
  132. if oldPlayerID == req.OwnerPlayerID {
  133. continue
  134. }
  135. if _, ok := cherrySlice.Int64In(oldPlayerID, req.PlayerIDList); !ok {
  136. removeList = append(removeList, oldPlayerID)
  137. }
  138. }
  139. // 所有需要查询的成员ID列表:邀请人,移除的人,群主
  140. allIDList = append(allIDList, inviteList...)
  141. allIDList = append(allIDList, removeList...)
  142. allIDList = append(allIDList, req.OwnerPlayerID)
  143. // 一次性把需要查询成员数据都查出来
  144. chatPlayerMap := redis.Game.GetChatPlayerMap(allIDList...)
  145. if chatPlayerMap == nil {
  146. clog.Warnf("groupPlayerChange GetPlayerDataMap is nil, allIDList len: %v", len(allIDList))
  147. return
  148. }
  149. // 发起邀请
  150. p.inviteSend(req.ChatID, req.Name, req.OwnerPlayerID, inviteList, chatPlayerMap)
  151. // 移除成员
  152. p.playerRemoveSend(req.ChatID, removeList, chatPlayerMap)
  153. }
  154. // 发起群组邀请
  155. func (p *actorGroup) inviteSend(chatID int64, name string, ownerPlayerID int64, invitePlayerIDList []int64, chatPlayerMap map[int64]*pb.ChatPlayer) {
  156. if len(invitePlayerIDList) < 1 {
  157. return
  158. }
  159. inviteReq := &pb.GroupInvite{
  160. ChatID: chatID,
  161. Name: name,
  162. InvitePlayer: chatPlayerMap[ownerPlayerID],
  163. }
  164. for _, invitePlayerID := range invitePlayerIDList {
  165. playerData, found := chatPlayerMap[invitePlayerID]
  166. if !found {
  167. clog.Warnf("inviteSend playerData is nil, chatID: %d, invitePlayerID: %d", chatID, invitePlayerID)
  168. continue
  169. }
  170. actorRemote.GamePlayer.Call(playerData.GameNodeID, playerData.PlayerID, nameRemote.Player_ChatGroupInvite, inviteReq)
  171. }
  172. }
  173. // 发起踢出群组聊天的成员
  174. func (p *actorGroup) playerRemoveSend(chatID int64, removePlayerIDList []int64, chatPlayerMap map[int64]*pb.ChatPlayer) {
  175. if len(removePlayerIDList) < 1 {
  176. return
  177. }
  178. rsp := &pb.I64Bool{
  179. Key: chatID,
  180. Value: false,
  181. }
  182. for _, removePlayerID := range removePlayerIDList {
  183. chatPlayer, found := chatPlayerMap[removePlayerID]
  184. if !found {
  185. clog.Warnf("playerRemoveSend chatPlayer is nil, chatID: %d, removePlayerID: %d", chatID, removePlayerID)
  186. continue
  187. }
  188. actorRemote.GamePlayer.Call(chatPlayer.GameNodeID, chatPlayer.PlayerID, nameRemote.Player_ChatGroupMemberRemove, rsp)
  189. }
  190. redis.Chat.DelGroupMember(chatID, removePlayerIDList...)
  191. chatRoom := p.GetChatRoom(chatID)
  192. // 清理成员缓存,下次从redis重新拉取新的
  193. chatRoom.PlayerIDList.Clear()
  194. }