game_sync/worldsrv/coinscenepool.go

468 lines
12 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"mongo.games.com/goserver/core/logger"
"mongo.games.com/game/model"
"mongo.games.com/game/proto"
gamehall_proto "mongo.games.com/game/protocol/gamehall"
server_proto "mongo.games.com/game/protocol/server"
"mongo.games.com/game/srvdata"
)
// CoinScenePool 房间池
type CoinScenePool struct {
platform string // 平台id
groupId int32 // 组id
id int32 // 场次id
dbGameFree *server_proto.DB_GameFree // 场次配置
dbGameRule *server_proto.DB_GameRule // 场次配置
scenes map[int]*Scene // 所有房间,房间id
players map[int32]struct{} // 玩家id
// 扩展数据
extraData interface{}
// 匹配规则
policy ICoinScenePool
}
func NewCoinScenePool(platform string, groupId int32, dbGameFree *server_proto.DB_GameFree) *CoinScenePool {
if dbGameFree == nil {
return nil
}
dbGameRule := srvdata.PBDB_GameRuleMgr.GetData(dbGameFree.GetGameRule())
if dbGameRule == nil {
logger.Logger.Errorf("Coin scene pool init failed,%v game rule data not find.", dbGameFree.GetGameRule())
return nil
}
csp := &CoinScenePool{
platform: platform,
groupId: groupId,
id: dbGameFree.GetId(),
dbGameFree: dbGameFree,
dbGameRule: dbGameRule,
scenes: make(map[int]*Scene),
players: make(map[int32]struct{}),
policy: new(BaseCoinScenePool), // 默认方式
}
policy := GetCoinScenePool(dbGameFree.GetGameId())
if policy != nil {
csp.policy = policy
csp.extraData = policy.New()
}
return csp
}
func (csp *CoinScenePool) GetPlayerNum() int32 {
return int32(len(csp.players))
}
func (csp *CoinScenePool) GetFakePlayerNum() int32 {
//if csp.dbGameFree != nil {
// correctNum := csp.dbGameFree.GetCorrectNum()
// correctRate := csp.dbGameFree.GetCorrectRate()
// count := csp.GetPlayerNum()
// return correctNum + count*correctRate/100 + csp.numDeviation
//}
return 0
}
// GetSceneType 获取场次id
func (csp *CoinScenePool) GetSceneType() int {
if csp.dbGameFree != nil {
return int(csp.dbGameFree.GetSceneType())
}
return 0
}
// CanInviteRob 能否邀请机器人
func (csp *CoinScenePool) CanInviteRob() bool {
if csp.dbGameFree != nil {
return csp.dbGameFree.GetBot() != 0
}
return false
}
// CanEnter 检查入场条件
func (csp *CoinScenePool) CanEnter(p *Player) gamehall_proto.OpResultCode {
if csp.dbGameFree == nil || p == nil {
return gamehall_proto.OpResultCode_OPRC_Error
}
//检测房间状态是否开启
gps := PlatformMgrSingleton.GetGameFree(p.Platform, csp.id)
if gps == nil || !gps.Status {
return gamehall_proto.OpResultCode_OPRC_RoomHadClosed
}
dbGameFree := csp.dbGameFree
if dbGameFree == nil {
return gamehall_proto.OpResultCode_OPRC_RoomHadClosed
}
//检查游戏次数限制
if !p.IsRob {
todayData, _ := p.GetDaliyGameData(int(dbGameFree.GetId()))
if dbGameFree.GetPlayNumLimit() != 0 &&
todayData != nil &&
todayData.GameTimes >= int64(dbGameFree.GetPlayNumLimit()) {
return gamehall_proto.OpResultCode_OPRC_RoomGameTimes
}
}
return csp.policy.CanEnter(csp, p)
}
// CanAudienceEnter 检查观众入场条件
func (csp *CoinScenePool) CanAudienceEnter(p *Player) gamehall_proto.OpResultCode {
if csp.dbGameFree == nil || p == nil {
return gamehall_proto.OpResultCode_OPRC_Error
}
//检测房间状态是否开启
gps := PlatformMgrSingleton.GetGameFree(p.Platform, csp.id)
if gps == nil {
return gamehall_proto.OpResultCode_OPRC_RoomHadClosed
}
dbGameFree := csp.dbGameFree
if dbGameFree == nil {
return gamehall_proto.OpResultCode_OPRC_RoomHadClosed
}
return csp.policy.CanAudienceEnter(csp, p)
}
// PlayerEnter 玩家进入房间池
func (csp *CoinScenePool) PlayerEnter(p *Player, roomId int32, exclude []int32, ischangeroom bool) gamehall_proto.OpResultCode {
if ret := csp.CanEnter(p); ret != gamehall_proto.OpResultCode_OPRC_Sucess {
logger.Logger.Warnf("(csp *CoinScenePool) PlayerEnter find snid:%v csp.CanEnter coin:%v ret:%v id:%v", p.SnId,
p.Coin, ret, csp.dbGameFree.GetId())
return ret
}
if p.scene != nil {
logger.Logger.Warnf("(csp *CoinScenePool) PlayerEnter[p.scene != nil] find snid:%v in scene:%v gameId:%v", p.SnId, p.scene.sceneId, p.scene.gameId)
return gamehall_proto.OpResultCode_OPRC_Error
}
var scene *Scene
// 进入房间
if roomId != 0 && (p.IsRob || p.GMLevel > 0 || csp.dbGameFree.GetCreateRoomNum() != 0) {
if s, ok := csp.scenes[int(roomId)]; ok {
if s != nil && !s.deleting { //指定房间id进入那么忽略掉排除id
if s.IsFull() {
return gamehall_proto.OpResultCode_OPRC_RoomIsFull
}
if sp, ok := s.sp.(*ScenePolicyData); ok {
if !s.starting || sp.EnterAfterStart {
scene = s
} else {
logger.Logger.Warnf("(csp *CoinScenePool) PlayerEnter[!s.starting || sp.EnterAfterStart] snid:%v sceneid:%v starting:%v EnterAfterStart:%v", p.SnId, s.sceneId, s.starting, sp.EnterAfterStart)
return gamehall_proto.OpResultCode_OPRC_Error
}
}
}
} else {
logger.Logger.Warnf("(csp *CoinScenePool) PlayerEnter(robot:%v,roomid:%v, exclude:%v, ischangeroom:%v) no found scene", p.SnId, roomId, exclude, ischangeroom)
return gamehall_proto.OpResultCode_OPRC_Error
}
}
if scene == nil {
var ret gamehall_proto.OpResultCode
ret, scene = csp.policy.PlayerEnter(csp, p, exclude, ischangeroom)
if ret != gamehall_proto.OpResultCode_OPRC_Sucess {
return ret
}
}
if scene == nil {
scene = csp.policy.NewScene(csp, p)
if scene != nil {
csp.scenes[scene.sceneId] = scene
scene.csp = csp
} else {
logger.Logger.Errorf("Create %v scene failed.", csp.id)
}
}
if scene != nil {
if p.EnterScene(scene, ischangeroom, -1) {
csp.OnPlayerEnter(p, scene)
return gamehall_proto.OpResultCode_OPRC_Sucess
}
}
logger.Logger.Warnf("(csp *CoinScenePool) PlayerEnter snid:%v not found scene", p.SnId)
return gamehall_proto.OpResultCode_OPRC_SceneServerMaintain
}
// AudienceEnter 观众入场
func (csp *CoinScenePool) AudienceEnter(p *Player, roomId int32, exclude []int32, ischangeroom bool) gamehall_proto.OpResultCode {
if ret := csp.CanAudienceEnter(p); ret != gamehall_proto.OpResultCode_OPRC_Sucess {
logger.Logger.Warnf("(csp *CoinScenePool) AudienceEnter find snid:%v csp.CanEnter coin:%v ret:%v id:%v", p.SnId, p.Coin, ret, csp.dbGameFree.GetId())
return ret
}
if p.scene != nil {
logger.Logger.Warnf("(csp *CoinScenePool) AudienceEnter[p.scene != nil] find snid:%v in scene:%v gameId:%v", p.SnId, p.scene.sceneId, p.scene.gameId)
return gamehall_proto.OpResultCode_OPRC_Error
}
var scene *Scene
if roomId != 0 {
if s, ok := csp.scenes[int(roomId)]; ok {
if s != nil && !s.deleting /*&& s.sceneId != int(exclude)*/ {
scene = s
} else {
logger.Logger.Warnf("(csp *CoinScenePool) AudienceEnter[!s.starting || sp.EnterAfterStart] snid:%v sceneid:%v starting:%v EnterAfterStart:%v", p.SnId, s.sceneId, s.starting)
}
}
}
if scene == nil {
var ret gamehall_proto.OpResultCode
ret, scene = csp.policy.AudienceEnter(csp, p, exclude, ischangeroom)
if ret != gamehall_proto.OpResultCode_OPRC_Sucess {
return ret
}
}
if scene == nil {
return gamehall_proto.OpResultCode_OPRC_NoFindDownTiceRoom
}
if scene != nil {
// 预创建房间检查观众数量
if scene.IsPreCreateScene() && scene.GetAudienceCnt() >= model.GameParamData.MaxAudienceNum {
return gamehall_proto.OpResultCode_OPRC_RoomIsFull
}
if scene.AudienceEnter(p, ischangeroom) {
csp.OnPlayerEnter(p, scene)
return gamehall_proto.OpResultCode_OPRC_Sucess
}
}
logger.Logger.Warnf("(csp *CoinScenePool) PlayerEnter snid:%v not found scene", p.SnId)
return gamehall_proto.OpResultCode_OPRC_NoFindDownTiceRoom
}
// OnPlayerEnter 玩家进入房间完成
func (csp *CoinScenePool) OnPlayerEnter(p *Player, scene *Scene) {
csp.players[p.SnId] = struct{}{}
csp.policy.OnPlayerEnter(csp, p, scene)
}
// PlayerLeave 玩家离开房间
func (csp *CoinScenePool) PlayerLeave(p *Player, reason int) bool {
if p.scene == nil {
return true
}
if p.scene.csp != csp && p.scene == csp.scenes[p.scene.sceneId] {
logger.Logger.Error("bug")
}
if p.scene.csp != csp {
return false
}
if p.scene != csp.scenes[p.scene.sceneId] {
logger.Logger.Error("bug")
}
s, ok := csp.scenes[p.scene.sceneId]
if !ok || s == nil {
return false
}
if !s.HasPlayer(p) {
return false
}
if !csp.policy.PlayerLeave(csp, p, reason) {
return false
}
s.PlayerLeave(p, reason)
logger.Logger.Tracef("(csp *CoinScenePool) PlayerLeave snid:%v in scene:%v", p.SnId, s.sceneId)
csp.policy.OnPlayerLeave(csp, s, p)
csp.OnPlayerLeave(s, p)
return true
}
// AudienceLeave 观众离开房间
func (csp *CoinScenePool) AudienceLeave(p *Player, reason int) bool {
if p.scene == nil {
return true
}
if p.scene.csp != csp {
return false
}
s, ok := csp.scenes[p.scene.sceneId]
if !ok || s == nil {
return false
}
if !s.HasAudience(p) {
return false
}
if !csp.policy.AudienceLeave(csp, p, reason) {
return false
}
s.AudienceLeave(p, reason)
logger.Logger.Tracef("(csp *CoinScenePool) AudienceLeave snid:%v in scene:%v", p.SnId, s.sceneId)
csp.policy.OnPlayerLeave(csp, s, p)
csp.OnPlayerLeave(s, p)
return true
}
// OnPlayerLeave 离开房间完成
func (csp *CoinScenePool) OnPlayerLeave(s *Scene, p *Player) {
if s == nil || p == nil {
return
}
delete(csp.players, p.SnId)
// 玩家离开结算空房间的私人房
if s.IsPrivateScene() {
if s.IsEmpty() {
s.ForceDelete(false)
}
return
}
// 解散空房间并且房间数量大于预创建房间数量
if s.IsPreCreateScene() {
if s.IsEmpty() {
var hasCnt int
for _, scene := range csp.scenes {
if s.limitPlatform.IdStr == scene.limitPlatform.IdStr {
hasCnt++
}
}
if hasCnt > int(csp.dbGameFree.GetCreateRoomNum()) {
s.ForceDelete(false)
}
}
}
}
// OnDestroyScene 解散房间
// todo 是否需要优化
func (csp *CoinScenePool) OnDestroyScene(sceneId int) {
scene, ok := csp.scenes[sceneId]
if !ok {
return
}
for id := range scene.players {
player := PlayerMgrSington.GetPlayerBySnId(id)
if player != nil {
if !player.IsRob {
ctx := scene.GetPlayerGameCtx(player.SnId)
if ctx != nil {
//发送一个探针,等待ack后同步金币
player.TryRetrieveLostGameCoin(sceneId)
}
}
}
}
for id := range scene.audiences {
player := PlayerMgrSington.GetPlayerBySnId(id)
if player != nil {
if !player.IsRob {
ctx := scene.GetPlayerGameCtx(player.SnId)
if ctx != nil {
//发送一个探针,等待ack后同步金币
player.TryRetrieveLostGameCoin(sceneId)
}
}
}
}
csp.policy.OnDestroyScene(csp, sceneId)
scene.csp = nil // 解除关联
delete(csp.scenes, sceneId)
}
// PreCreateRoom 预创建房间
func (csp *CoinScenePool) PreCreateRoom() {
if csp.platform == DefaultPlatform {
return
}
preCreateNum := int(csp.dbGameFree.GetCreateRoomNum())
if preCreateNum == 0 || model.GameParamData.ClosePreCreateRoom {
return
}
if p := PlatformMgrSingleton.GetPlatform(csp.platform); p == nil || p.Disable {
return
}
var num int
for _, scene := range csp.scenes {
if scene.limitPlatform.IdStr == csp.platform {
num++
}
}
if num < preCreateNum {
inc := preCreateNum - num
for i := 0; i < inc; i++ {
scene := csp.policy.NewPreCreateScene(csp)
if scene != nil {
csp.scenes[scene.sceneId] = scene
scene.csp = csp
}
}
}
}
// ListRoom 房间列表
func (csp *CoinScenePool) ListRoom(p *Player) bool {
if p.scene != nil {
logger.Logger.Warnf("(csp *CoinScenePool) PlayerListRoom[p.scene != nil] find snid:%v in scene:%v gameId:%v", p.SnId, p.scene.sceneId, p.scene.gameId)
return false
}
csp.PreCreateRoom()
if len(csp.scenes) == 0 {
return false
}
pack := &gamehall_proto.SCCoinSceneListRoom{
Id: csp.dbGameFree.Id,
LimitCoin: csp.dbGameFree.LimitCoin,
MaxCoinLimit: csp.dbGameFree.MaxCoinLimit,
BaseScore: csp.dbGameFree.BaseScore,
MaxScore: csp.dbGameFree.MaxChip,
OtherIntParams: csp.dbGameFree.OtherIntParams,
}
maxPlayerNum := 0
for sceneId, s := range csp.scenes {
data := &gamehall_proto.CoinSceneInfo{
SceneId: proto.Int(sceneId),
PlayerNum: proto.Int(len(s.players)),
}
pack.Datas = append(pack.Datas, data)
maxPlayerNum = s.playerNum
}
pack.MaxPlayerNum = proto.Int(maxPlayerNum)
proto.SetDefaults(pack)
p.SendToClient(int(gamehall_proto.CoinSceneGamePacketID_PACKET_SC_COINSCENE_LISTROOM), pack)
return true
}
// GetHasTruePlayerSceneCnt 有真人的房间数量
func (csp *CoinScenePool) GetHasTruePlayerSceneCnt() int {
cnt := 0
for _, s := range csp.scenes {
if s.GetTruePlayerCnt() != 0 {
cnt++
}
}
return cnt
}