468 lines
12 KiB
Go
468 lines
12 KiB
Go
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
|
||
}
|