480 lines
14 KiB
Go
480 lines
14 KiB
Go
package main
|
|
|
|
import (
|
|
"math/rand"
|
|
"time"
|
|
|
|
"mongo.games.com/goserver/core"
|
|
"mongo.games.com/goserver/core/logger"
|
|
"mongo.games.com/goserver/core/module"
|
|
"mongo.games.com/goserver/core/transact"
|
|
|
|
"mongo.games.com/game/common"
|
|
"mongo.games.com/game/model"
|
|
"mongo.games.com/game/proto"
|
|
hallproto "mongo.games.com/game/protocol/gamehall"
|
|
"mongo.games.com/game/protocol/server"
|
|
"mongo.games.com/game/protocol/webapi"
|
|
"mongo.games.com/game/srvdata"
|
|
)
|
|
|
|
var CoinSceneMgrSingleton = &CoinSceneMgr{
|
|
playerChanging: make(map[int32]int32),
|
|
scenesOfPlatform: make(map[string]map[int32]*CoinScenePool),
|
|
}
|
|
|
|
type CreateRoomCache struct {
|
|
gameFreeId int32
|
|
platformName string
|
|
}
|
|
|
|
type CoinSceneMgr struct {
|
|
scenesOfPlatform map[string]map[int32]*CoinScenePool // 场次房间池 platform:gamefreeid
|
|
playerChanging map[int32]int32 // 换桌中的玩家 snid:gamefreeid
|
|
//延迟创建房间列表
|
|
delayCache []*CreateRoomCache // 待预创建房间
|
|
}
|
|
|
|
// GetCoinScenePool 获取一个场景池
|
|
// plt 平台id
|
|
// id 场次id
|
|
func (m *CoinSceneMgr) GetCoinScenePool(plt string, id int32) *CoinScenePool {
|
|
gf := PlatformMgrSingleton.GetGameFree(plt, id)
|
|
if gf == nil || gf.DbGameFree == nil {
|
|
return nil
|
|
}
|
|
|
|
if ss, ok := m.scenesOfPlatform[plt]; ok {
|
|
if csp, ok := ss[id]; ok && csp != nil {
|
|
return csp
|
|
}
|
|
}
|
|
|
|
// 创建了一个新的
|
|
// 模块启动时所有场次都创建了房间池
|
|
pool := newCoinScenePool(plt, gf.GetDbGameFree())
|
|
v, ok := m.scenesOfPlatform[plt]
|
|
if !ok || v == nil {
|
|
m.scenesOfPlatform[plt] = make(map[int32]*CoinScenePool)
|
|
}
|
|
m.scenesOfPlatform[plt][id] = pool
|
|
return pool
|
|
}
|
|
|
|
// findCoinScenePool 查找指定平台和ID的场景池
|
|
// platform 平台ID
|
|
// id 场次ID
|
|
// 返回场景池map和对应的游戏场次配置
|
|
func (m *CoinSceneMgr) findCoinScenePool(platform string, id int32) (pools map[int32]*CoinScenePool, dbGameFree *server.DB_GameFree) {
|
|
gf := PlatformMgrSingleton.GetGameFree(platform, id)
|
|
if gf == nil || gf.GetDbGameFree() == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
ss, ok := m.scenesOfPlatform[platform]
|
|
if !ok || ss == nil {
|
|
ss = make(map[int32]*CoinScenePool)
|
|
m.scenesOfPlatform[platform] = ss
|
|
}
|
|
return ss, gf.GetDbGameFree()
|
|
}
|
|
|
|
// PlayerEnter 玩家进入房间池
|
|
// 参数:
|
|
// - p: 玩家对象
|
|
// - id: 场次ID
|
|
// - roomId: 房间ID,为0时随机分配房间
|
|
// - exclude: 排除的房间ID列表
|
|
// - isChangeRoom: 是否为换房操作
|
|
//
|
|
// 返回值:
|
|
// - hallproto.OpResultCode: 操作结果代码
|
|
func (m *CoinSceneMgr) PlayerEnter(p *Player, id int32, roomId int32, exclude []int32, isChangeRoom bool) hallproto.OpResultCode {
|
|
logger.Logger.Tracef("CoinSceneMgr PlayerEnter snid:%v id:%v roomid:%v exclude:%v", p.SnId, id, roomId, exclude)
|
|
//删档用户不让进游戏
|
|
if p.isDelete {
|
|
return hallproto.OpResultCode_OPRC_RoomHadClosed
|
|
}
|
|
// 玩家已经在房间里了
|
|
if m.InCoinScene(p) {
|
|
logger.Logger.Warnf("CoinSceneMgr PlayerEnter snid:%v find in gamefreeid:%v roomId:%v", p.SnId, p.scene.dbGameFree.Id, p.scene.sceneId)
|
|
return hallproto.OpResultCode_OPRC_Error
|
|
}
|
|
//多平台支持
|
|
platform := p.GetPlatform()
|
|
if platform == nil {
|
|
return hallproto.OpResultCode_OPRC_RoomHadClosed
|
|
}
|
|
csp := m.GetCoinScenePool(platform.IdStr, id)
|
|
ret := csp.playerEnter(p, roomId, exclude, isChangeRoom)
|
|
logger.Logger.Tracef("CoinSceneMgr PlayerEnter snid:%v id:%v ret:%v", p.SnId, id, ret)
|
|
return ret
|
|
}
|
|
|
|
// AudienceEnter 观众进入房间
|
|
// 参数:
|
|
// - p: 玩家对象
|
|
// - id: 场次ID
|
|
// - roomId: 房间ID,为0时随机分配房间
|
|
// - exclude: 排除的房间ID列表
|
|
// - ischangeroom: 是否为换房操作
|
|
//
|
|
// 返回值:
|
|
// - hallproto.OpResultCode: 操作结果代码
|
|
func (m *CoinSceneMgr) AudienceEnter(p *Player, id int32, roomId int32, exclude []int32, ischangeroom bool) hallproto.OpResultCode {
|
|
logger.Logger.Tracef("CoinSceneMgr AudienceEnter snid:%v id:%v roomid:%v exclude:%v", p.SnId, id, roomId, exclude)
|
|
//删档用户不让进游戏
|
|
if p.isDelete {
|
|
return hallproto.OpResultCode_OPRC_RoomHadClosed
|
|
}
|
|
if m.InCoinScene(p) {
|
|
logger.Logger.Warnf("CoinSceneMgr AudienceEnter snid:%v find in gamefreeid:%v roomId:%v", p.SnId, p.scene.dbGameFree.Id, p.scene.sceneId)
|
|
return hallproto.OpResultCode_OPRC_Error
|
|
}
|
|
//多平台支持
|
|
platform := p.GetPlatform()
|
|
if platform == nil {
|
|
return hallproto.OpResultCode_OPRC_RoomHadClosed
|
|
}
|
|
|
|
pools, _ := m.findCoinScenePool(platform.IdStr, id)
|
|
if pools == nil {
|
|
return hallproto.OpResultCode_OPRC_RoomHadClosed
|
|
}
|
|
if len(pools) == 0 {
|
|
return hallproto.OpResultCode_OPRC_NoFindDownTiceRoom
|
|
}
|
|
|
|
csp, ok := pools[id]
|
|
if !ok || csp == nil {
|
|
return hallproto.OpResultCode_OPRC_RoomHadClosed
|
|
}
|
|
|
|
ret := csp.audienceEnter(p, roomId, exclude, ischangeroom)
|
|
logger.Logger.Tracef("CoinSceneMgr AudienceEnter snid:%v id:%v ret:%v", p.SnId, id, ret)
|
|
return ret
|
|
}
|
|
|
|
// PlayerLeave 玩家离开
|
|
// 游戏服玩家离开房间消息触发
|
|
func (m *CoinSceneMgr) PlayerLeave(p *Player, reason int) bool {
|
|
logger.Logger.Tracef("玩家离开: snid %v, reason %v", p.SnId, reason)
|
|
if p.scene == nil || p.scene.csp == nil {
|
|
return false
|
|
}
|
|
if p.scene.csp.playerLeave(p, reason) {
|
|
return true
|
|
}
|
|
if p.scene.csp.audienceLeave(p, reason) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// OnDestroyScene 解散房间
|
|
// 游戏服解散房间消息触发
|
|
// sceneId 房间id
|
|
func (m *CoinSceneMgr) OnDestroyScene(sceneId int) {
|
|
if s := SceneMgrSingleton.GetScene(sceneId, true); s != nil && s.csp != nil {
|
|
s.csp.onDestroyScene(sceneId)
|
|
}
|
|
}
|
|
|
|
// GetPlayerNums 获取场次人数
|
|
func (m *CoinSceneMgr) GetPlayerNums(p *Player, gameId, gameMode int32) []int32 {
|
|
//多平台支持
|
|
platform := p.GetPlatform()
|
|
var nums [10]int32
|
|
wantNum := [10]int32{80, 50, 30, 20, 10, 10, 10, 10, 10, 10}
|
|
for i := 0; i < 10; i++ {
|
|
if wantNum[i]/2 > 0 {
|
|
nums[i] = rand.Int31n(wantNum[i]/2) + wantNum[i]
|
|
}
|
|
}
|
|
if platform == nil {
|
|
return nums[:]
|
|
}
|
|
ids, _ := srvdata.GameFreeMgr.GetGameFreeIds(gameId, gameMode)
|
|
for _, id := range ids {
|
|
gps := PlatformMgrSingleton.GetGameFree(platform.IdStr, id)
|
|
if gps != nil {
|
|
if ss, ok := m.scenesOfPlatform[platform.IdStr]; ok {
|
|
if csp, exist := ss[id]; exist {
|
|
sceneType := csp.GetSceneType() - 1
|
|
if sceneType >= 0 && sceneType < len(nums) {
|
|
nums[sceneType] += csp.GetPlayerNum() + csp.GetFakePlayerNum()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(ids) <= 10 {
|
|
return nums[:len(ids)]
|
|
}
|
|
return nums[:]
|
|
}
|
|
|
|
// InCoinScene 检查玩家是否在场次中
|
|
func (m *CoinSceneMgr) InCoinScene(p *Player) bool {
|
|
if p == nil {
|
|
logger.Logger.Tracef("(m *CoinSceneMgr) InCoinScene p == nil")
|
|
return false
|
|
}
|
|
|
|
if p.scene == nil {
|
|
return false
|
|
}
|
|
|
|
if p.scene.csp == nil {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// PlayerTryLeave 通知游戏服务玩家要离开房间
|
|
func (m *CoinSceneMgr) PlayerTryLeave(p *Player, isAudience bool) hallproto.OpResultCode {
|
|
if !m.InCoinScene(p) {
|
|
logger.Logger.Tracef("(m *CoinSceneMgr) PlayerTryLeave !m.InCoinScene(p) snid:%v ", p.SnId)
|
|
return hallproto.OpResultCode_OPRC_Sucess
|
|
}
|
|
|
|
// 通知gamesrv
|
|
op := common.CoinSceneOp_Leave
|
|
if isAudience {
|
|
op = common.CoinSceneOp_AudienceLeave
|
|
}
|
|
pack := &hallproto.CSCoinSceneOp{
|
|
Id: proto.Int32(p.scene.csp.ID()),
|
|
OpType: proto.Int32(op),
|
|
}
|
|
common.TransmitToServer(p.sid, int(hallproto.CoinSceneGamePacketID_PACKET_CS_COINSCENE_OP), pack, p.scene.gameSess.Session)
|
|
logger.Logger.Tracef("(m *CoinSceneMgr) PlayerTryLeave snid:%v id:%v", p.SnId, pack.GetId())
|
|
|
|
return hallproto.OpResultCode_OPRC_OpYield
|
|
}
|
|
|
|
// PlayerInChanging 检查玩家是否正在换房中
|
|
func (m *CoinSceneMgr) PlayerInChanging(p *Player) bool {
|
|
_, exist := m.playerChanging[p.SnId]
|
|
return exist
|
|
}
|
|
|
|
// ClearPlayerChanging 清除玩家换房状态
|
|
func (m *CoinSceneMgr) ClearPlayerChanging(p *Player) {
|
|
delete(m.playerChanging, p.SnId)
|
|
}
|
|
|
|
// PlayerTryChange 玩家尝试换房
|
|
// id 场次id
|
|
// excludeRoomId 排除的房间id
|
|
// isAudience 是否是观众
|
|
func (m *CoinSceneMgr) PlayerTryChange(p *Player, id int32, excludeRoomId []int32, isAudience bool) hallproto.OpResultCode {
|
|
if m.InCoinScene(p) {
|
|
return m.StartChangeCoinSceneTransact(p, id, excludeRoomId, isAudience)
|
|
}
|
|
|
|
// 不在场次中,进入房间观战
|
|
if isAudience {
|
|
return m.AudienceEnter(p, id, 0, excludeRoomId, true)
|
|
}
|
|
// 不在场次中,进入房间
|
|
return m.PlayerEnter(p, id, 0, excludeRoomId, true)
|
|
}
|
|
|
|
// StartChangeCoinSceneTransact 开始换房事务
|
|
func (m *CoinSceneMgr) StartChangeCoinSceneTransact(p *Player, id int32, exclude []int32, isAudience bool) hallproto.OpResultCode {
|
|
if p == nil || p.scene == nil {
|
|
logger.Logger.Warnf("(m *CoinSceneMgr) StartChangeCoinSceneTransact p == nil || p.scene == nil snid:%v id:%v", p.SnId, id)
|
|
return hallproto.OpResultCode_OPRC_Error
|
|
}
|
|
|
|
tNow := time.Now()
|
|
if !p.lastChangeScene.IsZero() && tNow.Sub(p.lastChangeScene) < time.Second {
|
|
logger.Logger.Warnf("(m *CoinSceneMgr) StartChangeCoinSceneTransact !p.lastChangeScene.IsZero() && tNow.Sub(p.lastChangeScene) < time.Second snid:%v id:%v", p.SnId, id)
|
|
return hallproto.OpResultCode_OPRC_ChangeRoomTooOften
|
|
}
|
|
|
|
tnp := &transact.TransNodeParam{
|
|
Tt: common.TransTypeCoinSceneChange,
|
|
Ot: transact.TransOwnerType(common.GetSelfSrvType()),
|
|
Oid: common.GetSelfSrvId(),
|
|
AreaID: common.GetSelfAreaId(),
|
|
}
|
|
ctx := &CoinSceneChangeCtx{
|
|
id: id,
|
|
isClub: false,
|
|
snid: p.SnId,
|
|
sceneId: int32(p.scene.sceneId),
|
|
exclude: exclude,
|
|
isAudience: isAudience,
|
|
}
|
|
tNode := transact.DTCModule.StartTrans(tnp, ctx, CoinSceneChangeTimeOut)
|
|
if tNode != nil {
|
|
tNode.Go(core.CoreObject())
|
|
m.playerChanging[p.SnId] = id
|
|
p.lastChangeScene = tNow
|
|
return hallproto.OpResultCode_OPRC_Sucess
|
|
}
|
|
logger.Logger.Warnf("(m *CoinSceneMgr) StartChangeCoinSceneTransact tNode == nil snid:%v id:%v", p.SnId, id)
|
|
return hallproto.OpResultCode_OPRC_Error
|
|
}
|
|
|
|
// TouchCreateRoom 触发预创建房间
|
|
// 1.模块启动后触发
|
|
// 2.游戏服建立连接后触发
|
|
// 3.房间解散后触发
|
|
// 4.场次配置更新后
|
|
func (m *CoinSceneMgr) TouchCreateRoom(platform string, gameFreeId int32) {
|
|
if model.GameParamData.ClosePreCreateRoom {
|
|
return
|
|
}
|
|
gf := PlatformMgrSingleton.GetGameFree(platform, gameFreeId)
|
|
if gf.Status && gf.DbGameFree.GetCreateRoomNum() > 0 {
|
|
logger.Logger.Tracef("TouchCreateRoom platform:%v gameFreeId:%v", platform, gameFreeId)
|
|
m.delayCache = append(m.delayCache, &CreateRoomCache{
|
|
platformName: platform,
|
|
gameFreeId: gameFreeId,
|
|
})
|
|
}
|
|
}
|
|
|
|
func (m *CoinSceneMgr) ModuleName() string {
|
|
return "CoinSceneMgr"
|
|
}
|
|
|
|
func (m *CoinSceneMgr) Init() {
|
|
// 房间池初始化
|
|
for _, platform := range PlatformMgrSingleton.GetPlatforms() {
|
|
if platform.Isolated || platform.IdStr == "" {
|
|
for _, v := range srvdata.PBDB_GameFreeMgr.Datas.GetArr() {
|
|
gps := PlatformMgrSingleton.GetGameFree(platform.IdStr, v.GetId())
|
|
if gps != nil {
|
|
m.GetCoinScenePool(platform.IdStr, v.GetId())
|
|
m.TouchCreateRoom(platform.IdStr, v.GetId())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (m *CoinSceneMgr) Update() {
|
|
cnt := len(m.delayCache)
|
|
if cnt > 0 {
|
|
data := m.delayCache[cnt-1]
|
|
m.delayCache = m.delayCache[:cnt-1]
|
|
gf := PlatformMgrSingleton.GetGameFree(data.platformName, data.gameFreeId)
|
|
if gf != nil && gf.DbGameFree != nil {
|
|
csp := m.GetCoinScenePool(data.platformName, data.gameFreeId)
|
|
if csp != nil {
|
|
csp.PreCreateRoom()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (m *CoinSceneMgr) Shutdown() {
|
|
module.UnregisteModule(m)
|
|
}
|
|
|
|
//=====================PlatformObserver======================
|
|
|
|
func (m *CoinSceneMgr) OnPlatformCreate(p *Platform) {
|
|
|
|
}
|
|
|
|
func (m *CoinSceneMgr) OnPlatformDestroy(p *Platform) {
|
|
if p == nil {
|
|
return
|
|
}
|
|
var ids []int
|
|
if v, ok := m.scenesOfPlatform[p.IdStr]; ok {
|
|
for _, csp := range v {
|
|
for _, scene := range csp.scenes {
|
|
ids = append(ids, scene.sceneId)
|
|
}
|
|
}
|
|
}
|
|
SceneMgrSingleton.SendGameDestroy(ids, true)
|
|
}
|
|
|
|
func (m *CoinSceneMgr) OnPlatformChangeDisabled(p *Platform, disabled bool) {
|
|
if disabled {
|
|
m.OnPlatformDestroy(p)
|
|
}
|
|
}
|
|
|
|
func (m *CoinSceneMgr) OnPlatformGameFreeUpdate(p *Platform, oldCfg, newCfg *webapi.GameFree) {
|
|
if p == nil || newCfg == nil {
|
|
return
|
|
}
|
|
|
|
ss, ok := m.scenesOfPlatform[p.IdStr]
|
|
if !ok || ss == nil {
|
|
return
|
|
}
|
|
|
|
if cps, ok := ss[newCfg.DbGameFree.Id]; ok {
|
|
cps.dbGameFree = newCfg.DbGameFree
|
|
var ids []int
|
|
for _, scene := range cps.scenes {
|
|
ids = append(ids, scene.sceneId)
|
|
}
|
|
SceneMgrSingleton.SendGameDestroy(ids, true)
|
|
m.TouchCreateRoom(p.IdStr, newCfg.DbGameFree.Id)
|
|
}
|
|
}
|
|
|
|
func (m *CoinSceneMgr) OnPlatformDestroyByGameFreeId(p *Platform, gameFreeId int32) {
|
|
if p == nil {
|
|
return
|
|
}
|
|
var ids []int
|
|
if v, ok := m.scenesOfPlatform[p.IdStr]; ok {
|
|
for _, csp := range v {
|
|
for _, scene := range csp.scenes {
|
|
if scene.dbGameFree.Id == gameFreeId {
|
|
ids = append(ids, scene.sceneId)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
SceneMgrSingleton.SendGameDestroy(ids, true)
|
|
}
|
|
|
|
//=========================PlatformGameGroupObserver==============================
|
|
|
|
func (m *CoinSceneMgr) OnGameGroupUpdate(oldCfg, newCfg *webapi.GameConfigGroup) {
|
|
|
|
}
|
|
|
|
//=========================GameSessionListener======================================
|
|
|
|
func (m *CoinSceneMgr) OnGameSessionRegiste(gs *GameSession) {
|
|
wildGs := len(gs.gameIds) == 0 || common.InSliceInt32(gs.gameIds, 0) // 是否所有游戏都支持
|
|
for _, platform := range PlatformMgrSingleton.GetPlatforms() {
|
|
if platform.IdStr == DefaultPlatform {
|
|
continue
|
|
}
|
|
//获取配置
|
|
gps := PlatformMgrSingleton.GetGameFrees(platform.IdStr)
|
|
for _, v := range gps {
|
|
if v != nil && (wildGs || common.InSliceInt32(gs.gameIds, v.DbGameFree.GetGameId())) {
|
|
m.TouchCreateRoom(platform.IdStr, v.DbGameFree.Id)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (m *CoinSceneMgr) OnGameSessionUnregiste(gs *GameSession) {
|
|
//todo 游戏服务断开,是否解散房间?
|
|
}
|
|
|
|
func init() {
|
|
module.RegisteModule(CoinSceneMgrSingleton, time.Second*2, 0)
|
|
|
|
PlatformMgrSingleton.RegisterObserver(CoinSceneMgrSingleton)
|
|
PlatformGameGroupMgrSington.RegisteObserver(CoinSceneMgrSingleton)
|
|
RegisteGameSessionListener(CoinSceneMgrSingleton)
|
|
}
|