980 lines
27 KiB
Go
980 lines
27 KiB
Go
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)
|
||
}
|
||
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 玩家进入场景
|
||
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 {
|
||
FirePlayerLeaveScene(p, this)
|
||
this.sp.OnPlayerLeave(this, p)
|
||
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 {
|
||
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
|
||
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
|
||
}
|
||
|
||
// 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)
|
||
}
|
||
|
||
// 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
|
||
}
|
||
|
||
// 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) 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)
|
||
}
|
||
}
|