|
|
|
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
|
|
|
|
}
|