game_sync/worldsrv/scene.go

972 lines
27 KiB
Go
Raw 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 (
"math/rand"
"strconv"
"time"
rawproto "google.golang.org/protobuf/proto"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/netlib"
"mongo.games.com/goserver/srvlib"
srvlibproto "mongo.games.com/goserver/srvlib/protocol"
"mongo.games.com/game/common"
"mongo.games.com/game/gamerule/tienlen"
"mongo.games.com/game/model"
"mongo.games.com/game/proto"
hallproto "mongo.games.com/game/protocol/gamehall"
serverproto "mongo.games.com/game/protocol/server"
"mongo.games.com/game/srvdata"
)
const (
// PlayerHistoryModel .
PlayerHistoryModel = iota + 1
// BIGWIN_HISTORY_MODEL .
BIGWIN_HISTORY_MODEL
// GameHistoryModel .
GameHistoryModel
)
type PlayerGameCtx struct {
takeCoin int64 //进房时携带的金币量
enterTs int64 //进入时间
totalConvertibleFlow int64 //进房时玩家身上的总流水
}
// Scene 场景(房间)
// todo 结构优化
type Scene struct {
sceneId int // 场景id
gameId int // 游戏id
gameMode int // 游戏模式(玩法)
sceneMode int // 房间模式,参考common.SceneMode_XXX
params []int64 // 场景参数
playerNum int // 房间最大人数
robotNum int // 机器人数量
robotLimit int // 最大限制机器人数量
preInviteRobNum int // 准备邀请机器人的数量
creator int32 // 创建者账号id
replayCode string // 回放码
currRound int32 // 当前第几轮
totalRound int32 // 总共几轮小于等于0表示无限轮
cycleTimes int32 // 循环次数
deleting bool // 正在删除
starting bool // 正在开始
closed bool // 房间已关闭
force bool // 强制删除
players map[int32]*Player // 玩家
audiences map[int32]*Player // 观众
seats [9]*Player // 座位
gameSess *GameSession // 所在gameserver
sp ScenePolicy // 场景上的一些业务策略
createTime time.Time // 创建时间
lastTime time.Time // 最后活跃时间
startTime time.Time // 开始时间
applyTimes map[int32]int32 // 申请坐下次数
limitPlatform *Platform // 限制平台
groupId int32 // 组id
hallId int32 // 厅id
dbGameFree *serverproto.DB_GameFree // 场次配置
gameCtx map[int32]*PlayerGameCtx // 进入房间的环境
BaseScore int32 // 游戏底分,优先级,创建参数>本地配置>场次配置
SceneState int32 // 房间当前状态
State int32 // 当前游戏状态后期放到ScenePolicy里去处理
StateTs int64 // 切换到当前状态的时间
StateSec int32 // 押注状态的秒数
Channel []string // 客户端类型
*serverproto.CustomParam // 房卡场参数
*serverproto.MatchParam // 比赛场参数
csp *CoinScenePool // 所在场景池
hp *HundredSceneMgr // 百人场房间池
}
// NewScene 创建房间
func NewScene(args *CreateSceneParam) *Scene {
gameId := int(args.GF.GetGameId())
gameMode := int(args.GF.GetGameMode())
gameFreeId := args.GF.GetId()
sp := GetScenePolicy(gameId, gameMode)
if sp == nil {
logger.Logger.Errorf("NewScene sp == nil, gameId=%v gameMode=%v", gameId, gameMode)
return nil
}
s := &Scene{
sceneId: args.RoomId,
hallId: gameFreeId,
playerNum: int(args.PlayerNum),
creator: args.CreateId,
gameId: gameId,
gameMode: gameMode,
sceneMode: args.SceneMode,
params: args.Params,
cycleTimes: int32(args.CycleTimes),
players: make(map[int32]*Player),
audiences: make(map[int32]*Player),
gameSess: args.GS,
sp: sp,
createTime: time.Now(),
limitPlatform: args.Platform,
groupId: 0,
gameCtx: make(map[int32]*PlayerGameCtx), //进入房间的环境
dbGameFree: args.GF,
currRound: 0,
totalRound: int32(args.TotalRound),
BaseScore: args.BaseScore,
Channel: args.Channel,
CustomParam: args.CustomParam,
MatchParam: args.MatchParam,
}
// 最大房间人数
if s.playerNum <= 0 {
s.playerNum = sp.GetPlayerNum()
}
// 底分
if s.BaseScore <= 0 {
s.BaseScore = int32(sp.GetBaseScore())
}
if s.BaseScore <= 0 {
s.BaseScore = s.dbGameFree.GetBaseScore()
}
if s.cycleTimes <= 0 {
s.cycleTimes = 1
}
s.lastTime = s.createTime
s.replayCode = SceneMgrSingleton.AllocReplayCode()
if s.dbGameFree.GetMatchMode() == 0 {
s.RandRobotCnt()
}
s.sp.OnStart(s)
return s
}
func (this *Scene) RebindPlayerSnId(oldSnId, newSnId int32) {
if this.creator == oldSnId {
this.creator = newSnId
}
if p, exist := this.players[oldSnId]; exist {
delete(this.players, oldSnId)
this.players[newSnId] = p
}
if p, exist := this.audiences[oldSnId]; exist {
delete(this.audiences, oldSnId)
this.audiences[newSnId] = p
}
}
func (this *Scene) RobotIsLimit() bool {
if this.robotLimit != 0 {
if this.robotNum >= this.robotLimit {
return true
}
}
return false
}
func (this *Scene) GetPlayerGameCtx(snid int32) *PlayerGameCtx {
if ctx, exist := this.gameCtx[snid]; exist {
return ctx
}
return nil
}
// PlayerEnter 玩家进入场景
// todo 优化
func (this *Scene) PlayerEnter(p *Player, pos int, ischangeroom bool) bool {
logger.Logger.Infof("(this *Scene:%v) PlayerEnter(%v, %v) ", this.sceneId, p.SnId, pos)
// 机器人数量限制
if p.IsRobot() && this.robotLimit != 0 {
if this.robotNum+1 > this.robotLimit {
logger.Logger.Warnf("(this *Scene:%v) PlayerEnter(%v) robot num limit(%v)", this.sceneId, p.SnId, this.robotLimit)
return false
}
}
// 非百人,设置座位
if !this.IsHundredScene() {
if pos != -1 {
if this.seats[pos] != nil {
for i := 0; i < this.playerNum; i++ {
if this.seats[i] == nil {
p.pos = i
this.seats[i] = p
break
}
}
} else {
p.pos = pos
this.seats[pos] = p
}
} else {
for i := 0; i < this.playerNum; i++ {
if this.seats[i] == nil {
p.pos = i
this.seats[i] = p
break
}
}
}
}
// 如果正在等待比赛,退赛
if !this.IsMatchScene() {
isWaiting, tmid := TournamentMgr.IsMatchWaiting(p.Platform, p.SnId)
if isWaiting {
TournamentMgr.CancelSignUp(p.Platform, tmid, p.SnId)
}
}
p.scene = this
this.players[p.SnId] = p
this.gameSess.AddPlayer(p)
takeCoin := p.Coin
leaveCoin := int64(0)
gameTimes := rand.Int31n(100)
var matchParams []int32 //排名、段位、假snid、假角色、假皮肤
if this.IsMatchScene() && p.matchCtx != nil {
takeCoin = int64(p.matchCtx.grade)
matchParams = append(matchParams, p.matchCtx.rank) //排名
if p.IsRob {
matchParams = append(matchParams, p.matchCtx.copyLv) //机器人随机段位
} else {
matchParams = append(matchParams, 1) //段位默认值
}
matchParams = append(matchParams, p.matchCtx.copySnid) //假snid
matchParams = append(matchParams, p.matchCtx.copyRoleId) //假RoleId
matchParams = append(matchParams, p.matchCtx.copySkinId) //假SkinId
}
if this.IsCustom() {
takeCoin = 1000
}
if p.IsRob && !this.IsMatchScene() && !this.IsCustom() {
if this.dbGameFree != nil { //机器人携带金币动态调整
gps := PlatformMgrSingleton.GetGameFree(this.limitPlatform.IdStr, this.dbGameFree.GetId())
if gps != nil {
dbGameFree := gps.DbGameFree
flag := false
if common.IsLocalGame(this.gameId) {
baseScore := this.BaseScore
arrs := srvdata.PBDB_CreateroomMgr.Datas.Arr
tmpIds := []int32{}
for i := 0; i < len(arrs); i++ {
arr := arrs[i]
if int(arr.GameId) == this.gameId && arr.GameSite == this.dbGameFree.GetSceneType() {
betRange := arr.GetBetRange()
if len(betRange) == 0 {
continue
}
for j := 0; j < len(betRange); j++ {
if betRange[j] == baseScore && len(arr.GetGoldRange()) > 0 && arr.GetGoldRange()[0] != 0 {
tmpIds = append(tmpIds, arr.GetId())
break
}
}
}
}
if len(tmpIds) > 0 {
randId := common.RandInt32Slice(tmpIds)
crData := srvdata.PBDB_CreateroomMgr.GetData(randId)
if crData != nil {
goldRange := crData.GetGoldRange()
if len(goldRange) == 2 {
takeCoin = common.RandFromRangeInt64(int64(goldRange[0]), int64(goldRange[1]))
flag = true
} else if len(goldRange) == 1 {
takeCoin = common.RandFromRangeInt64(int64(goldRange[0]), 2*int64(goldRange[0]))
flag = true
}
leaveCoin = int64(goldRange[0])
for _, id := range tmpIds {
tmp := srvdata.PBDB_CreateroomMgr.GetData(id).GetGoldRange()
if int64(tmp[0]) < leaveCoin && tmp[0] != 0 {
leaveCoin = int64(tmp[0])
}
}
}
} else {
logger.Logger.Warn("gameId: ", this.gameId, " gameSite: ", this.dbGameFree.GetSceneType(), " baseScore: ", baseScore)
}
if leaveCoin > takeCoin {
logger.Logger.Warn("robotSnId: ", p.SnId, " baseScore: ", baseScore, " takeCoin: ", takeCoin, " leaveCoin: ", leaveCoin)
}
if takeCoin > p.Coin {
p.Coin = takeCoin
}
}
if !flag {
takerng := dbGameFree.GetRobotTakeCoin()
if len(takerng) >= 2 && takerng[1] > takerng[0] {
if takerng[0] < dbGameFree.GetLimitCoin() {
takerng[0] = dbGameFree.GetLimitCoin()
}
takeCoin = int64(common.RandInt(int(takerng[0]), int(takerng[1])))
} else {
maxlimit := int64(dbGameFree.GetMaxCoinLimit())
if maxlimit != 0 && p.Coin > maxlimit {
logger.Logger.Trace("Player coin:", p.Coin)
//在下限和上限之间随机并对其的100的整数倍
takeCoin = int64(common.RandInt(int(dbGameFree.GetLimitCoin()), int(maxlimit)))
logger.Logger.Trace("Take coin:", takeCoin)
}
if maxlimit == 0 && this.IsCoinScene() {
maxlimit = int64(common.RandInt(10, 50)) * int64(dbGameFree.GetLimitCoin())
takeCoin = int64(common.RandInt(int(dbGameFree.GetLimitCoin()), int(maxlimit)))
logger.Logger.Trace("Take coin:", takeCoin)
}
}
takeCoin = takeCoin / 100 * 100
//离场金币
leaverng := dbGameFree.GetRobotLimitCoin()
if len(leaverng) >= 2 {
leaveCoin = int64(leaverng[0] + rand.Int63n(leaverng[1]-leaverng[0]))
}
}
// 象棋积分
chessScore := dbGameFree.GetChessScoreParams()
if len(chessScore) == 2 {
p.ChessGrade = int64(common.RandInt(int(chessScore[0]), int(chessScore[1])))
}
if takeCoin > p.Coin {
p.Coin = takeCoin
}
}
}
}
if p.IsRob {
this.robotNum++
p.RobotRandName()
p.RandRobotVip(this)
//随机机器人宠物技能等级
p.RandRobotPetSkillLevel()
name := this.GetSceneName()
logger.Logger.Tracef("(this *Scene) PlayerEnter(%v) robot(%v) robotlimit(%v)", name, this.robotNum, this.robotLimit)
}
data, err := p.MarshalData()
if err == nil {
var gateSid int64
if p.gateSess != nil {
if srvInfo, ok := p.gateSess.GetAttribute(srvlib.SessionAttributeServerInfo).(*srvlibproto.SSSrvRegiste); ok && srvInfo != nil {
sessionId := srvlib.NewSessionIdEx(srvInfo.GetAreaId(), srvInfo.GetType(), srvInfo.GetId(), 0)
gateSid = sessionId.Get()
}
}
msg := &serverproto.WGPlayerEnter{
Sid: proto.Int64(p.sid),
SnId: proto.Int32(p.SnId),
GateSid: proto.Int64(gateSid),
SceneId: proto.Int(this.sceneId),
PlayerData: data,
IsLoaded: proto.Bool(ischangeroom),
IParams: p.MarshalIParam(),
SParams: p.MarshalSParam(),
CParams: p.MarshalCParam(),
}
p.takeCoin = takeCoin
p.sceneCoin = takeCoin
p.enterts = time.Now()
if !p.IsRob { //保存下进入时的环境
this.gameCtx[p.SnId] = &PlayerGameCtx{
takeCoin: p.takeCoin,
enterTs: p.enterts.Unix(),
totalConvertibleFlow: p.TotalConvertibleFlow,
}
this.lastTime = time.Now()
}
msg.TakeCoin = proto.Int64(takeCoin)
msg.ExpectLeaveCoin = proto.Int64(leaveCoin)
msg.ExpectGameTimes = proto.Int32(gameTimes)
msg.Pos = proto.Int(p.pos)
if matchParams != nil {
for _, param := range matchParams {
msg.MatchParams = append(msg.MatchParams, param)
}
}
// 道具
dbItemArr := srvdata.GameItemMgr.GetArr(p.Platform)
if dbItemArr != nil {
msg.Items = make(map[int32]int64)
for _, dbItem := range dbItemArr {
msg.Items[dbItem.Id] = 0
itemInfo := BagMgrSingleton.GetItem(p.SnId, dbItem.Id)
if itemInfo != nil {
msg.Items[dbItem.Id] = itemInfo.ItemNum
}
}
}
// 排位积分
ret := RankMgrSingleton.GetPlayerSeason(p.SnId)
if ret != nil && ret.PlayerRankSeason != nil {
msg.RankScore = make(map[int32]int64)
for k, v := range ret.RankType {
if v != nil {
msg.RankScore[k] = v.Score
}
}
}
if p.IsRobot() {
msg.RankScore = make(map[int32]int64)
rankScore := this.dbGameFree.GetRankScoreParams()
if len(rankScore) == 2 {
switch {
case this.dbGameFree.GameDif == common.GameDifTienlen:
msg.RankScore[tienlen.RankType] = int64(common.RandInt(int(rankScore[0]), int(rankScore[1])))
}
}
}
proto.SetDefaults(msg)
this.SendToGame(int(serverproto.SSPacketID_PACKET_WG_PLAYERENTER), msg)
logger.Logger.Tracef("SSPacketID_PACKET_WG_PLAYERENTER Scene:%v ;PlayerEnter(%v, %v)", this.sceneId, p.SnId, pos)
FirePlayerEnterScene(p, this)
return true
} else {
logger.Logger.Warnf("(this *Scene:%v) PlayerEnter(%v, %v) Marshal player data error %v", this.sceneId, p.SnId, pos, err)
this.DelPlayer(p)
return false
}
}
func (this *Scene) AudienceEnter(p *Player, ischangeroom bool) bool {
logger.Logger.Infof("(this *Scene:%v) AudienceEnter(%v) ", this.sceneId, p.SnId)
p.scene = this
takeCoin := p.Coin
p.takeCoin = takeCoin
this.audiences[p.SnId] = p
this.gameSess.AddPlayer(p)
data, err := p.MarshalData()
if err != nil {
return false
}
var gateSid int64
if p.gateSess != nil {
if srvInfo, ok := p.gateSess.GetAttribute(srvlib.SessionAttributeServerInfo).(*srvlibproto.SSSrvRegiste); ok && srvInfo != nil {
sessionId := srvlib.NewSessionIdEx(srvInfo.GetAreaId(), srvInfo.GetType(), srvInfo.GetId(), 0)
gateSid = sessionId.Get()
}
}
msg := &serverproto.WGPlayerEnter{
Sid: proto.Int64(p.sid),
SnId: proto.Int32(p.SnId),
GateSid: proto.Int64(gateSid),
SceneId: proto.Int(this.sceneId),
PlayerData: data,
TakeCoin: takeCoin,
IsLoaded: proto.Bool(ischangeroom),
IsQM: false,
IParams: p.MarshalIParam(),
SParams: p.MarshalSParam(),
CParams: p.MarshalCParam(),
}
if !p.IsRob { //保存下进入时的环境
p.enterts = time.Now()
this.gameCtx[p.SnId] = &PlayerGameCtx{
takeCoin: p.takeCoin,
enterTs: p.enterts.Unix(),
}
this.lastTime = time.Now()
}
this.SendToGame(int(serverproto.SSPacketID_PACKET_WG_AUDIENCEENTER), msg)
return true
}
func (this *Scene) lastScene(p *Player) {
// 记录玩家在每个游戏场次最后进入的房间号
// 只记录金币场
if this.IsCoinScene() {
const MINHOLD = 10
const MAXHOLD = 20
holdCnt := MINHOLD
if this.csp != nil {
holdCnt = this.csp.GetHasTruePlayerSceneCnt() + 2
if holdCnt < MINHOLD {
holdCnt = MINHOLD
}
if holdCnt > MAXHOLD {
holdCnt = MAXHOLD
}
}
if p.lastSceneId == nil {
p.lastSceneId = make(map[int32][]int32)
}
id := this.dbGameFree.GetId()
if sceneIds, exist := p.lastSceneId[id]; exist {
if !common.InSliceInt32(sceneIds, int32(this.sceneId)) {
sceneIds = append(sceneIds, int32(this.sceneId))
cnt := len(sceneIds)
if cnt > holdCnt {
sceneIds = sceneIds[cnt-holdCnt:]
}
p.lastSceneId[id] = sceneIds
}
} else {
p.lastSceneId[id] = []int32{int32(this.sceneId)}
}
}
}
func (this *Scene) DelPlayer(p *Player) bool {
if p.scene != this {
roomId := 0
if p.scene != nil {
roomId = p.scene.sceneId
}
logger.Logger.Errorf("DelPlayer found player:%v in room:%v but room:%v", p.SnId, roomId, this.sceneId)
}
if this.gameSess != nil {
this.gameSess.DelPlayer(p)
}
// 玩家离开游戏
if _, ok := this.players[p.SnId]; ok {
delete(this.players, p.SnId)
if p.IsRobot() {
this.robotNum--
}
// 记录玩家最近玩游戏的房间
this.lastScene(p)
// 玩家最后所在游戏
p.LastGameId = int(this.dbGameFree.GetGameId())
}
// 观众离开游戏
if _, ok := this.audiences[p.SnId]; ok {
delete(this.audiences, p.SnId)
}
for k, v := range this.seats {
if v != nil && v.SnId == p.SnId {
p.pos = -1
this.seats[k] = nil
break
}
}
if !p.IsRob {
delete(this.gameCtx, p.SnId)
}
p.scene = nil
if !p.IsRob {
this.lastTime = time.Now()
}
return true
}
// PlayerLeave 玩家离开
func (this *Scene) PlayerLeave(p *Player, reason int) {
logger.Logger.Infof("(this *Scene:%v) PlayerLeave(%v, %v) ", this.sceneId, p.SnId, reason)
pack := &hallproto.SCQuitGame{
Id: this.dbGameFree.Id,
Reason: proto.Int(reason),
}
pack.OpCode = hallproto.OpResultCode_Game_OPRC_Sucess_Game
p.SendToClient(int(hallproto.GameHallPacketID_PACKET_SC_QUITGAME), pack)
logger.Logger.Tracef("SCQuitGame: %v, %v", p.SnId, pack)
this.DelPlayer(p)
}
// AudienceLeave 观众离开
func (this *Scene) AudienceLeave(p *Player, reason int) {
logger.Logger.Infof("(this *Scene:%v) AudienceLeave(%v, %v) ", this.sceneId, p.SnId, reason)
pack := &hallproto.SCLeaveRoom{
Reason: proto.Int(reason),
OpRetCode: hallproto.OpResultCode_Game_OPRC_Sucess_Game,
Mode: proto.Int(0),
RoomId: proto.Int(this.sceneId),
}
p.SendToClient(int(hallproto.GameHallPacketID_PACKET_SC_LEAVEROOM), pack)
logger.Logger.Tracef("AudienceLeave SCLeaveRoom: %v, %v", p.SnId, pack)
this.DelPlayer(p)
}
// AudienceSit 观众坐下
func (this *Scene) AudienceSit(p *Player, pos int) bool {
logger.Logger.Infof("(this *Scene:%v) AudienceSit(%v, %v, %v) ", this.sceneId, p.SnId, pos, this.dbGameFree.GetId())
if _, exist := this.audiences[p.SnId]; exist {
delete(this.audiences, p.SnId)
p.scene = this
p.takeCoin = p.Coin
this.players[p.SnId] = p
msg := &serverproto.WGAudienceSit{
SnId: proto.Int32(p.SnId),
TakeCoin: p.Coin,
SceneId: proto.Int(this.sceneId),
Pos: proto.Int(pos),
}
this.SendToGame(int(serverproto.SSPacketID_PACKET_WG_AUDIENCESIT), msg)
if !p.IsRob {
this.lastTime = time.Now()
}
return true
}
return false
}
func (this *Scene) HasPlayer(p *Player) bool {
if _, exist := this.players[p.SnId]; exist {
return true
}
return false
}
func (this *Scene) HasAudience(p *Player) bool {
if _, exist := this.audiences[p.SnId]; exist {
return true
}
return false
}
func (this *Scene) GetPlayer(id int32) *Player {
if p, exist := this.players[id]; exist {
return p
}
return nil
}
func (this *Scene) GetAudience(id int32) *Player {
if p, exist := this.audiences[id]; exist {
return p
}
return nil
}
func (this *Scene) GetPlayerPos(snId int32) int {
for index, value := range this.seats {
if value == nil {
continue
}
if value.SnId == snId {
return index
}
}
return -1
}
func (this *Scene) GetPlayerCnt() int {
return len(this.players)
}
func (this *Scene) GetAudienceCnt() int {
return len(this.audiences)
}
// IsFull 是否满人
// 不包含观众
func (this *Scene) IsFull() bool {
return this.GetPlayerCnt() >= this.playerNum
}
func (this *Scene) IsEmpty() bool {
return this.GetPlayerCnt() == 0
}
func (this *Scene) AllIsRobot() bool {
return len(this.players) == this.robotNum
}
// OnClose 房间销毁
func (this *Scene) OnClose() {
scDestroyRoom := &hallproto.SCDestroyRoom{
RoomId: proto.Int(this.sceneId),
OpRetCode: hallproto.OpResultCode_Game_OPRC_Sucess_Game,
IsForce: proto.Int(1),
}
this.Broadcast(int(hallproto.GameHallPacketID_PACKET_SC_DESTROYROOM), scDestroyRoom, 0)
this.deleting = true
this.closed = true
this.sp.OnStop(this)
for _, p := range this.players {
this.DelPlayer(p)
}
for _, p := range this.audiences {
this.DelPlayer(p)
}
this.players = nil
this.audiences = nil
this.gameSess = nil
}
func (this *Scene) SendToGame(packetId int, pack interface{}) bool {
if this.gameSess != nil {
this.gameSess.Send(packetId, pack)
return true
}
return false
}
func (this *Scene) SendToClient(packetId int, pack interface{}, excludeId int32) {
for v, value := range this.players {
if v == excludeId {
continue
}
value.SendToClient(packetId, pack)
}
}
func (this *Scene) IsLongTimeInactive() bool {
tNow := time.Now()
// 房间没有真人,没有观众,长时间没有真人进出房间
if this.GetTruePlayerCnt() == 0 && this.GetAudienceCnt() == 0 && tNow.Sub(this.lastTime) > time.Second*time.Duration(model.GameParamData.SceneMaxIdle) {
return true
}
return false
}
func (this *Scene) SendGameDestroy(isGrace bool) {
if !isGrace {
this.deleting = true
this.force = true
}
pack := &serverproto.WGDestroyScene{
Ids: []int64{int64(this.sceneId)},
IsGrace: isGrace,
}
this.SendToGame(int(serverproto.SSPacketID_PACKET_WG_DESTROYSCENE), pack)
logger.Logger.Tracef("WG_DESTROYSCENE: %v", pack)
}
// IsMatchScene 比赛场
func (this *Scene) IsMatchScene() bool {
return this.sceneId >= common.MatchSceneStartId && this.sceneId < common.MatchSceneMaxId
}
// IsCoinScene 金币场
func (this *Scene) IsCoinScene() bool {
return this.sceneId >= common.CoinSceneStartId && this.sceneId < common.CoinSceneMaxId
}
// IsHundredScene 百人场
func (this *Scene) IsHundredScene() bool {
return this.sceneId >= common.HundredSceneStartId && this.sceneId < common.HundredSceneMaxId
}
// IsPrivateScene 私人房间
func (this *Scene) IsPrivateScene() bool {
return this.sceneId >= common.PrivateSceneStartId && this.sceneId < common.PrivateSceneMaxId || this.sceneMode == common.SceneMode_Private
}
// IsCustom 房卡场房间
func (this *Scene) IsCustom() bool {
if this.dbGameFree == nil {
return false
}
return this.dbGameFree.IsCustom > 0
}
// IsSceneMode 房间模式
func (this *Scene) IsSceneMode(mode int) bool {
return this.sceneMode == mode
}
// IsRankMatch 排位赛
func (this *Scene) IsRankMatch() bool {
if this.dbGameFree == nil {
return false
}
return this.dbGameFree.RankType > 0
}
// IsTestScene 试玩场
func (this *Scene) IsTestScene() bool {
if this.dbGameFree != nil {
return this.dbGameFree.GetSceneType() == -1
}
return false
}
func (this *Scene) GetSceneName() string {
if this.dbGameFree != nil {
return this.dbGameFree.GetName() + this.dbGameFree.GetTitle()
}
return "[unknow scene name]"
}
func (this *Scene) RandRobotCnt() {
if this.dbGameFree != nil {
number := this.dbGameFree.GetRobotNumRng()
if len(number) >= 2 {
if number[1] == number[0] {
this.robotLimit = int(number[0])
} else {
if number[1] < number[0] {
number[1], number[0] = number[0], number[1]
}
this.robotLimit = int(number[1]) //int(number[0] + rand.Int31n(number[1]-number[0]) + 1)
}
}
return
}
}
func (this *Scene) IsPlatform(platform string) bool {
if platform == "0" || platform == this.limitPlatform.IdStr {
return true
}
return false
}
func (this *Scene) GetWhitePlayerCnt() int {
var cnt int
for _, p := range this.players {
if p.WBLevel > 0 {
cnt++
}
}
return cnt
}
func (this *Scene) GetBlackPlayerCnt() int {
var cnt int
for _, p := range this.players {
if p.WBLevel < 0 {
cnt++
}
}
return cnt
}
func (this *Scene) GetLostPlayerCnt() int {
var cnt int
keyGameId := strconv.Itoa(int(this.dbGameFree.GetGameId()))
for _, p := range this.players {
if p.GDatas != nil {
if d, exist := p.GDatas[keyGameId]; exist {
if d.Statics.TotalIn > d.Statics.TotalOut {
cnt++
}
}
}
}
return cnt
}
func (this *Scene) GetWinPlayerCnt() int {
var cnt int
keyGameId := strconv.Itoa(int(this.dbGameFree.GetGameId()))
for _, p := range this.players {
if p.GDatas != nil {
if d, exist := p.GDatas[keyGameId]; exist {
if d.Statics.TotalIn < d.Statics.TotalOut {
cnt++
}
}
}
}
return cnt
}
func (this *Scene) GetTruePlayerCnt() int {
return len(this.players) - this.robotNum
}
func (this *Scene) Broadcast(packetId int, msg rawproto.Message, excludeSid int64) {
mgs := make(map[*netlib.Session][]*srvlibproto.MCSessionUnion)
for _, p := range this.players {
if p != nil {
if p.sid != excludeSid {
if p.gateSess != nil && p.IsOnLine() {
mgs[p.gateSess] = append(mgs[p.gateSess], &srvlibproto.MCSessionUnion{
Mccs: &srvlibproto.MCClientSession{
SId: p.sid,
},
})
}
}
}
}
for _, p := range this.audiences {
if p != nil && p.sid != excludeSid {
if p.gateSess != nil && p.IsOnLine() {
mgs[p.gateSess] = append(mgs[p.gateSess], &srvlibproto.MCSessionUnion{
Mccs: &srvlibproto.MCClientSession{
SId: p.sid,
},
})
}
}
}
for gateSess, v := range mgs {
if gateSess != nil && len(v) != 0 {
pack, err := common.CreateMulticastPacket(packetId, msg, v...)
if err == nil {
proto.SetDefaults(pack)
gateSess.Send(int(srvlibproto.SrvlibPacketID_PACKET_SS_MULTICAST), pack)
}
}
}
}
func (this *Scene) HasSameIp(ip string) bool {
for _, p := range this.players {
if !p.IsRob {
if p.Ip == ip {
return true
}
}
}
return false
}
func (this *Scene) IsPreCreateScene() bool {
return this.dbGameFree.GetCreateRoomNum() > 0
}
func (this *Scene) TryForceDeleteMatchInfo() {
if !this.IsMatchScene() {
return
}
if len(this.players) == 0 {
return
}
if this.MatchSortId == 0 {
return
}
if players, exist := TournamentMgr.players[this.MatchSortId]; exist {
for _, player := range this.players {
if player != nil && !player.IsRob {
if TournamentMgr.IsMatching(player.SnId) {
delete(players, player.SnId)
}
}
}
}
}
// CanAudience 是否允许观战
func (this *Scene) CanAudience() bool {
switch {
case this.GetMatchSortId() > 0: // 比赛场
tm := TournamentMgr.GetTm(this.GetMatchSortId())
if tm != nil {
return tm.gmd.GetAudienceSwitch() == 1
}
return false
default:
return true
}
}