game_sync/worldsrv/hundredscenemgr.go

398 lines
11 KiB
Go

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