You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
2.4 KiB
Go

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
}