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.
169 lines
4.0 KiB
Go
169 lines
4.0 KiB
Go
package manager
|
|
|
|
import (
|
|
"dcg/game"
|
|
pbRoom "dcg/game/pb/room"
|
|
"errors"
|
|
"fmt"
|
|
"git.noahlan.cn/northlan/ngs"
|
|
"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"
|
|
)
|
|
|
|
type (
|
|
// Room 游戏房间
|
|
// 一种游戏类型一个房间(后期有需要再进行修改)
|
|
// 一个房间可加入多个直播间客户端
|
|
Room struct {
|
|
Id int64 // 房间ID
|
|
GameType pbRoom.GameType // 游戏类型
|
|
|
|
group *ngs.Group // 分组
|
|
}
|
|
|
|
RoomManager struct {
|
|
rooms map[pbRoom.GameType]*Room
|
|
}
|
|
)
|
|
|
|
func NewRoomManager() *RoomManager {
|
|
return &RoomManager{
|
|
rooms: make(map[pbRoom.GameType]*Room),
|
|
}
|
|
}
|
|
|
|
func (m *RoomManager) Rooms() []*Room {
|
|
resp := make([]*Room, 0, len(m.rooms))
|
|
for _, room := range m.rooms {
|
|
resp = append(resp, room)
|
|
}
|
|
return resp
|
|
}
|
|
|
|
func (m *RoomManager) Sessions() []*session.Session {
|
|
resp := make([]*session.Session, 0)
|
|
for _, room := range m.rooms {
|
|
for _, sid := range room.group.Members() {
|
|
member, err := room.group.Member(sid)
|
|
if err != nil {
|
|
return resp
|
|
}
|
|
resp = append(resp, member)
|
|
}
|
|
}
|
|
return resp
|
|
}
|
|
|
|
// RoomByGameType 通过游戏类型获取游戏房间
|
|
// 若房间不存在,则创建之
|
|
func (m *RoomManager) 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 *RoomManager) RoomByLiveRoomId(liveRoomId int64) (*Room, error) {
|
|
gameType, err := game.GameTypeByLiveRoomId(liveRoomId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return m.RoomByGameType(gameType), nil
|
|
}
|
|
|
|
func (m *RoomManager) SessionByLiveRoomId(liveRoomId int64) (*session.Session, error) {
|
|
room, err := m.RoomByLiveRoomId(liveRoomId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return room.SessionByLiveRoomId(liveRoomId)
|
|
}
|
|
|
|
func (m *RoomManager) SessionJoinRoom(s *session.Session, gameType pbRoom.GameType, liveRoomId int64) error {
|
|
room := m.RoomByGameType(gameType)
|
|
game.CacheGameType(liveRoomId, gameType)
|
|
|
|
// uid - uuid
|
|
err := s.Bind(uuid.NextId())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
s.Set(RoomKey, room)
|
|
s.Set(LiveRoomIdKey, liveRoomId)
|
|
s.Set(DataKey, NewGameData())
|
|
|
|
return room.group.Add(s)
|
|
}
|
|
|
|
func (m *RoomManager) SessionLeaveRoom(s *session.Session) {
|
|
if !s.HasKey(RoomKey) {
|
|
return
|
|
}
|
|
room := s.Value(RoomKey).(*Room)
|
|
_ = room.group.Leave(s)
|
|
}
|
|
|
|
func (m *RoomManager) Clean() {
|
|
for _, room := range m.rooms {
|
|
_ = room.group.LeaveAll()
|
|
}
|
|
}
|
|
|
|
// Broadcast 消息全局分发
|
|
func (m *RoomManager) 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) {
|
|
sess, err := r.SessionByLiveRoomId(liveRoomId)
|
|
if err != nil {
|
|
return
|
|
}
|
|
err = sess.Push(route, msg)
|
|
if err != nil {
|
|
logger.SLog.Errorf("推送消息到 直播间[%d]客户端 失败, err:%+v", liveRoomId, err)
|
|
}
|
|
}
|
|
|
|
func (r *Room) SessionByLiveRoomId(liveRoomId int64) (*session.Session, error) {
|
|
for _, sid := range r.group.Members() {
|
|
member, err := r.group.Member(sid)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if !member.HasKey(LiveRoomIdKey) {
|
|
continue
|
|
}
|
|
lRId := member.Value(LiveRoomIdKey).(int64)
|
|
if lRId == liveRoomId {
|
|
return member, nil
|
|
}
|
|
}
|
|
logger.SLog.Errorf("未找到直播间 [%d] 的客户端实例", liveRoomId)
|
|
return nil, errors.New("未找到客户端实例")
|
|
}
|
|
|
|
// 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
|
|
}
|
|
}
|