game_sync/worldsrv/scene.go

1266 lines
35 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"
"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"
playerproto "mongo.games.com/game/protocol/player"
serverproto "mongo.games.com/game/protocol/server"
"mongo.games.com/game/srvdata"
)
const (
MatchSceneState_Waiting = iota //等待状态
MatchSceneState_Running //进行状态
MatchSceneState_Billed //结算状态
)
const (
// PlayerHistoryModel .
PlayerHistoryModel = iota + 1
// BIGWIN_HISTORY_MODEL .
BIGWIN_HISTORY_MODEL
// GameHistoryModel .
GameHistoryModel
)
type PlayerGameCtx struct {
takeCoin int64 //进房时携带的金币量
enterTs int64 //进入时间
totalConvertibleFlow int64 //进房时玩家身上的总流水
}
// Scene 场景(房间)
type Scene struct {
sceneId int //场景id
gameId int //游戏id
gameMode int //游戏模式
sceneMode int //房间模式,参考common.SceneMode_XXX
params []int64 //场景参数
paramsEx []int32 //其他扩展参数
playerNum int //人数
robotNum int //机器人数量
robotLimit int //最大限制机器人数量
preInviteRobNum int //准备邀请机器人的数量
creator int32 //创建者账号id
agentor int32 //代理者id
replayCode string //回放码
currRound int32 //当前第几轮
totalRound int32 //总共几轮
clycleTimes int32 //循环次数
deleting bool //正在删除
starting bool //正在开始
closed bool //房间已关闭
force bool //强制删除
hadCost bool //是否已经扣过房卡
inTeahourse 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 //开始时间
dirty bool //脏标记
applyTimes map[int32]int32 //申请坐下次数
limitPlatform *Platform //限制平台
groupId int32 //组id
hallId int32 //厅id
state int32 //场景当前状态
fishing int32 //渔场的鱼潮状态
gameCtx map[int32]*PlayerGameCtx //进入房间的环境
dbGameFree *serverproto.DB_GameFree //
ClubId int32
clubRoomID string //俱乐部包间ID
clubRoomPos int32 //
clubRoomTax int32 //
createFee int32 //创建房间的费用
GameLog []int32 //游戏服务器同步的录单
JackPotFund int64 //游戏服务器同步的奖池
State int32 //当前游戏状态后期放到ScenePolicy里去处理
StateTs int64 //切换到当前状态的时间
StateSec int32 //押注状态的秒数
BankerListNum int32 //庄家列表数量
matchParams []int32 //比赛参数
matchState int //比赛状态
quitMatchSnids []int32 //退赛玩家id
gameSite int //tienlen游戏场次区分 1.初级 2.中级 3.高级场
BaseScore int32 //tienlen游戏底分
matchId int64 //比赛场id
csp *CoinScenePool // 所在场景池
}
// NewScene 创建房间
func NewScene(agentor, creator int32, id, gameId, gameMode, sceneMode int, clycleTimes, numOfGames int32, params []int64,
gs *GameSession, limitPlatform *Platform, groupId int32, dbGameFree *serverproto.DB_GameFree, paramsEx ...int32) *Scene {
sp := GetScenePolicy(gameId, gameMode)
if sp == nil {
logger.Logger.Errorf("NewScene sp == nil, gameId=%v gameMode=%v", gameId, gameMode)
return nil
}
s := &Scene{
sceneId: id,
hallId: dbGameFree.Id,
playerNum: 0,
creator: creator,
agentor: agentor,
gameId: gameId,
gameMode: gameMode,
sceneMode: sceneMode,
params: params,
paramsEx: paramsEx,
clycleTimes: clycleTimes,
players: make(map[int32]*Player),
audiences: make(map[int32]*Player),
gameSess: gs,
sp: sp,
createTime: time.Now(),
limitPlatform: limitPlatform,
groupId: groupId,
gameCtx: make(map[int32]*PlayerGameCtx), //进入房间的环境
dbGameFree: dbGameFree,
currRound: 0,
totalRound: numOfGames,
}
// 从房间配置参数获取,最大房间人数
s.playerNum = int(sp.GetPlayerNum(s))
s.lastTime = s.createTime
if s.IsHallScene() || s.IsCoinScene() {
code := SceneMgrSingleton.AllocReplayCode()
s.replayCode = code
}
if s.dbGameFree.GetMatchMode() == 0 {
s.RandRobotCnt()
}
if s.IsMatchScene() {
s.BaseScore = 10
}
s.sp.OnStart(s)
return s
}
func NewLocalGameScene(creator int32, sceneId, gameId, gameSite, sceneMode int, clycleTimes int32, params []int64,
gs *GameSession, limitPlatform *Platform, playerNum int, dbGameFree *serverproto.DB_GameFree, baseScore, groupId int32, paramsEx ...int32) *Scene {
sp := GetScenePolicy(gameId, 0)
if sp == nil {
logger.Logger.Errorf("NewLocalGameScene sp == nil, gameId=%v ", gameId)
return nil
}
s := &Scene{
sceneId: sceneId,
hallId: dbGameFree.Id,
playerNum: playerNum,
creator: creator,
gameId: gameId,
sceneMode: sceneMode,
params: params,
paramsEx: paramsEx,
clycleTimes: clycleTimes,
players: make(map[int32]*Player),
audiences: make(map[int32]*Player),
gameSess: gs,
sp: sp,
createTime: time.Now(),
limitPlatform: limitPlatform,
groupId: groupId,
gameCtx: make(map[int32]*PlayerGameCtx), //进入房间的环境
dbGameFree: dbGameFree,
gameSite: gameSite,
BaseScore: baseScore,
}
if s.playerNum <= 0 {
s.playerNum = int(sp.GetPlayerNum(s))
}
if s.BaseScore <= 0 {
s.BaseScore = int32(sp.GetBaseCoin(s))
}
s.lastTime = s.createTime
code := SceneMgrSingleton.AllocReplayCode()
s.replayCode = code
s.sp.OnStart(s)
return s
}
func (this *Scene) RebindPlayerSnId(oldSnId, newSnId int32) {
if this.creator == oldSnId {
this.creator = newSnId
}
if this.agentor == oldSnId {
this.agentor = 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) PlayerEnter(p *Player, pos int, ischangeroom bool) bool {
logger.Logger.Infof("(this *Scene:%v) PlayerEnter(%v, %v) ", this.sceneId, p.SnId, pos)
if p.IsRob {
if this.robotLimit != 0 {
if !model.GameParamData.IsRobFightTest {
//增加所有机器人对战场的
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
}
}
}
}
p.scene = this
this.players[p.SnId] = p
this.gameSess.AddPlayer(p)
switch {
case this.IsCoinScene():
case this.IsHundredScene():
// todo 删除这个标记
HundredSceneMgrSington.OnPlayerEnter(p, this.paramsEx[0])
case this.IsMatchScene():
}
// 如果正在等待比赛,退赛
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)
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
} else {
if p.IsRob {
if len(this.paramsEx) > 0 { //机器人携带金币动态调整
gps := PlatformMgrSingleton.GetGameFree(this.limitPlatform.IdStr, this.paramsEx[0])
if gps != nil {
dbGameFree := gps.DbGameFree
if gps.GroupId != 0 {
pgg := PlatformGameGroupMgrSington.GetGameGroup(gps.GroupId)
if pgg != nil {
dbGameFree = pgg.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 && int(arr.GameSite) == this.gameSite {
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.gameSite, " 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 && this.IsCoinScene() && !this.IsTestScene() {
// if expectEnterCoin, expectLeaveCoin, ExpectGameTime, ok := RobotCarryMgrEx.RandOneCarry(dbGameFree.GetId()); ok && expectEnterCoin > dbGameFree.GetLimitCoin() && expectEnterCoin < dbGameFree.GetMaxCoinLimit() {
// takeCoin = int64(expectEnterCoin)
// leaveCoin = int64(expectLeaveCoin)
// //如果带入金币和离开金币比较接近,就调整离开金币值
// var delta = takeCoin - leaveCoin
// if math.Abs(float64(delta)) < float64(takeCoin/50) {
// if leaveCoin = takeCoin + delta*(10+rand.Int63n(50)); leaveCoin < 0 {
// leaveCoin = 0
// }
// }
// gameTimes = ExpectGameTime * 2
// flag = true
// }
//}
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])))
}
bankerLimit := this.dbGameFree.GetBanker()
if bankerLimit != 0 {
//上庄AI携带
if /*this.gameId == common.GameId_HundredBull ||*/
this.gameId == common.GameId_RollCoin ||
this.gameId == common.GameId_RollAnimals ||
this.gameId == common.GameId_DragonVsTiger ||
this.gameId == common.GameId_Baccarat {
if this.BankerListNum < 3 {
if rand.Intn(100) < 5 {
randCoin := int64(math.Floor(float64(bankerLimit) * 1 / float64(this.dbGameFree.GetSceneType())))
takeCoin = rand.Int63n(randCoin) + int64(bankerLimit)
if takeCoin > p.Coin {
//加钱速度慢 暂时不用
//ExePMCmd(p.gateSess, fmt.Sprintf("%v%v%v", common.PMCmd_AddCoin, common.PMCmd_SplitToken, takeCoin))
}
}
}
}
}
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)
}
//todo:send add msg to gamesrv
data, err := p.MarshalData(this.gameId)
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()
}
}
isQuMin := false
//if !p.IsRob {
// pt := PlatformMgrSingleton.GetPackageTag(p.PackageID)
// if pt != nil && pt.SpreadTag == 1 {
// isQuMin = true
// }
//}
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),
IsQM: proto.Bool(isQuMin),
IParams: p.MarshalIParam(),
SParams: p.MarshalSParam(),
CParams: p.MarshalCParam(),
}
//sa, err2 := p.MarshalSingleAdjustData(this.dbGameFree.Id)
//if err2 == nil && sa != nil {
// msg.SingleAdjust = sa
//}
if this.ClubId != 0 {
}
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 ExePMCmd(s *netlib.Session, cmd string) {
CSPMCmd := &playerproto.CSPMCmd{
Cmd: proto.String(cmd),
}
proto.SetDefaults(CSPMCmd)
logger.Logger.Trace("CSPMCmd:", CSPMCmd)
s.Send(int(playerproto.PlayerPacketID_PACKET_CS_PMCMD), CSPMCmd)
}
func (this *Scene) GetPlayerGameCtx(snid int32) *PlayerGameCtx {
if ctx, exist := this.gameCtx[snid]; exist {
return ctx
}
return nil
}
func (this *Scene) PlayerLeave(p *Player, reason int) {
logger.Logger.Infof("(this *Scene:%v) PlayerLeave(%v, %v) ", this.sceneId, p.SnId, reason)
//if !this.IsMatchScene() {
//pack := &hall_proto.SCLeaveRoom{
// Reason: proto.Int(reason),
// OpRetCode: hall_proto.OpResultCode_Game_OPRC_Sucess_Game,
// Mode: proto.Int(0),
// RoomId: proto.Int(this.sceneId),
//}
//proto.SetDefaults(pack)
//p.SendToClient(int(hall_proto.GameHallPacketID_PACKET_SC_LEAVEROOM), pack)
pack := &hallproto.SCQuitGame{
Id: int32(this.dbGameFree.Id),
Reason: proto.Int(reason),
}
pack.OpCode = hallproto.OpResultCode_Game_OPRC_Sucess_Game
proto.SetDefaults(pack)
p.SendToClient(int(hallproto.GameHallPacketID_PACKET_SC_QUITGAME), pack)
//}
//其他人直接从房间退出来
this.DelPlayer(p)
// 玩家最后所在游戏
p.LastGameId = int(this.dbGameFree.GetGameId())
if !p.IsRob {
this.lastTime = time.Now()
}
}
func (this *Scene) DelPlayer(p *Player) bool {
if p.scene != this {
inroomid := 0
if p.scene != nil {
inroomid = p.scene.sceneId
}
logger.Logger.Warnf("(this *Scene) DelPlayer found player:%v in room:%v but room:%v", p.SnId, inroomid, this.sceneId)
}
if this.gameSess != nil {
this.gameSess.DelPlayer(p)
}
delete(this.players, p.SnId)
if !p.IsRob {
delete(this.gameCtx, p.SnId)
}
p.scene = nil
SceneMgrSingleton.OnPlayerLeaveScene(this, p)
switch {
case this.IsHundredScene():
HundredSceneMgrSington.OnPlayerLeave(p)
//case this.IsHallScene():
// PlatformMgrSingleton.OnPlayerLeaveScene(this, p)
// for i := 0; i < this.playerNum; i++ {
// if this.seats[i] == p {
// p.pos = -1
// this.seats[i] = nil
// break
// }
// }
case this.IsCoinScene() || this.IsMatchScene():
for i := 0; i < this.playerNum; i++ {
if this.seats[i] == p {
p.pos = -1
this.seats[i] = nil
break
}
}
}
if p.IsRob {
this.robotNum--
name := this.GetSceneName()
logger.Logger.Tracef("(this *Scene) PlayerLeave(%v) robot(%v) robotlimit(%v)", name, this.robotNum, this.robotLimit)
}
//from gameserver, so don't need send msg
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
this.audiences[p.SnId] = p
this.gameSess.AddPlayer(p)
if this.IsHundredScene() {
HundredSceneMgrSington.OnPlayerEnter(p, this.paramsEx[0])
}
//todo:send add msg to gamesrv
data, err := p.MarshalData(this.gameId)
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()
}
}
isQuMin := false
//if !p.IsRob {
// pt := PlatformMgrSingleton.GetPackageTag(p.PackageID)
// if pt != nil && pt.SpreadTag == 1 {
// isQuMin = true
// }
//}
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),
IsQM: proto.Bool(isQuMin),
IParams: p.MarshalIParam(),
SParams: p.MarshalSParam(),
CParams: p.MarshalCParam(),
}
if !p.IsRob { //保存下进入时的环境
this.gameCtx[p.SnId] = &PlayerGameCtx{
takeCoin: p.takeCoin,
enterTs: p.enterts.Unix(),
totalConvertibleFlow: p.TotalConvertibleFlow,
}
this.lastTime = time.Now()
}
takeCoin := p.Coin
p.takeCoin = takeCoin
msg.TakeCoin = proto.Int64(takeCoin)
proto.SetDefaults(msg)
this.SendToGame(int(serverproto.SSPacketID_PACKET_WG_AUDIENCEENTER), msg)
p.enterts = time.Now()
return true
}
return false
}
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),
}
proto.SetDefaults(pack)
p.SendToClient(int(hallproto.GameHallPacketID_PACKET_SC_LEAVEROOM), pack)
//观众直接从房间退出来
this.DelAudience(p)
if !p.IsRob {
this.lastTime = time.Now()
}
}
func (this *Scene) DelAudience(p *Player) bool {
logger.Logger.Infof("(this *Scene:%v) DelAudience(%v) ", this.sceneId, p.SnId)
if p.scene != this {
return false
}
if this.gameSess != nil {
this.gameSess.DelPlayer(p)
}
delete(this.audiences, p.SnId)
if !p.IsRob {
delete(this.gameCtx, p.SnId)
}
p.scene = nil
SceneMgrSingleton.OnPlayerLeaveScene(this, p)
if this.IsHundredScene() {
HundredSceneMgrSington.OnPlayerLeave(p)
}
//from gameserver, so don't need send msg
return true
}
//观众坐下
//func (this *Scene) AudienceSit(p *Player, pos int) bool {
// logger.Logger.Infof("(this *Scene:%v) AudienceSit(%v, %v, %v) ", this.sceneId, p.SnId, pos)
// if _, exist := this.audiences[p.SnId]; exist {
// if pos == -1 && !this.IsHundredScene() { //自动匹配;百人场没座位概念
// for i := 0; i < this.playerNum; i++ {
// if this.seats[i] == nil {
// pos = i
// break
// }
// }
// }
// if pos != -1 || this.IsHundredScene() {
// if !this.IsHundredScene() {
// if this.seats[pos] != nil {
// return false
// }
// p.pos = pos
// p.applyPos = -1
// this.seats[pos] = p
// }
// delete(this.audiences, p.SnId)
// }
//
// p.scene = this
// this.players[p.SnId] = p
//
// NpcServerAgentSington.OnPlayerEnterScene(this, p)
// if this.IsCoinScene() {
// CoinSceneMgrSingleton.OnPlayerEnter(p, int32(this.sceneId))
// } else if this.IsHallScene() {
// PlatformMgrSingleton.OnPlayerEnterScene(this, p)
// }
//
// msg := &protocol.WGAudienceSit{
// SnId: proto.Int32(p.SnId),
// SceneId: proto.Int(this.sceneId),
// Pos: proto.Int(pos),
// }
// p.takeCoin = p.Coin
// msg.TakeCoin = proto.Int64(p.Coin)
// proto.SetDefaults(msg)
// this.SendToGame(int(protocol.MmoPacketID_PACKET_WG_AUDIENCESIT), msg)
// this.lastTime = time.Now()
// return true
// }
// return false
//}
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
this.players[p.SnId] = p
msg := &serverproto.WGAudienceSit{
SnId: proto.Int32(p.SnId),
SceneId: proto.Int(this.sceneId),
Pos: proto.Int(pos),
}
p.takeCoin = p.Coin
msg.TakeCoin = proto.Int64(p.Coin)
proto.SetDefaults(msg)
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)
}
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
}
func (this *Scene) OnClose() {
scDestroyRoom := &hallproto.SCDestroyRoom{
RoomId: proto.Int(this.sceneId),
OpRetCode: hallproto.OpResultCode_Game_OPRC_Sucess_Game,
IsForce: proto.Int(1),
}
proto.SetDefaults(scDestroyRoom)
this.Broadcast(int(hallproto.GameHallPacketID_PACKET_SC_DESTROYROOM), scDestroyRoom, 0)
this.closed = true
this.sp.OnStop(this)
//NpcServerAgentSington.OnSceneClose(this)
for _, p := range this.players {
this.DelPlayer(p)
}
for _, p := range this.audiences {
this.DelAudience(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, rawpack interface{}, excludeId int32) {
for snid, value := range this.players {
if snid == excludeId {
continue
}
value.SendToClient(packetid, rawpack)
}
}
func (this *Scene) BilledRoomCard(snid []int32) {
if this.sp != nil {
this.sp.BilledRoomCard(this, snid)
}
}
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) DoDelete(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)
}
func (this *Scene) Shutdown() {
if this.hadCost && this.sp != nil {
this.sp.OnShutdown(this)
}
}
// 小游戏场
func (this *Scene) IsMiniGameScene() bool {
return this.sceneId >= common.MiniGameSceneStartId && this.sceneId < common.MiniGameSceneMaxId
}
// 比赛场
func (this *Scene) IsMatchScene() bool {
return this.sceneId >= common.MatchSceneStartId && this.sceneId < common.MatchSceneMaxId
}
// 大厅场
func (this *Scene) IsHallScene() bool {
return this.sceneId >= common.HallSceneStartId && this.sceneId < common.HallSceneMaxId
}
// 金币场
func (this *Scene) IsCoinScene() bool {
return this.sceneId >= common.CoinSceneStartId && this.sceneId < common.CoinSceneMaxId
}
// 百人场
func (this *Scene) IsHundredScene() bool {
return this.sceneId >= common.HundredSceneStartId && this.sceneId < common.HundredSceneMaxId
}
// 私人房间
func (this *Scene) IsPrivateScene() bool {
return this.sceneId >= common.PrivateSceneStartId && this.sceneId < common.PrivateSceneMaxId || this.sceneMode == common.SceneMode_Private
}
func (this *Scene) IsSceneMode(mode int) bool {
return this.sceneMode == mode
}
func (this *Scene) IsRankMatch() bool {
if this.dbGameFree == nil {
return false
}
return this.dbGameFree.RankType > 0
}
func (this *Scene) IsTestScene() bool {
if this.dbGameFree != nil {
return this.dbGameFree.GetSceneType() == -1
}
if len(this.paramsEx) > 0 {
dbGameFree := srvdata.PBDB_GameFreeMgr.GetData(this.paramsEx[0])
if dbGameFree != nil {
return dbGameFree.GetSceneType() == -1
}
}
return false
}
func (this *Scene) GetSceneName() string {
if len(this.paramsEx) > 0 {
dbGameFree := srvdata.PBDB_GameFreeMgr.GetData(this.paramsEx[0])
if dbGameFree != nil {
return dbGameFree.GetName() + dbGameFree.GetTitle()
}
}
return "[unknow scene name]"
}
func (this *Scene) RandRobotCnt() {
if len(this.paramsEx) > 0 {
gps := PlatformMgrSingleton.GetGameFree(this.limitPlatform.IdStr, this.paramsEx[0])
if gps != nil {
dbGameFree := gps.DbGameFree
if gps.GroupId != 0 {
pgg := PlatformGameGroupMgrSington.GetGameGroup(gps.GroupId)
if pgg != nil {
dbGameFree = pgg.DbGameFree
}
}
numrng := dbGameFree.GetRobotNumRng()
if len(numrng) >= 2 {
if numrng[1] == numrng[0] {
this.robotLimit = int(numrng[0])
} else {
if numrng[1] < numrng[0] {
numrng[1], numrng[0] = numrng[0], numrng[1]
}
this.robotLimit = int(numrng[1]) //int(numrng[0] + rand.Int31n(numrng[1]-numrng[0]) + 1)
}
}
}
}
}
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) GetPlayerType(gameid, gamefreeid int32) (types []int32) {
for _, p := range this.players {
t := int32(0)
if p.IsRob {
t = common.PlayerType_Rob
} else if p.WBLevel < 0 {
t = common.PlayerType_Black
} else if p.WBLevel > 0 {
t = common.PlayerType_White
} else {
pt := p.CheckType(gameid, gamefreeid)
if pt != nil {
t = pt.GetId()
} else {
t = common.PlayerType_Undefine
}
}
if !common.InSliceInt32(types, t) {
types = append(types, t)
}
}
return
}
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 := MulticastMaker.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.GMLevel == 0 && p.Ip == ip {
return true
}
}
}
return false
}
func (this *Scene) IsPreCreateScene() bool {
return this.dbGameFree.GetCreateRoomNum() > 0
}
func (this *Scene) PlayerTryChange() {
var member []*Player
var player *Player
for _, value := range this.players {
if !value.IsRob {
member = append(member, value)
player = value
}
}
if len(member) <= 1 {
return
}
gameFreeId := this.dbGameFree.GetId()
gameConfig := PlatformMgrSingleton.GetGameFree(player.Platform, gameFreeId)
if gameConfig != nil && gameConfig.DbGameFree.GetMatchMode() == 1 {
return
}
for i := 0; i < len(member)-1; i++ {
p := member[i]
other := member[i+1:]
if this.dbGameFree.GetSamePlaceLimit() > 0 && sceneLimitMgr.LimitSamePlaceBySnid(other, p,
this.dbGameFree.GetGameId(), this.dbGameFree.GetSamePlaceLimit()) {
if p.scene.IsPrivateScene() {
//if ClubSceneMgrSington.PlayerInChanging(p) {
// continue
//}
//ClubSceneMgrSington.PlayerTryChange(p, gameFreeId, []int32{int32(this.sceneId)}, false)
} else {
if CoinSceneMgrSingleton.PlayerInChanging(p) {
continue
}
excludeSceneIds := p.lastSceneId[gameFreeId]
CoinSceneMgrSingleton.PlayerTryChange(p, gameFreeId, excludeSceneIds, false)
}
}
}
}
func (this *Scene) GetParamEx(idx int) int32 {
if idx < 0 || idx > len(this.paramsEx) {
return -1
}
return this.paramsEx[idx]
}
func (this *Scene) SetParamEx(idx int, val int32) {
cnt := len(this.paramsEx)
if idx >= 0 && idx < cnt {
this.paramsEx[idx] = val
}
}
func (this *Scene) TryForceDelectMatchInfo() {
if !this.IsMatchScene() {
return
}
if len(this.players) == 0 {
return
}
if this.matchId == 0 {
return
}
if players, exist := TournamentMgr.players[this.matchId]; exist {
for _, player := range this.players {
if player != nil && !player.IsRob {
if TournamentMgr.IsMatching(player.SnId) {
delete(players, player.SnId)
}
}
}
}
}