package manager import ( pbRoom "dcg/game/pb/room" "errors" "fmt" "git.noahlan.cn/northlan/ngs/session" "git.noahlan.cn/northlan/ntools-go/uuid" "google.golang.org/protobuf/proto" "sync" ) const ( RoomKey = "ROOM" ) type ( // RoomManager 房间管理器 RoomManager struct { rooms map[pbRoom.GameType]*Room mutex sync.RWMutex } ) func NewRoomManager() *RoomManager { return &RoomManager{ rooms: make(map[pbRoom.GameType]*Room), } } func (m *RoomManager) Members() []*session.Session { m.mutex.RLock() defer m.mutex.RUnlock() resp := make([]*session.Session, 0) for _, room := range m.rooms { resp = append(resp, room.Members()...) } return resp } func (m *RoomManager) PeekRoom(fn func(gameType pbRoom.GameType, room *Room) bool) { m.mutex.RLock() defer m.mutex.RUnlock() for gameType, room := range m.rooms { if !fn(gameType, room) { break } } } func (m *RoomManager) PeekAllSession(fn func(*Room, *session.Session) bool) { m.mutex.RLock() defer m.mutex.RUnlock() for _, room := range m.rooms { room.PeekMembers(func(sId int64, s *session.Session) bool { return fn(room, s) }) } } func (m *RoomManager) JoinRoom(s *session.Session, gameType pbRoom.GameType) error { room := m.RetrieveRoomByType(gameType) s.Set(RoomKey, room) return room.Add(s) } func (m *RoomManager) LeaveRoom(s *session.Session) { room, err := m.RoomBySession(s) if err != nil { return } _ = room.Leave(s) } func (m *RoomManager) RoomBySession(s *session.Session) (*Room, error) { if !s.HasKey(RoomKey) { return nil, errors.New(fmt.Sprintf("session [%d] 未加入房间", s.ID())) } room := s.Value(RoomKey).(*Room) return room, nil } func (m *RoomManager) Clean() { m.mutex.Lock() defer m.mutex.Unlock() for _, room := range m.rooms { _ = room.LeaveAll() } m.rooms = make(map[pbRoom.GameType]*Room) } // Broadcast 消息全局分发,即所有房间分发 func (m *RoomManager) Broadcast(route string, msg proto.Message) { m.mutex.RLock() defer m.mutex.RUnlock() for _, room := range m.rooms { room.Broadcast(route, msg) } } // RetrieveRoomByType 通过游戏类型获取游戏房间 // 若房间不存在,则创建 func (m *RoomManager) RetrieveRoomByType(gameType pbRoom.GameType) *Room { m.mutex.Lock() defer m.mutex.Unlock() room, found := m.rooms[gameType] if !found { room = newRoom(uuid.NextId(), gameType) m.rooms[gameType] = room } return room }