game_sync/worldsrv/scene.go

980 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"
"mongo.games.com/game/protocol/gamehall"
hallproto "mongo.games.com/game/protocol/gamehall"
serverproto "mongo.games.com/game/protocol/server"
"mongo.games.com/game/srvdata"
)
type PlayerGameCtx struct {
takeCoin int64 //进房时携带的金币量
enterTs int64 //进入时间
}
// Scene 场景(房间)
type Scene struct {
sceneId int // 场景id
gameId int // 游戏id
gameMode int // 废弃,游戏模式(玩法)
sceneMode int // 房间模式,参考common.SceneMode_XXX
params []int64 // 场景参数
playerNum int // 房间最大人数
robotNum int // 机器人数量
robotLimit 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 // 游戏开始时间
limitPlatform *Platform // 限制平台
groupId int32 // 组id
dbGameFree *serverproto.DB_GameFree // 场次配置
gameCtx map[int32]*PlayerGameCtx // 进入房间的环境,没有机器人数据 SnId
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())
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,
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 {
// 普通匹配设置最大机器人数量
number := s.dbGameFree.GetRobotNumRng()
if len(number) >= 2 {
if number[1] == number[0] {
s.robotLimit = int(number[0])
} else {
if number[1] < number[0] {
number[1], number[0] = number[0], number[1]
}
s.robotLimit = int(number[1])
}
}
}
if s.MatchParam == nil {
s.MatchParam = new(serverproto.MatchParam)
}
if s.CustomParam == nil {
s.CustomParam = new(serverproto.CustomParam)
}
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 玩家进入场景
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 this.dbGameFree == nil {
return false
}
// 机器人数量限制
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)
}
}
takeCoin := p.Coin
leaveCoin := int64(0)
gameTimes := rand.Int31n(100)
if this.IsCustom() { // 房卡场初始1000金币
takeCoin = 1000
}
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 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)
if !this.IsMatchScene() && !this.IsCustom() {
flag := false
// 本地游戏机器人携带金币
if common.IsLocalGame(this.gameId) {
baseScore := this.BaseScore
arrs := srvdata.PBDB_CreateroomMgr.Datas.Arr
var 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 := this.dbGameFree.GetRobotTakeCoin()
if len(takerng) >= 2 && takerng[1] > takerng[0] {
if takerng[0] < this.dbGameFree.GetLimitCoin() {
takerng[0] = this.dbGameFree.GetLimitCoin()
}
takeCoin = int64(common.RandInt(int(takerng[0]), int(takerng[1])))
} else {
maxlimit := int64(this.dbGameFree.GetMaxCoinLimit())
if maxlimit != 0 && p.Coin > maxlimit {
logger.Logger.Trace("Player coin:", p.Coin)
//在下限和上限之间随机并对其的100的整数倍
takeCoin = int64(common.RandInt(int(this.dbGameFree.GetLimitCoin()), int(maxlimit)))
logger.Logger.Trace("Take coin:", takeCoin)
}
if maxlimit == 0 && this.IsCoinScene() {
maxlimit = int64(common.RandInt(10, 50)) * int64(this.dbGameFree.GetLimitCoin())
takeCoin = int64(common.RandInt(int(this.dbGameFree.GetLimitCoin()), int(maxlimit)))
logger.Logger.Trace("Take coin:", takeCoin)
}
}
takeCoin = takeCoin / 100 * 100
//离场金币
leaverng := this.dbGameFree.GetRobotLimitCoin()
if len(leaverng) >= 2 {
leaveCoin = leaverng[0] + rand.Int63n(leaverng[1]-leaverng[0])
}
}
// 象棋积分
chessScore := this.dbGameFree.GetChessScoreParams()
if len(chessScore) == 2 {
p.ChessGrade = int64(common.RandInt(int(chessScore[0]), int(chessScore[1])))
}
if takeCoin > p.Coin {
p.Coin = takeCoin
}
}
}
data, err := p.MarshalData()
if err != nil {
logger.Logger.Errorf("Scene PlayerEnter MarshalData failed, err:%v", err)
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),
GateSid: proto.Int64(gateSid),
SceneId: proto.Int(this.sceneId),
PlayerData: data,
TakeCoin: takeCoin,
IsLoaded: proto.Bool(ischangeroom),
IsQM: false,
ExpectLeaveCoin: leaveCoin,
ExpectGameTimes: gameTimes,
IParams: p.MarshalIParam(),
SParams: p.MarshalSParam(),
CParams: p.MarshalCParam(),
SnId: proto.Int32(p.SnId),
Pos: int32(p.pos),
MatchParams: matchParams,
}
// 道具
msg.Items = make(map[int32]int64)
dbItemArr := srvdata.GameItemMgr.GetArr(p.Platform)
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])))
}
}
}
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)
p.scene = this
p.takeCoin = takeCoin
p.sceneCoin = takeCoin
p.enterts = time.Now()
this.players[p.SnId] = p
if !p.IsRob { //保存下进入时的环境
this.gameCtx[p.SnId] = &PlayerGameCtx{
takeCoin: p.takeCoin,
enterTs: p.enterts.Unix(),
}
this.lastTime = time.Now()
}
this.gameSess.AddPlayer(p)
FirePlayerEnterScene(p, this)
this.sp.OnPlayerEnter(this, p)
return true
}
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),
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()
}
FirePlayerLeaveScene(p, this)
this.sp.OnPlayerLeave(this, p)
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 {
if this.playerNum == 0 {
return false
}
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
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
}
// IsLongTimeInactive 房间是否长时间没有活动
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)
}
// IsCoinScene 金币场
func (this *Scene) IsCoinScene() bool {
return this != nil && this.csp != nil
}
// IsHundredScene 百人场
func (this *Scene) IsHundredScene() bool {
return this != nil && this.hp != nil
}
// IsMatchScene 比赛场
func (this *Scene) IsMatchScene() bool {
return this.IsSceneMode(common.SceneModeMatch)
}
// IsPrivateScene 私人房间
func (this *Scene) IsPrivateScene() bool {
return this.IsSceneMode(common.SceneModePrivate)
}
// IsCustom 竞技馆房间
func (this *Scene) IsCustom() bool {
if this.IsSceneMode(common.SceneModePrivateMatch) {
return true
}
if this.dbGameFree == nil {
return false
}
return this.dbGameFree.IsCustom > 0
}
// IsRankMatch 排位赛
func (this *Scene) IsRankMatch() bool {
if this.dbGameFree == nil {
return false
}
return this.dbGameFree.RankType > 0
}
// IsSceneMode 房间模式
func (this *Scene) IsSceneMode(mode int) bool {
return this.sceneMode == mode
}
// 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) 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
}
}
func (this *Scene) ProtoPrivateRoom() *gamehall.PrivateRoomInfo {
if !this.IsCustom() {
return nil
}
needPassword := int32(0)
if this.GetPassword() != "" {
needPassword = int32(1)
}
ret := &gamehall.PrivateRoomInfo{
GameFreeId: this.dbGameFree.GetId(),
GameId: int32(this.gameId),
RoomTypeId: this.RoomTypeId,
RoomConfigId: this.RoomConfigId,
RoomId: int32(this.sceneId),
NeedPassword: needPassword,
CurrRound: this.currRound,
MaxRound: this.totalRound,
CurrNum: int32(this.GetPlayerCnt()),
MaxPlayer: int32(this.playerNum),
CreateTs: this.createTime.Unix(),
State: this.SceneState,
}
for _, v := range this.players {
ret.Players = append(ret.Players, &gamehall.PrivatePlayerInfo{
SnId: v.SnId,
Name: v.Name,
UseRoleId: v.GetRoleId(),
})
}
return ret
}
// NotifyPrivateRoom 通知私人房列表变更
func (this *Scene) NotifyPrivateRoom(tp common.ListOpType) {
if this.IsCustom() {
pack := &gamehall.SCGetPrivateRoomList{
Tp: int32(tp),
Datas: []*gamehall.PrivateRoomInfo{this.ProtoPrivateRoom()},
}
PlayerNotifySingle.SendToClient(common.NotifyPrivateRoomList, int(gamehall.GameHallPacketID_PACKET_SC_GETPRIVATEROOMLIST), pack)
logger.Logger.Tracef("NotifyPrivateRoom: %v", pack)
}
}