package room import ( "dcg/game" pbRoom "dcg/game/pb/room" "fmt" "git.noahlan.cn/northlan/ngs" "git.noahlan.cn/northlan/ngs/component" "git.noahlan.cn/northlan/ngs/scheduler" "git.noahlan.cn/northlan/ngs/session" "git.noahlan.cn/northlan/ntools-go/logger" "git.noahlan.cn/northlan/ntools-go/uuid" "github.com/golang/protobuf/proto" "time" ) const ( roomKey = "ROOM" liveRoomIdKey = "LIVE_ROOM_ID" ) type ( // Room 游戏房间 // 一种游戏类型一个房间(后期有需要再进行修改) // 一个房间可加入多个直播间客户端 Room struct { Id int64 // 房间ID GameType pbRoom.GameType // 游戏类型 group *ngs.Group // 分组 } Manager struct { component.Base timer *scheduler.Timer rooms map[pbRoom.GameType]*Room } ) func NewRoomManager() *Manager { return &Manager{ rooms: make(map[pbRoom.GameType]*Room), } } func (m *Manager) CMD() string { return "room" } func (m *Manager) Init() { } func (m *Manager) AfterInit() { session.Lifetime.OnClosed(func(s *session.Session) { if !s.HasKey(roomKey) { return } room := s.Value(roomKey).(*Room) _ = room.group.Leave(s) }) m.timer = scheduler.NewTimer(30*time.Second, func() { for roomId, room := range m.rooms { logger.SLog.Debugf("UserCount: RoomID=%d, Time=%s, Count=%d", roomId, time.Now().String(), room.group.Count()) } }) } func (m *Manager) Shutdown() { for _, room := range m.rooms { _ = room.group.LeaveAll() } } func (m *Manager) Join(s *session.Session, msg *pbRoom.JoinRoomReq) error { room := m.RoomByGameType(msg.GameType) game.CacheGameType(msg.LiveRoomId, msg.GameType) // uid - uuid err := s.Bind(uuid.NextId()) if err != nil { return err } s.Set(roomKey, room) s.Set(liveRoomIdKey, msg.LiveRoomId) // members var resp = &pbRoom.JoinRoomResp{ Code: 200, Result: "加入房间成功", } err = room.group.Add(s) if err != nil { resp.Code = 500 resp.Result = "加入房间失败" } else { _ = room.group.Broadcast("onNewClient", &pbRoom.Client{Id: msg.LiveRoomId}) } return s.Response(&pbRoom.JoinRoomResp{ Code: 200, Result: "success", }) } // RoomByGameType 通过游戏类型获取游戏房间 // 若房间不存在,则创建之 func (m *Manager) RoomByGameType(gameType pbRoom.GameType) *Room { room, found := m.rooms[gameType] if !found { room = &Room{ Id: uuid.NextId(), GameType: gameType, group: ngs.NewGroup(fmt.Sprintf("Room-%s", pbRoom.GameType_name[int32(gameType)])), } m.rooms[gameType] = room } return room } func (m *Manager) RoomByLiveRoomId(liveRoomId int64) (*Room, error) { gameType, err := game.GameTypeByLiveRoomId(liveRoomId) if err != nil { return nil, err } return m.RoomByGameType(gameType), nil } // Broadcast 消息全局分发 func (m *Manager) Broadcast(route string, msg proto.Message) { for _, room := range m.rooms { err := room.group.Broadcast(route, msg) if err != nil { logger.SLog.Errorf("broadcast message to room %d err:%+v", room.Id, err) } } } // PushToLiveRoom 消息Push到直播间ID指定客户端 func (r *Room) PushToLiveRoom(liveRoomId int64, route string, msg proto.Message) { for _, sid := range r.group.Members() { member, err := r.group.Member(sid) if err != nil { continue } lRId := member.Value(liveRoomIdKey).(int64) if lRId == liveRoomId { err = member.Push(route, msg) if err != nil { logger.SLog.Errorf("推送消息到 直播间[%d]客户端 失败, err:%+v", liveRoomId, err) } } } } // Broadcast 房间内分发消息 func (r *Room) Broadcast(route string, msg proto.Message) { err := r.group.Broadcast(route, msg) if err != nil { logger.SLog.Errorf("推送消息到 房间[%d:%s] 失败, err:%+v", r.Id, pbRoom.GameType_name[int32(r.GameType)], err) return } }