package main import ( "math/rand" "time" "mongo.games.com/goserver/core/logger" "mongo.games.com/goserver/core/module" "mongo.games.com/game/common" "mongo.games.com/game/model" "mongo.games.com/game/proto" gamehallproto "mongo.games.com/game/protocol/gamehall" serverproto "mongo.games.com/game/protocol/server" "mongo.games.com/game/protocol/webapi" "mongo.games.com/game/srvdata" ) const ( HundredSceneOPEnter int32 = iota //进入 HundredSceneOPLeave //离开 HundredSceneOPChange //换桌 ) var HundredSceneMgrSingleton = &HundredSceneMgr{ scenesOfPlatform: make(map[string]map[int32]*Scene), } type HundredSceneMgr struct { scenesOfPlatform map[string]map[int32]*Scene // platform:gamefreeid:房间 } // PlayerEnter 玩家进入场次 // id 场次id func (this *HundredSceneMgr) PlayerEnter(p *Player, id int32) gamehallproto.OpResultCode_Hundred { logger.Logger.Tracef("HundredSceneMgr PlayerEnter snid:%v gamefreeid:%v", p.SnId, id) if p.isDelete { return gamehallproto.OpResultCode_Hundred_OPRC_RoomHadClosed_Hundred } if this.InHundredScene(p) { logger.Logger.Warnf("HundredSceneMgr PlayerEnter snid:%v find in gamefreeid:%v roomId:%v", p.SnId, p.scene.dbGameFree.Id, p.scene.sceneId) return gamehallproto.OpResultCode_Hundred_OPRC_Error_Hundred } //多平台支持 platform := p.GetPlatform() if platform == nil { return gamehallproto.OpResultCode_Hundred_OPRC_RoomHadClosed_Hundred } gps := PlatformMgrSingleton.GetGameFree(platform.IdStr, id) if gps == nil { return gamehallproto.OpResultCode_Hundred_OPRC_RoomHadClosed_Hundred } //没有场景,尝试创建 if _, ok := this.scenesOfPlatform[platform.IdStr]; !ok { this.scenesOfPlatform[platform.IdStr] = make(map[int32]*Scene) } ss := this.scenesOfPlatform[platform.IdStr] if s, ok := ss[id]; !ok || s == nil { s = this.CreateNewScene(id, gps.GroupId, platform, gps.DbGameFree) if s != nil { ss[id] = s s.hp = this logger.Logger.Infof("HundredSceneMgr PlayerEnter(platform=%v snid=%v) Create %v scene success.", platform.IdStr, p.SnId, id) } else { logger.Logger.Errorf("HundredSceneMgr PlayerEnter(platform=%v snid=%v) Create %v scene failed.", platform.IdStr, p.SnId, id) } } //尝试进入 if s, ok := ss[id]; ok && s != nil { if s.PlayerEnter(p, -1, true) { logger.Logger.Infof("HundredSceneMgr PlayerEnter(platform=%v snid=%v) enter %v scene success.", platform.IdStr, p.SnId, id) return gamehallproto.OpResultCode_Hundred_OPRC_Sucess_Hundred } else { logger.Logger.Errorf("HundredSceneMgr PlayerEnter(platform=%v snid=%v) enter %v scene failed.", platform.IdStr, p.SnId, id) } } else { logger.Logger.Errorf("HundredSceneMgr PlayerEnter(platform=%v) get %v scene failed.", platform.IdStr, id) } return gamehallproto.OpResultCode_Hundred_OPRC_SceneServerMaintain_Hundred } // PlayerLeave 离开房间 // 游戏服通知玩家离开房间 func (this *HundredSceneMgr) PlayerLeave(p *Player, reason int) bool { if p == nil || p.scene == nil || p.scene.hp == nil { return false } p.scene.PlayerLeave(p, reason) return false } // PlayerTryLeave 玩家尝试离开房间 // 给游戏服发离开消息 func (this *HundredSceneMgr) PlayerTryLeave(p *Player) gamehallproto.OpResultCode_Hundred { if !this.InHundredScene(p) { logger.Logger.Tracef("(this *HundredSceneMgr) PlayerTryLeave !csm.InCoinScene(p) snid:%v ", p.SnId) return gamehallproto.OpResultCode_Hundred_OPRC_Sucess_Hundred } pack := &gamehallproto.CSLeaveRoom{Mode: proto.Int(0)} common.TransmitToServer(p.sid, int(gamehallproto.GameHallPacketID_PACKET_CS_LEAVEROOM), pack, p.scene.gameSess.Session) return gamehallproto.OpResultCode_Hundred_OPRC_Sucess_Hundred // ??? } // OnDestroyScene 房间销毁 func (this *HundredSceneMgr) OnDestroyScene(sceneId int) { s := SceneMgrSingleton.GetScene(sceneId, true) if s == nil { return } plt := SceneMgrSingleton.GetPlatformBySceneId(sceneId) if plt == "" { return } if ss, ok := this.scenesOfPlatform[plt]; ok { for id, scene := range ss { if scene.sceneId == sceneId { if scene != s { logger.Logger.Errorf("bug") } //删除玩家 for _, v := range scene.players { if v != nil { if !v.IsRob { ctx := scene.GetPlayerGameCtx(v.SnId) if ctx != nil { //发送一个探针,等待ack后同步金币 v.TryRetrieveLostGameCoin(sceneId) logger.Logger.Warnf("(this *HundredSceneMgr) OnDestroyScene(sceneid:%v) snid:%v SyncGameCoin", sceneId, v.SnId) } } } } scene.hp = nil delete(ss, id) break } } } this.tryCreateRoom(plt, s.dbGameFree.Id) } func (this *HundredSceneMgr) 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 := this.scenesOfPlatform[platform.IdStr]; ok { if s, exist := ss[id]; exist && s.dbGameFree != nil { sceneType := s.dbGameFree.GetSceneType() - 1 if sceneType >= 0 && int(sceneType) < len(nums) { nums[sceneType] += int32(s.GetPlayerCnt()) } } } } } if len(ids) <= 10 { return nums[:len(ids)] } return nums[:] } func (this *HundredSceneMgr) InHundredScene(p *Player) bool { if p == nil { return false } if p.scene == nil { return false } if p.scene.hp == nil { return false } return true } func (this *HundredSceneMgr) CreateNewScene(id, groupId int32, limitPlatform *Platform, dbGameFree *serverproto.DB_GameFree) *Scene { if dbGameFree != nil { dbGameRule := srvdata.PBDB_GameRuleMgr.GetData(dbGameFree.GetGameRule()) if dbGameRule != nil { gameId := int(dbGameRule.GetGameId()) sceneId := SceneMgrSingleton.GenOneHundredSceneId() params := common.CopySliceInt32ToInt64(dbGameRule.GetParams()) scene := SceneMgrSingleton.CreateScene(&CreateSceneParam{ RoomId: sceneId, SceneMode: common.SceneModePublic, Params: params, Platform: limitPlatform, GF: dbGameFree, }) if scene != nil { logger.Logger.Infof("Create hundred scene %v-%v success.", gameId, sceneId) scene.hp = this return scene } else { logger.Logger.Warnf("Create hundred scene %v-%v failed.", gameId, sceneId) } } else { logger.Logger.Errorf("Game rule data %v no found.", dbGameFree.GetGameRule()) } } else { logger.Logger.Errorf("Game free data %v no found.", id) } return nil } func (this *HundredSceneMgr) tryCreateRoom(plt string, id ...int32) { limitPlatform := PlatformMgrSingleton.GetPlatform(plt) if limitPlatform == nil || !limitPlatform.Isolated { limitPlatform = PlatformMgrSingleton.GetPlatform(DefaultPlatform) } if this.scenesOfPlatform[plt] == nil { this.scenesOfPlatform[plt] = make(map[int32]*Scene) } if limitPlatform.IdStr == DefaultPlatform { return } f := func(i int32) { if this.scenesOfPlatform[plt][i] != nil { return } gps := PlatformMgrSingleton.GetGameFree(plt, i) if !common.IsHundredType(gps.GetDbGameFree().GetGameType()) { return } scene := this.CreateNewScene(i, gps.GroupId, limitPlatform, gps.DbGameFree) if scene != nil { this.scenesOfPlatform[plt][i] = scene scene.hp = this logger.Logger.Infof("HundredSceneMgr PreCreateRoom Platform:%v Id:%v", plt, i) } } if len(id) == 0 { // 所有百人场 for _, vv := range srvdata.PBDB_GameFreeMgr.Datas.GetArr() { f(vv.GetId()) } } else { for _, v := range id { f(v) } } } // TryCreateRoom 预创建房间 func (this *HundredSceneMgr) TryCreateRoom() { if !model.GameParamData.HundredScenePreCreate { return } for _, v := range PlatformMgrSingleton.GetPlatforms() { this.tryCreateRoom(v.IdStr) } } func (this *HundredSceneMgr) OnPlatformChangeIsolated(p *Platform, isolated bool) { if p == nil { return } if isolated { //孤立 this.OnPlatformCreate(p) //预创建场景 } else { this.OnPlatformDestroy(p) } } func (this *HundredSceneMgr) GetPlatformSceneByGameFreeId(platform string, gameFreeIds []int32) []*Scene { platformName := DefaultPlatform platformData := PlatformMgrSingleton.GetPlatform(platform) if platformData != nil && platformData.Isolated { platformName = platformData.IdStr } else if platform != DefaultPlatform { platformData = PlatformMgrSingleton.GetPlatform(DefaultPlatform) } if platformData == nil { return nil } var scenes []*Scene for _, id := range gameFreeIds { gps := PlatformMgrSingleton.GetGameFree(platformData.IdStr, id) if gps != nil { if ss, ok := this.scenesOfPlatform[platformName]; ok { if s, exist := ss[id]; exist && s != nil { scenes = append(scenes, s) } } } } return scenes } func (this *HundredSceneMgr) GetPlatformScene(platform string, gameId int32) []*Scene { gameFreeIds := gameStateMgr.gameIds[gameId] gameScenes := this.GetPlatformSceneByGameFreeId(platform, gameFreeIds) if len(gameScenes) != len(gameFreeIds) { var createIds []int32 for _, gfi := range gameFreeIds { bFind := false for _, s := range gameScenes { if s.dbGameFree.GetId() == gfi { bFind = true break } } if !bFind { createIds = append(createIds, gfi) } } if len(createIds) > 0 { this.tryCreateRoom(platform, createIds...) gameScenes = this.GetPlatformSceneByGameFreeId(platform, gameFreeIds) } } return gameScenes } func (this *HundredSceneMgr) ModuleName() string { return "HundredSceneMgr" } func (this *HundredSceneMgr) Init() { //this.TryCreateRoom() } func (this *HundredSceneMgr) Update() { } func (this *HundredSceneMgr) Shutdown() { module.UnregisteModule(this) } func (this *HundredSceneMgr) OnPlatformCreate(p *Platform) { if model.GameParamData.HundredScenePreCreate { this.tryCreateRoom(p.IdStr) } } func (this *HundredSceneMgr) OnPlatformDestroy(p *Platform) { if p == nil { return } if ss, ok := this.scenesOfPlatform[p.IdStr]; ok { var ids []int for _, scene := range ss { ids = append(ids, scene.sceneId) } SceneMgrSingleton.SendGameDestroy(ids, true) } } func (this *HundredSceneMgr) OnPlatformChangeDisabled(p *Platform, disabled bool) { if p == nil { return } if disabled { this.OnPlatformDestroy(p) } } func (this *HundredSceneMgr) OnPlatformGameFreeUpdate(p *Platform, oldCfg, newCfg *webapi.GameFree) { if p == nil || newCfg == nil { return } if scenes, exist := this.scenesOfPlatform[p.IdStr]; exist { if s, ok := scenes[newCfg.DbGameFree.Id]; ok { s.SendGameDestroy(false) } } } func (this *HundredSceneMgr) OnGameGroupUpdate(oldCfg, newCfg *webapi.GameConfigGroup) { } func (this *HundredSceneMgr) OnPlatformDestroyByGameFreeId(p *Platform, gameFreeId int32) { if p == nil { return } if scenes, ok := this.scenesOfPlatform[p.IdStr]; ok { var ids []int for _, scene := range scenes { if scene.dbGameFree.Id == gameFreeId { ids = append(ids, scene.sceneId) } } SceneMgrSingleton.SendGameDestroy(ids, true) } } func init() { module.RegisteModule(HundredSceneMgrSingleton, time.Hour, 0) PlatformMgrSingleton.RegisterObserver(HundredSceneMgrSingleton) PlatformGameGroupMgrSington.RegisteObserver(HundredSceneMgrSingleton) }