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.

164 lines
3.8 KiB
Go

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