2583 lines
68 KiB
Go
2583 lines
68 KiB
Go
package base
|
||
|
||
import (
|
||
"fmt"
|
||
"github.com/globalsign/mgo/bson"
|
||
"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/core/utils"
|
||
"mongo.games.com/goserver/srvlib/action"
|
||
srvlibproto "mongo.games.com/goserver/srvlib/protocol"
|
||
|
||
"mongo.games.com/game/common"
|
||
"mongo.games.com/game/model"
|
||
"mongo.games.com/game/mq"
|
||
"mongo.games.com/game/proto"
|
||
"mongo.games.com/game/protocol/gamehall"
|
||
"mongo.games.com/game/protocol/player"
|
||
"mongo.games.com/game/protocol/server"
|
||
"mongo.games.com/game/protocol/webapi"
|
||
"mongo.games.com/game/srvdata"
|
||
)
|
||
|
||
const ReplayIdTf = "20060102150405"
|
||
|
||
var sceneRandSeed = time.Now().UnixNano()
|
||
var RobotSceneDBGameFreeSync = make(map[int]bool)
|
||
|
||
type GameScene interface {
|
||
SceneDestroy(force bool)
|
||
}
|
||
|
||
// todo 结构优化
|
||
type Scene struct {
|
||
*server.WGCreateScene
|
||
ws *netlib.Session // 大厅服
|
||
Rand *rand.Rand // 随机数生成器
|
||
ExtraData interface{} // 房间数据
|
||
aiMgr AIMgr //
|
||
WithLocalAI bool //
|
||
disbandGen int //第几次解散申请
|
||
disbandParam []int64 //解散参数
|
||
disbandPos int32 //发起解散的玩家位置
|
||
disbandTs int64 //解散发起时间戳
|
||
realPlayerNum int //真实玩家人数
|
||
robotNum int //机器人数量
|
||
robotLimit int //最大限制机器人数量
|
||
robotNumLastInvite int //上次邀请机器人时的数量
|
||
NumOfGames int //局数
|
||
Players map[int32]*Player //参与者
|
||
audiences map[int32]*Player //观众
|
||
sp ScenePolicy //场景游戏策略
|
||
rr *ReplayRecorder //回放记录器
|
||
rrVer int32 //录像的协议版本号
|
||
SceneState SceneState //场景状态
|
||
StateStartTime time.Time //状态开始时间
|
||
stateEndTime time.Time //状态结束时间
|
||
GameStartTime time.Time //游戏开始计时时间
|
||
GameNowTime time.Time //当局游戏开始时间
|
||
nextInviteTime time.Time //下次邀请机器人时间
|
||
inviteInterval int64 //邀请间隔
|
||
pause bool
|
||
Gaming bool
|
||
destroyed bool
|
||
completed bool
|
||
Testing bool //是否为测试场
|
||
graceDestroy bool //等待销毁
|
||
replayAddId int32
|
||
KeyGameId string //游戏类型唯一ID
|
||
KeyGamefreeId string //游戏场次唯一id
|
||
KeyGameDif string
|
||
GroupId int32 //分组id
|
||
bEnterAfterStart bool //是否允许中途加入
|
||
ClubId int32
|
||
RoomId string //俱乐部那个包间
|
||
RoomPos int32 //房间桌号
|
||
PumpCoin int32 //抽水比例,同一个俱乐部下面的抽水比例是一定的,百分比
|
||
DealyTime int64 //结算延时时间
|
||
CpCtx model.CoinPoolCtx //水池环境
|
||
CpControlled bool //被水池控制了
|
||
timerRandomRobot int64
|
||
nogDismiss int //检查机器人离场时的局数(同一局只检查一次)
|
||
SystemCoinOut int64 //本局游戏机器人营收 机器人赢:正值 机器人输:负值
|
||
ChessRank []int32
|
||
RealCtrl bool
|
||
CycleID string // 房卡场多轮对局id
|
||
LogId string // 游戏每局id
|
||
}
|
||
|
||
func NewScene(args *CreateSceneParam) *Scene {
|
||
gameId := int(args.GetGameId())
|
||
gameMode := int(args.GetGameMode())
|
||
sp := GetScenePolicy(gameId, gameMode)
|
||
if sp == nil {
|
||
logger.Logger.Errorf("Game id %v not register in ScenePolicyPool.", gameId)
|
||
return nil
|
||
}
|
||
|
||
tNow := time.Now()
|
||
s := &Scene{
|
||
WGCreateScene: args.WGCreateScene,
|
||
ws: args.Session,
|
||
Players: make(map[int32]*Player),
|
||
audiences: make(map[int32]*Player),
|
||
sp: sp,
|
||
GameStartTime: tNow,
|
||
inviteInterval: model.GameParamData.RobotInviteInitInterval,
|
||
bEnterAfterStart: args.GetEnterAfterStart(),
|
||
ChessRank: args.GetChessRank(),
|
||
KeyGameId: strconv.Itoa(int(args.GetGameId())),
|
||
KeyGamefreeId: strconv.Itoa(int(args.GetDBGameFree().GetId())),
|
||
KeyGameDif: args.GetDBGameFree().GetGameDif(),
|
||
}
|
||
s.CycleID, _ = model.AutoIncGameLogId()
|
||
s.rrVer = ReplayRecorderVer[gameId]
|
||
s.RecordReplayStart()
|
||
s.init()
|
||
return s
|
||
}
|
||
|
||
func (this *Scene) GetSceneType() int32 {
|
||
if this.GetDBGameFree() != nil {
|
||
return this.GetDBGameFree().GetSceneType()
|
||
}
|
||
return 0
|
||
}
|
||
|
||
func (this *Scene) GetInit() bool {
|
||
return this.init()
|
||
}
|
||
|
||
func (this *Scene) init() bool {
|
||
tNow := time.Now()
|
||
sceneRandSeed++
|
||
this.Rand = rand.New(rand.NewSource(sceneRandSeed))
|
||
this.nextInviteTime = tNow.Add(time.Second * time.Duration(this.Rand.Int63n(model.GameParamData.RobotInviteInitInterval)))
|
||
this.RandRobotCnt()
|
||
return true
|
||
}
|
||
|
||
func (this *Scene) GetParam(idx int) int64 {
|
||
if idx < 0 || idx >= len(this.Params) {
|
||
return -1
|
||
}
|
||
|
||
return this.Params[idx]
|
||
}
|
||
|
||
func (this *Scene) GetBetMap() []int64 {
|
||
return this.GetDBGameFree().GetOtherIntParams()
|
||
}
|
||
|
||
func (this *Scene) GetGameFreeId() int32 {
|
||
return this.GetDBGameFree().GetId()
|
||
}
|
||
|
||
func (this *Scene) GetKeyGameId() string {
|
||
return this.KeyGameId
|
||
}
|
||
|
||
func (this *Scene) SetKeyGameId(keyGameId string) {
|
||
this.KeyGameId = keyGameId
|
||
}
|
||
|
||
func (this *Scene) GetSceneId() int {
|
||
return int(this.SceneId)
|
||
}
|
||
|
||
func (this *Scene) SetSceneId(sceneId int) {
|
||
this.SceneId = int32(sceneId)
|
||
}
|
||
|
||
func (this *Scene) GetGroupId() int32 {
|
||
return this.GroupId
|
||
}
|
||
|
||
func (this *Scene) SetGroupId(groupId int32) {
|
||
this.GroupId = groupId
|
||
}
|
||
|
||
func (this *Scene) GetExtraData() interface{} {
|
||
return this.ExtraData
|
||
}
|
||
|
||
func (this *Scene) SetExtraData(data interface{}) {
|
||
this.ExtraData = data
|
||
}
|
||
|
||
func (this *Scene) GetSceneState() SceneState {
|
||
return this.SceneState
|
||
}
|
||
|
||
func (this *Scene) SetSceneState(state SceneState) {
|
||
this.SceneState = state
|
||
}
|
||
|
||
func (this *Scene) GetGameId() int {
|
||
return int(this.GameId)
|
||
}
|
||
|
||
func (this *Scene) SetGameId(gameId int) {
|
||
this.GameId = int32(gameId)
|
||
}
|
||
|
||
func (this *Scene) GetPlayerNum() int {
|
||
n := this.WGCreateScene.GetPlayerNum()
|
||
if n > 0 {
|
||
return int(n)
|
||
}
|
||
return int(this.PlayerNum)
|
||
}
|
||
|
||
func (this *Scene) SetPlayerNum(playerNum int) {
|
||
this.WGCreateScene.PlayerNum = int32(playerNum)
|
||
this.PlayerNum = int32(playerNum)
|
||
}
|
||
|
||
func (this *Scene) GetGameMode() int {
|
||
return int(this.GameMode)
|
||
}
|
||
|
||
func (this *Scene) SetGameMode(gameMode int) {
|
||
this.GameMode = int32(gameMode)
|
||
}
|
||
|
||
func (this *Scene) GetGaming() bool {
|
||
return this.Gaming
|
||
}
|
||
|
||
func (this *Scene) SetGaming(gaming bool) {
|
||
this.Gaming = gaming
|
||
}
|
||
|
||
func (this *Scene) GetTesting() bool {
|
||
return this.Testing
|
||
}
|
||
|
||
func (this *Scene) SetTesting(testing bool) {
|
||
this.Testing = testing
|
||
}
|
||
|
||
func (this *Scene) GetCreator() int32 {
|
||
return this.Creator
|
||
}
|
||
|
||
func (this *Scene) SetCreator(creator int32) {
|
||
this.Creator = creator
|
||
}
|
||
|
||
func (this *Scene) GetSceneMode() int {
|
||
return int(this.SceneMode)
|
||
}
|
||
|
||
func (this *Scene) SetSceneMode(sceneMode int) {
|
||
this.SceneMode = int32(sceneMode)
|
||
}
|
||
|
||
func (this *Scene) GetParams() []int64 {
|
||
return this.Params
|
||
}
|
||
|
||
func (this *Scene) GetStateStartTime() time.Time {
|
||
return this.StateStartTime
|
||
}
|
||
|
||
func (this *Scene) SetStateStartTime(stateStartTime time.Time) {
|
||
this.StateStartTime = stateStartTime
|
||
}
|
||
|
||
func (this *Scene) GetGameStartTime() time.Time {
|
||
return this.GameStartTime
|
||
}
|
||
|
||
func (this *Scene) SetGameStartTime(gameStartTime time.Time) {
|
||
this.GameStartTime = gameStartTime
|
||
}
|
||
|
||
func (this *Scene) GetGameNowTime() time.Time {
|
||
return this.GameNowTime
|
||
}
|
||
|
||
func (this *Scene) SetGameNowTime(gameNowTime time.Time) {
|
||
this.GameNowTime = gameNowTime
|
||
}
|
||
|
||
func (this *Scene) GetNumOfGames() int {
|
||
return this.NumOfGames
|
||
}
|
||
|
||
func (this *Scene) SetNumOfGames(numOfGames int) {
|
||
this.NumOfGames = numOfGames
|
||
}
|
||
|
||
func (this *Scene) GetCpCtx() model.CoinPoolCtx {
|
||
return this.CpCtx
|
||
}
|
||
|
||
func (this *Scene) SetCpCtx(cpCtx model.CoinPoolCtx) {
|
||
this.CpCtx = cpCtx
|
||
}
|
||
|
||
func (this *Scene) GetAudiences() map[int32]*Player {
|
||
return this.audiences
|
||
}
|
||
|
||
func (this *Scene) GetDisbandGen() int {
|
||
return this.disbandGen
|
||
}
|
||
|
||
func (this *Scene) SetDisbandGen(disbandGen int) {
|
||
this.disbandGen = disbandGen
|
||
}
|
||
|
||
func (this *Scene) GetScenePolicy() ScenePolicy {
|
||
return this.sp
|
||
}
|
||
func (this *Scene) SetScenePolicy(sp ScenePolicy) {
|
||
this.sp = sp
|
||
}
|
||
func (this *Scene) GetGraceDestroy() bool {
|
||
return this.graceDestroy
|
||
}
|
||
func (this *Scene) SetGraceDestroy() {
|
||
this.graceDestroy = true
|
||
}
|
||
|
||
func (this *Scene) GetCpControlled() bool {
|
||
return this.CpControlled
|
||
}
|
||
func (this *Scene) SetCpControlled(cpControlled bool) {
|
||
this.CpControlled = cpControlled
|
||
}
|
||
|
||
func (this *Scene) GetSystemCoinOut() int64 {
|
||
return this.SystemCoinOut
|
||
}
|
||
func (this *Scene) SetSystemCoinOut(systemCoinOut int64) {
|
||
this.SystemCoinOut = systemCoinOut
|
||
}
|
||
|
||
func (this *Scene) GetBEnterAfterStart() bool {
|
||
return this.bEnterAfterStart
|
||
}
|
||
func (this *Scene) SetBEnterAfterStart(bEnterAfterStart bool) {
|
||
this.bEnterAfterStart = bEnterAfterStart
|
||
}
|
||
|
||
func (this *Scene) GetTimerRandomRobot() int64 {
|
||
return this.timerRandomRobot
|
||
}
|
||
func (this *Scene) SetTimerRandomRobot(timerRandomRobot int64) {
|
||
this.timerRandomRobot = timerRandomRobot
|
||
}
|
||
|
||
func (this *Scene) GetDestroyed() bool {
|
||
return this.destroyed
|
||
}
|
||
func (this *Scene) SetDestroyed(destroyed bool) {
|
||
this.destroyed = destroyed
|
||
}
|
||
|
||
// ////////////////////////////////////////////////
|
||
func (this *Scene) OnStart() {
|
||
logger.Logger.Trace("Scene on start.")
|
||
this.sp.OnStart(this)
|
||
this.TryInviteRobot()
|
||
}
|
||
|
||
func (this *Scene) OnStop() {
|
||
logger.Logger.Trace("Scene on stop.")
|
||
this.sp.OnStop(this)
|
||
}
|
||
|
||
func (this *Scene) OnTick() {
|
||
if !this.pause {
|
||
this.TryInviteRobot()
|
||
this.sp.OnTick(this)
|
||
}
|
||
}
|
||
func (this *Scene) SendRoomType(p *Player) {
|
||
//通知客户端 当前房间类型
|
||
//RoomSign := &protocol.SCClubRoomSign{
|
||
// ClubId: proto.Int64(this.ClubId),
|
||
//}
|
||
//proto.SetDefaults(RoomSign)
|
||
//logger.Logger.Trace("RoomSign: ", RoomSign)
|
||
//p.SendToClient(int(protocol.MmoPacketID_PACKET_SC_CLUB_ROOMSIGN), RoomSign)
|
||
}
|
||
|
||
//////////////////////////////////////////////////
|
||
|
||
func (this *Scene) PlayerEnter(p *Player, isLoaded bool) {
|
||
logger.Logger.Trace("(this *Scene) PlayerEnter:", p.SnId, isLoaded, this.SceneId, p.GetName())
|
||
this.Players[p.SnId] = p
|
||
p.scene = this
|
||
|
||
pack := &gamehall.SCEnterRoom{
|
||
GameId: this.GameId,
|
||
ModeType: this.GameMode,
|
||
RoomId: this.SceneId,
|
||
OpRetCode: gamehall.OpResultCode_Game_OPRC_Sucess_Game,
|
||
Params: []int32{},
|
||
ClubId: proto.Int32(this.ClubId),
|
||
}
|
||
proto.SetDefaults(pack)
|
||
p.SendToClient(int(gamehall.GameHallPacketID_PACKET_SC_ENTERROOM), pack)
|
||
|
||
if p.IsRob {
|
||
this.robotNum++
|
||
logger.Logger.Tracef("(this *Scene) PlayerEnter(%v) robot(%v) robotlimit(%v)", this.GetDBGameFree().GetName()+this.GetDBGameFree().GetTitle(), this.robotNum, this.robotLimit)
|
||
} else {
|
||
p.Trusteeship = 0
|
||
p.ValidCacheBetTotal = 0
|
||
this.realPlayerNum++
|
||
this.RandRobotCnt()
|
||
}
|
||
|
||
p.OnEnter(this)
|
||
p.SyncFlagToWorld()
|
||
if !isLoaded && !p.IsRob { //等待玩家加载
|
||
p.MarkFlag(PlayerState_Leave)
|
||
}
|
||
//避免游戏接口异常
|
||
utils.RunPanicless(func() { this.sp.OnPlayerEnter(this, p) })
|
||
|
||
if p.WBLevel < 0 {
|
||
WarningBlackPlayer(p.SnId, this.GetDBGameFree().Id)
|
||
}
|
||
|
||
this.ResetNextInviteTime()
|
||
}
|
||
|
||
func (this *Scene) PlayerLeave(p *Player, reason int, isBill bool) {
|
||
logger.Logger.Trace("===(this *Scene) PlayerLeave ", p.SnId, reason, isBill)
|
||
//logger.Logger.Trace(utils.GetCallStack())
|
||
if _, exist := this.Players[p.SnId]; !exist {
|
||
logger.Logger.Warnf("(this *Scene) PlayerLeave(%v) no found in scene(%v)", p.SnId, this.SceneId)
|
||
return
|
||
}
|
||
|
||
//当前状态不能离场
|
||
if !this.CanChangeCoinScene(p) && !this.destroyed {
|
||
pack := &gamehall.SCLeaveRoom{
|
||
//OpRetCode: p.opCode, //protocol.OpResultCode_OPRC_Hundred_YouHadBetCannotLeave,
|
||
OpRetCode: gamehall.OpResultCode_Game(p.OpCode),
|
||
RoomId: this.SceneId,
|
||
}
|
||
if pack.GetOpRetCode() == gamehall.OpResultCode_Game_OPRC_Sucess_Game {
|
||
//不能这么做,机器人有特殊判定
|
||
//pack.OpRetCode = gamehall.OpResultCode_OPRC_Error
|
||
pack.OpRetCode = gamehall.OpResultCode_Game_OPRC_Error_Game
|
||
}
|
||
proto.SetDefaults(pack)
|
||
p.SendToClient(int(gamehall.GameHallPacketID_PACKET_SC_LEAVEROOM), pack)
|
||
logger.Logger.Tracef("(this *Scene) Cant PlayerLeave(%v) no found in scene(%v)", p.SnId, this.SceneId)
|
||
return
|
||
}
|
||
|
||
//避免游戏接口异常
|
||
utils.RunPanicless(func() { this.sp.OnPlayerLeave(this, p, reason) })
|
||
|
||
p.OnLeave(reason)
|
||
delete(this.Players, p.SnId)
|
||
isBill = true
|
||
|
||
//send world离开房间
|
||
pack := &server.GWPlayerLeave{
|
||
RoomId: this.SceneId,
|
||
PlayerId: proto.Int32(p.SnId),
|
||
Reason: proto.Int(reason),
|
||
ServiceFee: proto.Int64(p.serviceFee),
|
||
GameTimes: proto.Int32(p.GameTimes),
|
||
BetCoin: proto.Int64(p.TotalBet),
|
||
WinTimes: proto.Int(p.winTimes),
|
||
LostTimes: proto.Int(p.lostTimes),
|
||
TotalConvertibleFlow: proto.Int64(p.TotalConvertibleFlow),
|
||
ValidCacheBetTotal: proto.Int64(p.ValidCacheBetTotal),
|
||
MatchId: this.GetMatch().GetMatchSortId(),
|
||
CurIsWin: proto.Int64(p.CurIsWin), // 负数:输 0:平局 正数:赢
|
||
}
|
||
matchRobotGrades := p.MatchRobotGrades
|
||
if matchRobotGrades != nil {
|
||
pack.MatchRobotGrades = make(map[int32]int32)
|
||
for _, gradeInfo := range matchRobotGrades {
|
||
pack.MatchRobotGrades[gradeInfo.CopySnid] = proto.Int32(gradeInfo.Grade)
|
||
}
|
||
p.MatchRobotGrades = nil
|
||
}
|
||
|
||
pack.ReturnCoin = proto.Int64(p.Coin)
|
||
if this.Testing {
|
||
pack.ReturnCoin = proto.Int64(p.takeCoin)
|
||
}
|
||
pack.GameCoinTs = proto.Int64(p.GameCoinTs)
|
||
if !p.IsLocal {
|
||
data, err := p.MarshalData(int(this.GameId))
|
||
if err == nil {
|
||
pack.PlayerData = data
|
||
}
|
||
}
|
||
|
||
//pack.Items = make(map[int32]int64)
|
||
//for id, num := range p.Items {
|
||
// pack.Items[id] = num
|
||
//}
|
||
pack.RankScore = make(map[int32]int64)
|
||
for k, v := range p.RankScore {
|
||
pack.RankScore[k] = v
|
||
}
|
||
|
||
proto.SetDefaults(pack)
|
||
this.SendToWorld(int(server.SSPacketID_PACKET_GW_PLAYERLEAVE), pack)
|
||
logger.Logger.Tracef("(this *Scene) PlayerLeave(%v) success reason %v", p.SnId, reason)
|
||
|
||
if p.IsRob {
|
||
this.robotNum--
|
||
if this.robotNum != len(this.Players) {
|
||
var num int
|
||
for _, p2 := range this.Players {
|
||
if p2.IsRob {
|
||
num++
|
||
}
|
||
}
|
||
this.robotNum = num
|
||
}
|
||
logger.Logger.Tracef("(this *Scene) PlayerLeave(%v) robot(%v) robotlimit(%v)", this.GetDBGameFree().GetName()+this.GetDBGameFree().GetTitle(), this.robotNum, this.robotLimit)
|
||
} else {
|
||
this.realPlayerNum--
|
||
this.RandRobotCnt()
|
||
}
|
||
|
||
this.ResetNextInviteTime()
|
||
}
|
||
|
||
func (this *Scene) AudienceEnter(p *Player, isload bool) {
|
||
logger.Logger.Trace("(this *Scene) AudienceEnter")
|
||
this.audiences[p.SnId] = p
|
||
p.scene = this
|
||
p.MarkFlag(PlayerState_Audience)
|
||
pack := &gamehall.SCEnterRoom{
|
||
GameId: this.GameId,
|
||
ModeType: this.GameMode,
|
||
RoomId: this.SceneId,
|
||
OpRetCode: gamehall.OpResultCode_Game_OPRC_Sucess_Game,
|
||
}
|
||
proto.SetDefaults(pack)
|
||
p.SendToClient(int(gamehall.GameHallPacketID_PACKET_SC_ENTERROOM), pack)
|
||
|
||
p.OnAudienceEnter(this)
|
||
if !isload && !p.IsRob {
|
||
p.MarkFlag(PlayerState_Leave)
|
||
}
|
||
//避免游戏接口异常
|
||
utils.RunPanicless(func() { this.sp.OnAudienceEnter(this, p) })
|
||
}
|
||
|
||
func (this *Scene) AudienceLeave(p *Player, reason int) {
|
||
logger.Logger.Trace("(this *Scene) AudienceLeave")
|
||
//当前状态不能离场
|
||
if !this.CanChangeCoinScene(p) {
|
||
pack := &gamehall.SCLeaveRoom{
|
||
OpRetCode: gamehall.OpResultCode_Game(p.OpCode), //protocol.OpResultCode_OPRC_Hundred_YouHadBetCannotLeave,
|
||
RoomId: this.SceneId,
|
||
}
|
||
proto.SetDefaults(pack)
|
||
p.SendToClient(int(gamehall.GameHallPacketID_PACKET_SC_LEAVEROOM), pack)
|
||
return
|
||
}
|
||
//避免游戏接口异常
|
||
utils.RunPanicless(func() { this.sp.OnAudienceLeave(this, p, reason) })
|
||
p.OnAudienceLeave(reason)
|
||
delete(this.audiences, p.SnId)
|
||
//send world离开房间
|
||
pack := &server.GWPlayerLeave{
|
||
RoomId: this.SceneId,
|
||
PlayerId: proto.Int32(p.SnId),
|
||
Reason: proto.Int(reason),
|
||
TotalConvertibleFlow: proto.Int64(p.TotalConvertibleFlow),
|
||
ValidCacheBetTotal: proto.Int64(p.ValidCacheBetTotal),
|
||
}
|
||
pack.ReturnCoin = proto.Int64(p.Coin)
|
||
if this.Testing {
|
||
pack.ReturnCoin = proto.Int64(p.takeCoin)
|
||
}
|
||
pack.GameCoinTs = proto.Int64(p.GameCoinTs)
|
||
// if p.dirty {
|
||
// data, err := p.MarshalData(this.gameId)
|
||
// if err == nil {
|
||
// pack.PlayerData = data
|
||
// }
|
||
// }
|
||
proto.SetDefaults(pack)
|
||
this.SendToWorld(int(server.SSPacketID_PACKET_GW_AUDIENCELEAVE), pack)
|
||
}
|
||
|
||
func (this *Scene) AudienceSit(p *Player) {
|
||
logger.Logger.Trace("(this *Scene) AudienceSit")
|
||
if _, exist := this.audiences[p.SnId]; exist {
|
||
delete(this.audiences, p.SnId)
|
||
|
||
this.Players[p.SnId] = p
|
||
p.scene = this
|
||
|
||
p.OnEnter(this)
|
||
//避免游戏接口异常
|
||
utils.RunPanicless(func() { this.sp.OnAudienceSit(this, p) })
|
||
if !p.IsRob {
|
||
this.realPlayerNum++
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *Scene) HasPlayer(p *Player) bool {
|
||
if p == nil {
|
||
return false
|
||
}
|
||
|
||
if pp, ok := this.Players[p.SnId]; ok && pp == p {
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
|
||
func (this *Scene) HasAudience(p *Player) bool {
|
||
if p == nil {
|
||
return false
|
||
}
|
||
|
||
if pp, ok := this.audiences[p.SnId]; ok && pp == p {
|
||
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) GetPlayerByPos(pos int) *Player {
|
||
for _, p := range this.Players {
|
||
if p.Pos == pos {
|
||
return p
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (this *Scene) PlayerDropLine(snid int32) {
|
||
logger.Logger.Trace("(this *Scene) PlayerDropLine")
|
||
if p, exist := this.Players[snid]; exist {
|
||
p.OnDropLine()
|
||
//避免游戏接口异常
|
||
utils.RunPanicless(func() { this.sp.OnPlayerDropLine(this, p) })
|
||
} else if p, exist := this.audiences[snid]; exist {
|
||
p.OnAudienceDropLine()
|
||
//避免游戏接口异常
|
||
utils.RunPanicless(func() { this.sp.OnAudienceDropLine(this, p) })
|
||
}
|
||
}
|
||
|
||
func (this *Scene) PlayerRehold(snid int32, sid int64, gs *netlib.Session) {
|
||
logger.Logger.Trace("(this *Scene) PlayerRehold")
|
||
if p, exist := this.Players[snid]; exist {
|
||
p.OnRehold(sid, gs)
|
||
//if !p.IsRob {
|
||
// p.trusteeship = 0
|
||
//}
|
||
//避免游戏接口异常
|
||
utils.RunPanicless(func() { this.sp.OnPlayerRehold(this, p) })
|
||
} else if p, exist := this.audiences[snid]; exist {
|
||
p.OnRehold(sid, gs)
|
||
//if !p.IsRob {
|
||
// p.trusteeship = 0
|
||
//}
|
||
//避免游戏接口异常
|
||
utils.RunPanicless(func() { this.sp.OnAudienceEnter(this, p) })
|
||
}
|
||
}
|
||
|
||
func (this *Scene) PlayerReturn(p *Player, isLoaded bool) {
|
||
logger.Logger.Trace("(this *Scene) PlayerReturn")
|
||
pack := &gamehall.SCReturnRoom{
|
||
RoomId: this.SceneId,
|
||
GameId: this.GameId,
|
||
ModeType: this.GameMode,
|
||
Params: common.CopySliceInt64ToInt32(this.Params),
|
||
HallId: this.GetDBGameFree().GetId(),
|
||
IsLoaded: proto.Bool(isLoaded),
|
||
OpRetCode: gamehall.OpResultCode_Game_OPRC_Sucess_Game,
|
||
ClubId: proto.Int32(this.ClubId),
|
||
}
|
||
proto.SetDefaults(pack)
|
||
p.SendToClient(int(gamehall.GameHallPacketID_PACKET_SC_RETURNROOM), pack)
|
||
logger.Logger.Tracef("Scene.PlayerReturn %v", pack)
|
||
//if !p.IsRob {
|
||
// p.trusteeship = 0
|
||
//}
|
||
if this.HasPlayer(p) {
|
||
//避免游戏接口异常
|
||
//utils.RunPanicless(func() { this.sp.OnPlayerRehold(this, p) })
|
||
//这里应该调用 return消息 因为在上面rehold的消息已经处理过了
|
||
utils.RunPanicless(func() { this.sp.OnPlayerReturn(this, p) })
|
||
} else if this.HasAudience(p) {
|
||
//避免游戏接口异常
|
||
utils.RunPanicless(func() { this.sp.OnAudienceEnter(this, p) })
|
||
}
|
||
if !p.IsRob { //等待玩家加载
|
||
if isLoaded {
|
||
p.UnmarkFlag(PlayerState_Leave)
|
||
} else {
|
||
p.MarkFlag(PlayerState_Leave)
|
||
}
|
||
}
|
||
if this.IsMatchScene() {
|
||
p.SetIParam(common.PlayerIParam_IsQuit, 0)
|
||
p.UnmarkFlag(PlayerState_MatchQuit)
|
||
}
|
||
}
|
||
|
||
// 广播消息
|
||
func (this *Scene) Broadcast(packetid int, msg rawproto.Message, excludeSid int64, includeOffline ...bool) {
|
||
excludePos := -1
|
||
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() && !p.IsMarkFlag(PlayerState_Leave)) || len(includeOffline) != 0 {
|
||
mgs[p.gateSess] = append(mgs[p.gateSess], &srvlibproto.MCSessionUnion{
|
||
Mccs: &srvlibproto.MCClientSession{
|
||
SId: proto.Int64(p.sid),
|
||
},
|
||
})
|
||
}
|
||
}
|
||
if p.sid == excludeSid {
|
||
excludePos = p.Pos
|
||
}
|
||
}
|
||
}
|
||
for _, p := range this.audiences {
|
||
if p != nil && p.sid != excludeSid {
|
||
if (p.gateSess != nil && p.IsOnLine() && !p.IsMarkFlag(PlayerState_Leave)) || len(includeOffline) != 0 {
|
||
mgs[p.gateSess] = append(mgs[p.gateSess], &srvlibproto.MCSessionUnion{
|
||
Mccs: &srvlibproto.MCClientSession{
|
||
SId: proto.Int64(p.sid),
|
||
},
|
||
})
|
||
}
|
||
}
|
||
}
|
||
if this.rr != nil && !this.Testing && this.Gaming && !this.IsHundredScene() && !this.IsMatchScene() {
|
||
this.rr.Record(-1, excludePos, packetid, msg)
|
||
}
|
||
for gateSess, v := range mgs {
|
||
if gateSess != nil && len(v) != 0 {
|
||
action.MulticastMessageToServer(gateSess, packetid, msg, v...)
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *Scene) RobotBroadcast(packetid int, msg rawproto.Message) {
|
||
mgs := make(map[*netlib.Session][]*srvlibproto.MCSessionUnion)
|
||
for _, p := range this.Players {
|
||
if p != nil && p.IsRob {
|
||
if p.gateSess != nil && p.IsOnLine() && !p.IsMarkFlag(PlayerState_Leave) {
|
||
mgs[p.gateSess] = append(mgs[p.gateSess], &srvlibproto.MCSessionUnion{
|
||
Mccs: &srvlibproto.MCClientSession{
|
||
SId: proto.Int64(p.sid),
|
||
},
|
||
})
|
||
}
|
||
}
|
||
}
|
||
for gateSess, v := range mgs {
|
||
if gateSess != nil && len(v) != 0 {
|
||
action.MulticastMessageToServer(gateSess, packetid, msg, v...)
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *Scene) BroadcastToAudience(packetid int, msg rawproto.Message) {
|
||
if len(this.audiences) > 0 {
|
||
mgs := make(map[*netlib.Session][]*srvlibproto.MCSessionUnion)
|
||
for _, p := range this.audiences {
|
||
if p != nil {
|
||
if p.gateSess != nil && p.IsOnLine() {
|
||
mgs[p.gateSess] = append(mgs[p.gateSess], &srvlibproto.MCSessionUnion{
|
||
Mccs: &srvlibproto.MCClientSession{
|
||
SId: proto.Int64(p.sid),
|
||
},
|
||
})
|
||
}
|
||
}
|
||
}
|
||
for gateSess, v := range mgs {
|
||
if gateSess != nil && len(v) != 0 {
|
||
action.MulticastMessageToServer(gateSess, packetid, msg, v...)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *Scene) GetAudiencesNum() int {
|
||
if this.audiences != nil {
|
||
return len(this.audiences)
|
||
}
|
||
return 0
|
||
}
|
||
|
||
func (this *Scene) ChangeSceneState(stateid int) {
|
||
if this.destroyed {
|
||
return
|
||
}
|
||
state := this.sp.GetSceneState(this, stateid)
|
||
if state == nil {
|
||
return
|
||
}
|
||
oldState := -1
|
||
if this.SceneState != nil {
|
||
oldState = this.SceneState.GetState()
|
||
if this.SceneState.CanChangeTo(state) {
|
||
logger.Logger.Tracef("(this *Scene) [%v] ChangeSceneState %v -> %v", this.SceneId, this.SceneState.GetState(), state.GetState())
|
||
|
||
this.SceneState.OnLeave(this)
|
||
this.SceneState = state
|
||
this.SceneState.OnEnter(this)
|
||
this.sp.NotifyGameState(this)
|
||
} else {
|
||
logger.Logger.Tracef("(this *Scene) [%v] ChangeSceneState failed %v -> %v", this.SceneId, this.SceneState.GetState(), state.GetState())
|
||
}
|
||
} else {
|
||
logger.Logger.Tracef("(this *Scene) [%v] ChangeSceneState -> %v", this.SceneId, state.GetState())
|
||
this.SceneState = state
|
||
this.SceneState.OnEnter(this)
|
||
//this.SyncSceneState(stateid)
|
||
}
|
||
|
||
if this.aiMgr != nil {
|
||
this.aiMgr.OnChangeState(this, oldState, stateid)
|
||
}
|
||
}
|
||
|
||
func (this *Scene) SendToWorld(packetid int, pack interface{}) {
|
||
if this.ws != nil {
|
||
this.ws.Send(packetid, pack)
|
||
}
|
||
}
|
||
|
||
func (this *Scene) FirePlayerEvent(p *Player, evtcode int, params []int64) {
|
||
if this.SceneState != nil {
|
||
this.SceneState.OnPlayerEvent(this, p, evtcode, params)
|
||
}
|
||
////比赛事件
|
||
//if this.mp != nil {
|
||
// this.mp.OnPlayerEvent(this, p, evtcode, params)
|
||
//}
|
||
}
|
||
|
||
func (this *Scene) Pause() {
|
||
this.pause = true
|
||
}
|
||
|
||
// RankMatchDestroy 排位解散房间
|
||
func (this *Scene) RankMatchDestroy() {
|
||
if this.IsRankMatch() {
|
||
this.Destroy(true)
|
||
}
|
||
}
|
||
|
||
func (this *Scene) Destroy(force bool) {
|
||
|
||
this.destroyed = true
|
||
this.pause = true
|
||
|
||
if !this.IsMatchScene() {
|
||
for _, p := range this.Players {
|
||
this.PlayerLeave(p, common.PlayerLeaveReason_OnDestroy, true)
|
||
}
|
||
for _, p := range this.audiences {
|
||
this.AudienceLeave(p, common.PlayerLeaveReason_OnDestroy)
|
||
}
|
||
} else {
|
||
for _, p := range this.Players {
|
||
this.PlayerLeave(p, common.PlayerLeaveReason_OnBilled, true)
|
||
}
|
||
}
|
||
|
||
for _, p := range this.Players {
|
||
PlayerMgrSington.DelPlayerBySnId(p.SnId)
|
||
}
|
||
|
||
for _, p := range this.audiences {
|
||
PlayerMgrSington.DelPlayerBySnId(p.SnId)
|
||
}
|
||
|
||
isCompleted := this.sp.IsCompleted(this) || this.completed
|
||
SceneMgrSington.DestroyScene(int(this.SceneId))
|
||
pack := &server.GWDestroyScene{
|
||
SceneId: int64(this.SceneId),
|
||
IsCompleted: isCompleted,
|
||
}
|
||
proto.SetDefaults(pack)
|
||
this.SendToWorld(int(server.SSPacketID_PACKET_GW_DESTROYSCENE), pack)
|
||
logger.Logger.Trace("(this *Scene) Destroy(force bool) isCompleted", isCompleted)
|
||
}
|
||
|
||
// IsSceneMode 房间模式
|
||
func (this *Scene) IsSceneMode(mode int) bool {
|
||
return this.SceneMode == int32(mode)
|
||
}
|
||
|
||
func (this *Scene) IsPrivateScene() bool {
|
||
return this.IsSceneMode(common.SceneModePrivate) || this.IsSceneMode(common.SceneModePrivateMatch)
|
||
}
|
||
|
||
// IsFreePublic 自由桌
|
||
func (this *Scene) IsFreePublic() bool {
|
||
return this.GetDBGameFree().GetFreeMode() == 1
|
||
}
|
||
|
||
// IsRankMatch 排位赛
|
||
func (this *Scene) IsRankMatch() bool {
|
||
return this.GetDBGameFree().GetRankType() > 0
|
||
}
|
||
|
||
// IsMatchScene 比赛场
|
||
func (this *Scene) IsMatchScene() bool {
|
||
return this.IsSceneMode(common.SceneModeMatch)
|
||
}
|
||
|
||
func (this *Scene) IsCustom() bool {
|
||
if this.IsSceneMode(common.SceneModePrivateMatch) {
|
||
return true
|
||
}
|
||
return this.GetDBGameFree().GetIsCustom() > 0
|
||
}
|
||
|
||
func (this *Scene) IsFull() bool {
|
||
return len(this.Players) >= this.GetPlayerNum()
|
||
}
|
||
|
||
// 对战场
|
||
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) GetCoinSceneLowerThanKick() int64 {
|
||
if this.GetDBGameFree() != nil {
|
||
return this.GetDBGameFree().GetLowerThanKick()
|
||
}
|
||
return 0
|
||
}
|
||
|
||
func (this *Scene) GetCoinSceneMaxCoinLimit() int64 {
|
||
if this.GetDBGameFree() != nil {
|
||
return this.GetDBGameFree().GetMaxCoinLimit()
|
||
}
|
||
return 0
|
||
}
|
||
|
||
// CoinInLimitLocal 本地游戏入场限额检查
|
||
func (this *Scene) CoinInLimitLocal(coin int64) bool {
|
||
minCoin := this.GetLimitCoin()
|
||
if minCoin != 0 && coin < minCoin {
|
||
return false
|
||
}
|
||
if coin <= 0 {
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
|
||
// NotCoinInLimitType 金额超出入场限额,返回踢出类型
|
||
func (this *Scene) NotCoinInLimitType(coin int64) int {
|
||
if common.IsLocalGame(int(this.GameId)) {
|
||
minCoin := this.GetLimitCoin()
|
||
if minCoin != 0 && coin < minCoin {
|
||
return common.PlayerLeaveReason_Bekickout
|
||
}
|
||
if coin <= 0 {
|
||
return common.PlayerLeaveReason_Bekickout
|
||
}
|
||
return common.PlayerLeaveReason_Normal
|
||
}
|
||
|
||
minCoin := int(this.GetCoinSceneLowerThanKick())
|
||
maxCoin := int(this.GetCoinSceneMaxCoinLimit())
|
||
if minCoin != 0 && coin < int64(minCoin) {
|
||
return common.PlayerLeaveReason_Bekickout
|
||
}
|
||
if maxCoin != 0 && coin > int64(maxCoin) {
|
||
return common.PlayerLeaveReason_RoomMaxCoin
|
||
}
|
||
if coin <= 0 {
|
||
return common.PlayerLeaveReason_Bekickout
|
||
}
|
||
return common.PlayerLeaveReason_Normal
|
||
}
|
||
|
||
// CoinInLimit 单入场限额检查
|
||
func (this *Scene) CoinInLimit(coin int64) bool {
|
||
if common.IsLocalGame(int(this.GameId)) {
|
||
return this.CoinInLimitLocal(coin)
|
||
}
|
||
|
||
minCoin := int(this.GetCoinSceneLowerThanKick())
|
||
maxCoin := int(this.GetCoinSceneMaxCoinLimit())
|
||
if minCoin != 0 && coin < int64(minCoin) {
|
||
return false
|
||
}
|
||
if maxCoin != 0 && coin > int64(maxCoin) {
|
||
return false
|
||
}
|
||
if coin <= 0 {
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
|
||
// 根据底注去取createroom表里面的最小携带金额
|
||
func (this *Scene) GetLimitCoin() int64 {
|
||
limitCoin := int64(0)
|
||
tmpIds := []int32{}
|
||
for _, data := range srvdata.PBDB_CreateroomMgr.Datas.GetArr() {
|
||
if data.GameId == this.GameId && data.GameSite == this.GetDBGameFree().GetSceneType() {
|
||
betRange := data.GetBetRange()
|
||
if len(betRange) == 0 {
|
||
continue
|
||
}
|
||
for j := 0; j < len(betRange); j++ {
|
||
if betRange[j] == this.BaseScore && len(data.GetGoldRange()) > 0 && data.GetGoldRange()[0] != 0 {
|
||
tmpIds = append(tmpIds, data.GetId())
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if len(tmpIds) > 0 {
|
||
goldRange := srvdata.PBDB_CreateroomMgr.GetData(tmpIds[0]).GetGoldRange()
|
||
if len(goldRange) != 0 && goldRange[0] != 0 {
|
||
limitCoin = int64(goldRange[0])
|
||
}
|
||
if limitCoin != 0 {
|
||
for _, id := range tmpIds {
|
||
tmp := srvdata.PBDB_CreateroomMgr.GetData(id).GetGoldRange()
|
||
if int64(tmp[0]) < limitCoin && tmp[0] != 0 {
|
||
limitCoin = int64(tmp[0])
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return limitCoin
|
||
}
|
||
|
||
func (this *Scene) CoinOverMaxLimit(coin int64, p *Player) bool {
|
||
if this.Testing {
|
||
return false
|
||
}
|
||
if coin < 0 {
|
||
return false
|
||
}
|
||
|
||
if p.ExpectLeaveCoin != 0 && this.IsCoinScene() { //暂只对对战场生效
|
||
if p.ExpectLeaveCoin < p.takeCoin { //期望输的时候离场
|
||
if coin <= p.ExpectLeaveCoin {
|
||
return true
|
||
}
|
||
} else { //期望赢的时候离场
|
||
if coin >= p.ExpectLeaveCoin {
|
||
return true
|
||
}
|
||
}
|
||
} else {
|
||
if this.GetDBGameFree() != nil {
|
||
limit := this.GetDBGameFree().GetRobotLimitCoin()
|
||
if len(limit) >= 2 {
|
||
comp := common.RandInt(int(limit[0]), int(limit[1]))
|
||
if coin > int64(comp) {
|
||
return true
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return false
|
||
}
|
||
|
||
func (this *Scene) CorrectBillCoin(coin, limit1, limit2 int64) int64 {
|
||
if coin > limit1 {
|
||
coin = limit1
|
||
}
|
||
if coin > limit2 {
|
||
coin = limit2
|
||
}
|
||
return coin
|
||
}
|
||
|
||
func (this *Scene) GetCoinSceneServiceFee() int32 {
|
||
if this.GetDBGameFree() != nil {
|
||
return this.GetDBGameFree().GetServiceFee()
|
||
}
|
||
return 0
|
||
}
|
||
|
||
func (this *Scene) GetCoinSceneTypeId() int32 {
|
||
if this.GetDBGameFree() != nil {
|
||
return this.GetDBGameFree().Id
|
||
}
|
||
return 0
|
||
}
|
||
|
||
func (this *Scene) GetCoinSceneName() string {
|
||
if this.GetDBGameFree() != nil {
|
||
return this.GetDBGameFree().GetName() + this.GetDBGameFree().GetTitle()
|
||
}
|
||
return ""
|
||
}
|
||
|
||
func (this *Scene) GetHundredSceneName() string {
|
||
if this.IsHundredScene() && this.GetDBGameFree() != nil {
|
||
if this.GetDBGameFree().GetName() == this.GetDBGameFree().GetTitle() {
|
||
return this.GetDBGameFree().GetTitle()
|
||
} else {
|
||
return this.GetDBGameFree().GetName() + this.GetDBGameFree().GetTitle()
|
||
}
|
||
}
|
||
return ""
|
||
}
|
||
|
||
func (this *Scene) GetSceneName() string {
|
||
if this.IsCoinScene() {
|
||
return this.GetCoinSceneName()
|
||
} else if this.IsHundredScene() {
|
||
return this.GetHundredSceneName()
|
||
}
|
||
return ""
|
||
}
|
||
|
||
func (this *Scene) CanChangeCoinScene(p *Player) bool {
|
||
//if p.IsMarkFlag(PlayerState_Audience) {
|
||
// if this.drp != nil {
|
||
// return this.drp.CanChangeCoinScene(this, p)
|
||
// }
|
||
//}
|
||
//if this.mp != nil {
|
||
// if !this.mp.IsMatchEnd(this) {
|
||
// return false
|
||
// }
|
||
//}
|
||
if this.sp != nil {
|
||
return this.sp.CanChangeCoinScene(this, p)
|
||
}
|
||
return false
|
||
}
|
||
|
||
func (this *Scene) SyncPlayerCoin() {
|
||
//if this.Testing {
|
||
// return
|
||
//}
|
||
//pack := &server.GWSyncPlayerCoin{
|
||
// SceneId: proto.Int(this.SceneId),
|
||
//}
|
||
//switch this.GameId {
|
||
//case common.GameId_HFishing, common.GameId_TFishing:
|
||
// for _, value := range this.Players {
|
||
// if value.IsRob {
|
||
// continue
|
||
// }
|
||
// //todo dev 捕鱼的逻辑暂时不用 开发的时候再增加
|
||
// //if exData, ok := value.extraData.(*FishingPlayerData); ok {
|
||
// // if exData.CoinCache != value.LastSyncCoin {
|
||
// // pack.PlayerCoins = append(pack.PlayerCoins, int64(value.SnId))
|
||
// // pack.PlayerCoins = append(pack.PlayerCoins, exData.CoinCache)
|
||
// // value.LastSyncCoin = exData.CoinCache
|
||
// // }
|
||
// //}
|
||
// }
|
||
//default:
|
||
// for _, value := range this.Players {
|
||
// if value.Coin != value.LastSyncCoin && !value.IsRob {
|
||
// pack.PlayerCoins = append(pack.PlayerCoins, int64(value.SnId))
|
||
// pack.PlayerCoins = append(pack.PlayerCoins, value.Coin)
|
||
// value.LastSyncCoin = value.Coin
|
||
// }
|
||
// }
|
||
//}
|
||
//if len(pack.PlayerCoins) > 0 {
|
||
// proto.SetDefaults(pack)
|
||
// this.SendToWorld(int(server.SSPacketID_PACKET_GW_SYNCPLAYERCOIN), pack)
|
||
//}
|
||
}
|
||
|
||
func (this *Scene) SyncSceneState(state int) {
|
||
pack := &server.GWSceneState{
|
||
RoomId: int32(this.SceneId),
|
||
RoomState: int32(state),
|
||
}
|
||
this.SendToWorld(int(server.SSPacketID_PACKET_GW_SCENESTATE), pack)
|
||
}
|
||
|
||
func (this *Scene) NotifySceneRoundStart(round int) {
|
||
pack := &server.GWSceneStart{
|
||
RoomId: this.SceneId,
|
||
CurrRound: proto.Int(round),
|
||
Start: proto.Bool(true),
|
||
MaxRound: this.TotalOfGames,
|
||
}
|
||
proto.SetDefaults(pack)
|
||
this.SendToWorld(int(server.SSPacketID_PACKET_GW_SCENESTART), pack)
|
||
}
|
||
|
||
func (this *Scene) NotifySceneRoundPause() {
|
||
pack := &server.GWSceneStart{
|
||
RoomId: this.SceneId,
|
||
Start: proto.Bool(false),
|
||
CurrRound: proto.Int(this.NumOfGames),
|
||
MaxRound: this.TotalOfGames,
|
||
}
|
||
proto.SetDefaults(pack)
|
||
this.SendToWorld(int(server.SSPacketID_PACKET_GW_SCENESTART), pack)
|
||
}
|
||
|
||
// SyncScenePlayer 游戏开始的时候同步防伙牌数据
|
||
func (this *Scene) SyncScenePlayer() {
|
||
pack := &server.GWScenePlayerLog{
|
||
GameId: this.GameId,
|
||
GameFreeId: proto.Int32(this.GetDBGameFree().GetId()),
|
||
}
|
||
for _, value := range this.Players {
|
||
if value.IsRob || !value.IsGameing() {
|
||
continue
|
||
}
|
||
pack.Snids = append(pack.Snids, value.SnId)
|
||
}
|
||
this.SendToWorld(int(server.SSPacketID_PACKET_GW_SCENEPLAYERLOG), pack)
|
||
}
|
||
|
||
func (this *Scene) RecordReplayStart() {
|
||
if !this.IsHundredScene() && !this.IsMatchScene() {
|
||
logger.Logger.Trace("RecordReplayStart-----", this.GetReplayCode(), this.NumOfGames, this.replayAddId)
|
||
id := fmt.Sprintf("%d%d%v%d", this.GameId, this.SceneId, this.GameNowTime.Format(ReplayIdTf), this.replayAddId)
|
||
this.rr = NewReplayRecorder(id)
|
||
}
|
||
}
|
||
|
||
func (this *Scene) RecordReplayOver() {
|
||
if !this.Testing && !this.IsHundredScene() && !this.IsMatchScene() {
|
||
logger.Logger.Trace("RecordReplayOver-----", this.GetReplayCode(), this.NumOfGames, this.replayAddId)
|
||
this.replayAddId++
|
||
this.rr.Fini(this)
|
||
|
||
this.RecordReplayStart()
|
||
}
|
||
}
|
||
|
||
// TryDismissRob 尝试机器人离场
|
||
func (this *Scene) TryDismissRob(params ...int) {
|
||
if this.IsMatchScene() {
|
||
return
|
||
}
|
||
if this.IsCoinScene() {
|
||
allRobot := true
|
||
for _, p := range this.Players {
|
||
if !p.IsRob {
|
||
allRobot = false
|
||
break
|
||
}
|
||
}
|
||
//一次离开一个
|
||
hasLeave := false
|
||
if allRobot && !this.IsPreCreateScene() {
|
||
for _, p := range this.Players {
|
||
if p.IsRob {
|
||
this.PlayerLeave(p, common.PlayerLeaveReason_Normal, true)
|
||
hasLeave = true
|
||
}
|
||
}
|
||
}
|
||
|
||
//当局已经检查过了
|
||
if this.nogDismiss == this.NumOfGames {
|
||
return
|
||
}
|
||
this.nogDismiss = this.NumOfGames
|
||
|
||
//如果是满桌并且是禁止匹配真人,那么保持满桌几局
|
||
if this.GetDBGameFree().GetMatchTrueMan() == common.MatchTrueMan_Forbid && this.IsFull() && rand.Intn(4) == 1 {
|
||
hasLeave = true
|
||
}
|
||
|
||
if !hasLeave && !this.Testing {
|
||
for _, p := range this.Players {
|
||
rands := this.Rand.Int63n(20) + 20
|
||
a := float64(p.Coin) / float64(p.takeCoin)
|
||
if p != nil && p.IsRob && a >= float64(rands)/10 {
|
||
this.PlayerLeave(p, common.PlayerLeaveReason_Normal, true)
|
||
hasLeave = true
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
if !hasLeave && this.GetDBGameFree().GetMatchTrueMan() != common.MatchTrueMan_Forbid && len(params) > 0 &&
|
||
params[0] == 1 && this.IsFull() && common.RandInt(10000) < 4000 {
|
||
for _, r := range this.Players {
|
||
if r.IsRob {
|
||
this.PlayerLeave(r, common.PlayerLeaveReason_Normal, true)
|
||
hasLeave = true
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
if !hasLeave {
|
||
for _, r := range this.Players {
|
||
if r.IsRob {
|
||
if !r.IsGameing() { //5%的概率,不玩游戏直接离场
|
||
if rand.Intn(100) < 5 {
|
||
this.PlayerLeave(r, common.PlayerLeaveReason_Normal, true)
|
||
hasLeave = true
|
||
break
|
||
}
|
||
} else { //玩游戏的,玩几局有概率离场
|
||
expectTimes := 5 + rand.Int31n(20)
|
||
if r.GameTimes >= expectTimes {
|
||
this.PlayerLeave(r, common.PlayerLeaveReason_Normal, true)
|
||
hasLeave = true
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//如果当局有机器人离开,适当延长下下次邀请的时间
|
||
if hasLeave {
|
||
tNow := time.Now()
|
||
if this.nextInviteTime.Sub(tNow) < time.Second {
|
||
this.nextInviteTime = tNow.Add(time.Second * time.Duration(rand.Int31n(3)+1))
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *Scene) CreateGameRecPacket() *server.GWGameRec {
|
||
return &server.GWGameRec{
|
||
RoomId: this.SceneId,
|
||
NumOfGames: proto.Int(this.NumOfGames),
|
||
GameTime: proto.Int(int(time.Now().Sub(this.GameStartTime) / time.Second)),
|
||
}
|
||
}
|
||
|
||
func (this *Scene) IsAllReady() bool {
|
||
for _, p := range this.Players {
|
||
if !p.IsOnLine() || !p.IsReady() {
|
||
return false
|
||
}
|
||
}
|
||
return true
|
||
}
|
||
|
||
func (this *Scene) GetOnlineCnt() int {
|
||
cnt := 0
|
||
for _, p := range this.Players {
|
||
if p.IsOnLine() && !p.IsMarkFlag(PlayerState_Leave) {
|
||
cnt++
|
||
}
|
||
}
|
||
return cnt
|
||
}
|
||
|
||
func (this *Scene) GetRealPlayerCnt() int {
|
||
cnt := 0
|
||
for _, p := range this.Players {
|
||
if !p.IsRob {
|
||
cnt++
|
||
}
|
||
}
|
||
return cnt
|
||
}
|
||
|
||
func (this *Scene) GetGameingPlayerCnt() int {
|
||
cnt := 0
|
||
for _, p := range this.Players {
|
||
if p != nil && p.IsGameing() {
|
||
cnt += 1
|
||
}
|
||
}
|
||
return cnt
|
||
}
|
||
|
||
func (this *Scene) GetGameingRealPlayerCnt() int {
|
||
cnt := 0
|
||
for _, p := range this.Players {
|
||
if p != nil && p.IsGameing() && !p.IsRob {
|
||
cnt += 1
|
||
}
|
||
}
|
||
return cnt
|
||
}
|
||
|
||
func (this *Scene) GetRandomRobotPlayer() *Player {
|
||
robotArray := []*Player{}
|
||
for _, p := range this.Players {
|
||
if p != nil && p.IsGameing() && p.IsRob {
|
||
robotArray = append(robotArray, p)
|
||
}
|
||
}
|
||
if len(robotArray) > 0 {
|
||
return robotArray[common.RandInt(0, len(robotArray))]
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
func (this *Scene) CoinPoolCanOut() bool {
|
||
return true
|
||
/* 暂时屏蔽
|
||
noRobotPlayerCount := this.GetRealPlayerCnt()
|
||
setting := coinPoolMgr.GetCoinPoolSetting(this.platform, this.gamefreeId, this.groupId)
|
||
if setting != nil {
|
||
return int32(noRobotPlayerCount) >= setting.GetMinOutPlayerNum()
|
||
}
|
||
return int32(noRobotPlayerCount) >= this.GetDBGameFree().GetMinOutPlayerNum()
|
||
*/
|
||
}
|
||
|
||
func (this *Scene) ClearAutoPlayer() {
|
||
for _, p := range this.Players {
|
||
if p.IsAuto() {
|
||
p.UnmarkFlag(PlayerState_Auto)
|
||
p.SyncFlag()
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *Scene) SaveFriendRecord(snid int32, isWin int32, billCoin int64, baseScore int32) {
|
||
if this.SceneMode == common.SceneModePrivate {
|
||
return
|
||
}
|
||
log := model.NewFriendRecordLogEx(this.Platform, snid, isWin, this.GameId, baseScore, billCoin, int64(this.GetMatch().GetMatchType()))
|
||
if log != nil {
|
||
mq.Write(log)
|
||
}
|
||
}
|
||
|
||
type SaveGameDetailedParam struct {
|
||
LogId string // 日志id
|
||
Detail string // 游戏详细信息
|
||
GameTime int64 // 游戏时长
|
||
Trend20Lately string // 最近20局开奖结果
|
||
CtrlType int // 调控类型 1控赢 2控输
|
||
PlayerPool map[int]int // 个人水池分
|
||
}
|
||
|
||
func (this *Scene) SaveGameDetailedLog(param *SaveGameDetailedParam) {
|
||
if this == nil || param == nil {
|
||
return
|
||
}
|
||
|
||
if param.GameTime <= 0 {
|
||
param.GameTime = int64(time.Now().Sub(this.GameNowTime).Seconds())
|
||
}
|
||
|
||
if param.GameTime < 0 {
|
||
param.GameTime = 0
|
||
}
|
||
|
||
now := time.Now()
|
||
|
||
f := func(plt string) {
|
||
log := &model.GameDetailedLog{
|
||
Id: bson.NewObjectId(),
|
||
LogId: param.LogId,
|
||
GameId: this.GameId,
|
||
Platform: plt,
|
||
MatchId: this.GetMatch().GetMatchSortId(),
|
||
SceneId: this.SceneId,
|
||
GameMode: this.GameMode,
|
||
GameFreeid: this.GetGameFreeId(),
|
||
PlayerCount: int32(len(this.Players)),
|
||
GameTiming: int32(param.GameTime),
|
||
GameBaseBet: this.GetBaseScore(),
|
||
GameDetailedNote: param.Detail,
|
||
GameDetailVer: GameDetailedVer[int(this.GameId)],
|
||
CpCtx: this.CpCtx,
|
||
Time: now,
|
||
Trend20Lately: param.Trend20Lately,
|
||
Ts: now.Unix(),
|
||
CtrlType: param.CtrlType,
|
||
PlayerPool: make(map[int]int),
|
||
CycleId: this.CycleID,
|
||
}
|
||
for k, v := range param.PlayerPool {
|
||
log.PlayerPool[k] = v
|
||
}
|
||
mq.Write(log)
|
||
}
|
||
|
||
switch {
|
||
case this.IsCoinScene():
|
||
mapPlatform := make(map[string]bool)
|
||
for _, v := range this.Players {
|
||
if v == nil {
|
||
continue
|
||
}
|
||
if _, ok := mapPlatform[v.Platform]; ok {
|
||
continue
|
||
}
|
||
mapPlatform[v.Platform] = true
|
||
f(v.Platform)
|
||
}
|
||
default:
|
||
f(this.Platform)
|
||
}
|
||
}
|
||
|
||
type SaveGamePlayerListLogParam struct {
|
||
LogId string // 详情日志id
|
||
Platform string // 平台
|
||
Snid int32 // 玩家id
|
||
PlayerName string // 玩家名字
|
||
Channel string // 渠道
|
||
ChannelId string // 推广渠道
|
||
TotalIn int64 // 总投入
|
||
TotalOut int64 // 总产出(税前)
|
||
TaxCoin int64 // 总税收
|
||
BetAmount int64 // 下注量
|
||
WinAmountNoAnyTax int64 // 税后赢取额(净利润,正负值)
|
||
IsFirstGame bool // 是否第一次游戏
|
||
IsFree bool // 拉霸专用 是否免费
|
||
WinSmallGame int64 // 拉霸专用 小游戏奖励
|
||
WinTotal int64 // 拉霸专用 本局输赢
|
||
GameTime int64 // 游戏时长
|
||
}
|
||
|
||
// SaveGamePlayerListLog 保存玩家对局记录
|
||
func (this *Scene) SaveGamePlayerListLog(param *SaveGamePlayerListLogParam) {
|
||
if this == nil {
|
||
return
|
||
}
|
||
if param == nil {
|
||
return
|
||
}
|
||
|
||
p := this.GetPlayer(param.Snid)
|
||
if p == nil {
|
||
return
|
||
}
|
||
|
||
if param.PlayerName == "" {
|
||
param.PlayerName = p.Name
|
||
}
|
||
|
||
baseScore := this.GetBaseScore()
|
||
|
||
// 上报玩家游戏记录
|
||
if !p.IsRob && (param.IsFree || param.TotalIn != 0 || param.TotalOut != 0) {
|
||
p.ReportGameEvent(&ReportGameEventParam{
|
||
Tax: param.TaxCoin,
|
||
Change: param.WinAmountNoAnyTax,
|
||
In: param.TotalIn,
|
||
Out: param.TotalOut,
|
||
GameTime: param.GameTime,
|
||
})
|
||
}
|
||
|
||
// 保存玩家游戏日志
|
||
now := time.Now()
|
||
log := &model.GamePlayerListLog{
|
||
LogId: bson.NewObjectId(),
|
||
SnId: p.SnId,
|
||
Name: param.PlayerName,
|
||
GameId: this.GameId,
|
||
BaseScore: baseScore,
|
||
TaxCoin: param.TaxCoin,
|
||
Platform: param.Platform,
|
||
Channel: param.Channel,
|
||
SceneId: this.SceneId,
|
||
GameMode: this.GameMode,
|
||
GameFreeid: this.GetGameFreeId(),
|
||
GameDetailedLogId: param.LogId,
|
||
IsFirstGame: param.IsFirstGame,
|
||
BetAmount: param.BetAmount,
|
||
WinAmountNoAnyTax: param.WinAmountNoAnyTax,
|
||
TotalIn: param.TotalIn,
|
||
TotalOut: param.TotalOut,
|
||
Time: now,
|
||
RoomType: this.SceneMode,
|
||
GameDif: this.GetDBGameFree().GetGameDif(),
|
||
GameClass: this.GetDBGameFree().GetGameClass(),
|
||
MatchId: this.GetMatch().GetMatchSortId(),
|
||
MatchType: int64(this.GetMatch().GetMatchType()),
|
||
Ts: now.Unix(),
|
||
IsFree: param.IsFree,
|
||
WinSmallGame: param.WinSmallGame,
|
||
WinTotal: param.WinTotal,
|
||
CycleId: this.CycleID,
|
||
}
|
||
mq.Write(log)
|
||
}
|
||
|
||
func (this *Scene) IsPlayerFirst(p *Player) bool {
|
||
if p == nil {
|
||
return false
|
||
}
|
||
if p.GDatas != nil {
|
||
if data, ok := p.GDatas[this.KeyGameId]; ok {
|
||
if data.Statics.GameTimes <= 1 {
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
|
||
func (this *Scene) RobotIsLimit() bool {
|
||
if this.robotLimit != 0 {
|
||
if this.IsCoinScene() {
|
||
if this.robotLimit <= this.robotNum {
|
||
return true
|
||
}
|
||
// 房间需要给真人留一个空位
|
||
//if this.GetDBGameFree().GetMatchTrueMan() == common.MatchTrueMan_Priority && this.playerNum-this.realPlayerNum-1 <= this.robotNum {
|
||
// 没有真人的房间需要给真人留一个空位
|
||
if this.GetDBGameFree().GetMatchTrueMan() == common.MatchTrueMan_Priority && this.GetPlayerNum()-1 <= this.robotNum {
|
||
return true
|
||
}
|
||
} else if this.IsHundredScene() {
|
||
if this.robotNum >= this.robotLimit {
|
||
return true
|
||
}
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
func (this *Scene) RandRobotCnt() {
|
||
if this.GetDBGameFree() != nil {
|
||
if this.GetDBGameFree().GetMatchMode() == 1 {
|
||
return
|
||
}
|
||
numrng := this.GetDBGameFree().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[0] + this.Rand.Int31n(numrng[1]-numrng[0]+1))
|
||
}
|
||
}
|
||
//logger.Logger.Tracef("===(this *Scene) RandRobotCnt() sceneid:%v gameid:%v mode:%v robotLimit:%v robotNum:%v", this.SceneId, this.GameId, this.GameMode, this.robotLimit, this.robotNum)
|
||
}
|
||
}
|
||
|
||
func (this *Scene) GetRobotTime() int64 {
|
||
l := int64(common.RandInt(model.NormalParamData.RobotRandomTimeMin, model.NormalParamData.RobotRandomTimeMax))
|
||
return l + time.Now().Unix()
|
||
}
|
||
|
||
func (this *Scene) IsPreCreateScene() bool {
|
||
return this.GetDBGameFree().GetCreateRoomNum() > 0
|
||
}
|
||
|
||
func (this *Scene) TryInviteRobot() {
|
||
if this.aiMgr != nil {
|
||
return
|
||
}
|
||
// 游戏配置错误
|
||
if this.GetDBGameFree() == nil {
|
||
return
|
||
}
|
||
// 私有房间不邀请机器人,比赛场部邀请机器人
|
||
if this.IsPrivateScene() || this.IsMatchScene() {
|
||
return
|
||
}
|
||
// 队列匹配不邀请机器人
|
||
if this.GetDBGameFree().GetMatchMode() == 1 {
|
||
return
|
||
}
|
||
// 不使用机器人
|
||
if this.GetDBGameFree().GetBot() == 0 { //机器人不进的场
|
||
return
|
||
}
|
||
|
||
// 分组模式下机器人是否使用(默认不使用)
|
||
if !model.GameParamData.GameConfigGroupUseRobot && this.GroupId != 0 {
|
||
return
|
||
}
|
||
|
||
// 对战场有真实玩家的情况才需要机器人匹配
|
||
if !this.IsRobFightGame() && this.realPlayerNum <= 0 && !this.IsHundredScene() && !this.IsPreCreateScene() { //预创建房间的对战场可以优先进机器人,如:21点 判断依据:CreateRoomNum
|
||
return
|
||
}
|
||
|
||
switch this.GetDBGameFree().GetGameType() {
|
||
case common.GameType_Fishing:
|
||
if this.robotNum >= this.robotLimit {
|
||
return
|
||
}
|
||
}
|
||
|
||
tNow := time.Now()
|
||
if tNow.Before(this.nextInviteTime) {
|
||
return
|
||
}
|
||
if model.GameParamData.EnterAfterStartSwitch && this.IsCoinScene() && this.Gaming && !this.bEnterAfterStart {
|
||
return
|
||
}
|
||
|
||
if this.robotNumLastInvite == this.robotNum {
|
||
this.inviteInterval = this.inviteInterval + 1
|
||
if this.inviteInterval > model.GameParamData.RobotInviteIntervalMax {
|
||
this.inviteInterval = model.GameParamData.RobotInviteIntervalMax
|
||
}
|
||
} else {
|
||
this.inviteInterval = model.GameParamData.RobotInviteInitInterval
|
||
}
|
||
|
||
this.ResetNextInviteTime()
|
||
this.robotNumLastInvite = this.robotNum
|
||
|
||
if !this.RobotIsLimit() {
|
||
var robCnt int
|
||
if this.robotLimit != 0 {
|
||
if this.IsCoinScene() {
|
||
if this.robotNum >= this.robotLimit { //机器人数量已达上限
|
||
return
|
||
}
|
||
hadCnt := len(this.Players)
|
||
robCnt = this.robotLimit - this.robotNum
|
||
if robCnt > this.GetPlayerNum()-hadCnt {
|
||
robCnt = this.GetPlayerNum() - hadCnt
|
||
}
|
||
} else if this.IsHundredScene() {
|
||
robCnt = this.robotLimit - this.robotNum
|
||
}
|
||
} else {
|
||
if this.IsCoinScene() {
|
||
if this.IsFull() {
|
||
return
|
||
}
|
||
hadCnt := len(this.Players)
|
||
robCnt = this.GetPlayerNum() - hadCnt
|
||
if this.realPlayerNum == 0 { //一个真人都没有,不让机器人坐满房间
|
||
robCnt--
|
||
}
|
||
}
|
||
}
|
||
if robCnt > 0 {
|
||
var num int32
|
||
if this.GetDBGameFree().GameId == common.GameId_ChesstitiansCambodianRobot {
|
||
num = int32(robCnt)
|
||
} else {
|
||
num = this.Rand.Int31n(int32(robCnt + 1))
|
||
}
|
||
if num > 0 {
|
||
if this.IsCoinScene() /* && this.gaming*/ { //如果牌局正在进行中,一个一个进
|
||
num = 1
|
||
}
|
||
//logger.Logger.Tracef("(this *Scene)(groupid:%v sceneid:%v) TryInviteRobot(%v) current robot(%v+%v) robotlimit(%v)", this.groupId, this.sceneId, this.GetDBGameFree().GetName()+this.GetDBGameFree().GetTitle(), this.robotNum, num, this.robotLimit)
|
||
//同步下房间里的参数'
|
||
NpcServerAgentSingleton.SyncDBGameFree(int(this.SceneId), this.GetDBGameFree())
|
||
//然后再邀请
|
||
NpcServerAgentSingleton.Invite(int(this.SceneId), int(num), this.GetDBGameFree().Id)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *Scene) ResetNextInviteTime() {
|
||
this.nextInviteTime = time.Now().Add(time.Second * (time.Duration(this.Rand.Int63n(2+this.inviteInterval)) + 1))
|
||
}
|
||
|
||
// 是否有真人参与游戏
|
||
func (this *Scene) IsRealInGame() bool {
|
||
for _, player := range this.Players {
|
||
if player != nil && player.IsGameing() && !player.IsRob {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
// 是否都是真人
|
||
func (this *Scene) IsAllRealInGame() bool {
|
||
for _, player := range this.Players {
|
||
if player != nil && player.IsGameing() && player.IsRob {
|
||
return false
|
||
}
|
||
}
|
||
return true
|
||
}
|
||
|
||
// 是否开启机器人对战游戏
|
||
func (this *Scene) IsRobFightGame() bool {
|
||
if this.GetDBGameFree() == nil {
|
||
return false
|
||
}
|
||
if this.GetDBGameFree().GetAi()[0] == 1 && model.GameParamData.IsRobFightTest == true {
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
|
||
// 百人场机器人离场规则
|
||
func (this *Scene) RobotLeaveHundred() {
|
||
for _, p := range this.Players {
|
||
if p != nil {
|
||
leave := false
|
||
var reason int
|
||
//if p.trusteeship >= 5 {
|
||
// leave = true
|
||
// reason = common.PlayerLeaveReason_LongTimeNoOp
|
||
//}
|
||
if !leave && !p.IsOnLine() && time.Now().Sub(p.DropTime) > 30*time.Second {
|
||
leave = true
|
||
reason = common.PlayerLeaveReason_DropLine
|
||
}
|
||
if !leave && p.IsRob {
|
||
if !this.CoinInLimit(p.Coin) {
|
||
//钱少
|
||
leave = true
|
||
reason = common.PlayerLeaveReason_Bekickout
|
||
} else if this.CoinOverMaxLimit(p.Coin, p) {
|
||
//钱多
|
||
leave = true
|
||
reason = common.PlayerLeaveReason_Normal
|
||
} else if p.Coin < int64(this.GetDBGameFree().GetBetLimit()) {
|
||
//少于下注限额
|
||
leave = true
|
||
reason = common.PlayerLeaveReason_Normal
|
||
}
|
||
}
|
||
if leave {
|
||
this.PlayerLeave(p, reason, leave)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *Scene) RandInt(args ...int) int {
|
||
switch len(args) {
|
||
case 0:
|
||
return this.Rand.Int()
|
||
case 1:
|
||
if args[0] != 0 {
|
||
return this.Rand.Intn(args[0])
|
||
} else {
|
||
return 0
|
||
}
|
||
default:
|
||
l := args[0]
|
||
u := args[1]
|
||
switch {
|
||
case l == u:
|
||
{
|
||
return l
|
||
}
|
||
case l > u:
|
||
{
|
||
return u + this.Rand.Intn(l-u)
|
||
}
|
||
default:
|
||
{
|
||
return l + this.Rand.Intn(u-l)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *Scene) CheckNeedDestroy() bool {
|
||
//if common.IsLocalGame(this.GameId) {
|
||
return ServerStateMgr.GetState() == common.GameSessStateOff || this.graceDestroy
|
||
//} else {
|
||
// return (ServerStateMgr.GetState() == common.GAME_SESS_STATE_OFF || this.graceDestroy) || (this.IsPrivateScene() && this.NumOfGames >= this.TotalOfGames)
|
||
//}
|
||
}
|
||
|
||
func (this *Scene) GetRecordId() string {
|
||
if this.rr != nil {
|
||
return this.rr.id
|
||
}
|
||
return fmt.Sprintf("%d%d%v%d", this.GameId, this.SceneId, this.GameNowTime.Format(ReplayIdTf), this.NumOfGames)
|
||
}
|
||
|
||
func (this *Scene) RandTakeCoin(p *Player) (takeCoin, leaveCoin, gameTimes int64) {
|
||
if p.IsRob && p.IsLocal {
|
||
dbGameFree := this.GetDBGameFree()
|
||
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]))
|
||
}
|
||
}
|
||
return
|
||
}
|
||
|
||
// TryBillExGameDrop 掉落道具
|
||
func (this *Scene) TryBillExGameDrop(p *Player) {
|
||
if p.IsRob {
|
||
return
|
||
}
|
||
|
||
this.DropCollectBox(p)
|
||
|
||
baseScore := this.GetDBGameFree().BaseScore
|
||
if common.IsLocalGame(int(this.GameId)) {
|
||
baseScore = this.BaseScore
|
||
}
|
||
if baseScore == 0 {
|
||
return
|
||
}
|
||
|
||
// 场次掉落开关
|
||
if this.GetDBGameFree().IsDrop != 1 {
|
||
return
|
||
}
|
||
|
||
// 渠道开关
|
||
if !ConfigMgrInst.IsOn(p.Platform, common.ChannelSwitchDropItem, p.LastChannel) {
|
||
return
|
||
}
|
||
|
||
dropInfo := srvdata.GameDropMgrSingleton.GetDropInfoByBaseScore(baseScore)
|
||
if dropInfo != nil && len(dropInfo) != 0 {
|
||
realDrop := make(map[int32]int32)
|
||
for _, drop := range dropInfo {
|
||
//概率
|
||
randTmp := rand.Int31n(10000)
|
||
if randTmp < drop.Rate {
|
||
//个数
|
||
num := drop.MinAmount
|
||
if drop.MaxAmount > drop.MinAmount {
|
||
num = rand.Int31n(drop.MaxAmount-drop.MinAmount+1) + drop.MinAmount
|
||
}
|
||
oldNum := num
|
||
a := math.Max(float64(p.MoneyTotal), 50) * 10.0 / math.Max(float64(p.VCardCost), 500.0)
|
||
num = int32(float64(num) * math.Min(a, 1.5))
|
||
if num == 0 {
|
||
// 50%概率给oldNum
|
||
if rand.Int31n(100) < 50 {
|
||
num = oldNum
|
||
}
|
||
}
|
||
realDrop[drop.ItemId] = num
|
||
}
|
||
}
|
||
if realDrop != nil && len(realDrop) != 0 {
|
||
//通知客户端游戏内额外掉落
|
||
pack := &player.SCGameExDropItems{}
|
||
pack.Items = make(map[int32]int32)
|
||
for id, num := range realDrop {
|
||
pack.Items[id] = proto.Int32(num)
|
||
itemData := srvdata.GameItemMgr.Get(p.Platform, id)
|
||
if itemData != nil {
|
||
p.AddItems(&model.AddItemParam{
|
||
Platform: p.Platform,
|
||
SnId: p.SnId,
|
||
Change: []*model.Item{
|
||
{
|
||
ItemId: id,
|
||
ItemNum: int64(num),
|
||
},
|
||
},
|
||
GainWay: common.GainWay_Game,
|
||
Operator: "system",
|
||
Remark: fmt.Sprintf("游戏掉落%v", id),
|
||
GameId: int64(this.GameId),
|
||
GameFreeId: int64(this.GetGameFreeId()),
|
||
})
|
||
}
|
||
}
|
||
if len(pack.Items) > 0 {
|
||
p.SendToClient(int(player.PlayerPacketID_PACKET_SCGAMEEXDROPITEMS), pack)
|
||
logger.Logger.Trace("SCGAMEEXDROPITEMS ", pack)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// DropCollectBox 掉落集卡礼盒
|
||
func (this *Scene) DropCollectBox(p *Player) {
|
||
if p == nil || p.IsRob || ConfigMgrInst.GetConfig(p.Platform).WelfareCollectConfig.Switch != model.WelfareOpen {
|
||
return
|
||
}
|
||
|
||
data := srvdata.PBDB_CollectBoxGainMgr.GetData(this.GetGameFreeId())
|
||
if data == nil {
|
||
return
|
||
}
|
||
|
||
n := this.RandInt(100)
|
||
if n < int(data.GetRate()) {
|
||
pack := &player.SCGameExDropItems{}
|
||
pack.Items = make(map[int32]int32)
|
||
itemData := srvdata.GameItemMgr.Get(p.Platform, common.ItemIDCollectBox)
|
||
if itemData != nil {
|
||
pack.Items = map[int32]int32{itemData.Id: 1}
|
||
p.AddItems(&model.AddItemParam{
|
||
Platform: p.Platform,
|
||
SnId: p.SnId,
|
||
Change: []*model.Item{
|
||
{
|
||
ItemId: itemData.Id,
|
||
ItemNum: 1,
|
||
},
|
||
},
|
||
GainWay: common.GainWay_Game,
|
||
Operator: "system",
|
||
Remark: fmt.Sprintf("游戏掉落%v", itemData.Id),
|
||
GameId: int64(this.GameId),
|
||
GameFreeId: int64(this.GetGameFreeId()),
|
||
})
|
||
}
|
||
if len(pack.Items) > 0 {
|
||
p.SendToClient(int(player.PlayerPacketID_PACKET_SCGAMEEXDROPITEMS), pack)
|
||
logger.Logger.Trace("SCGAMEEXDROPITEMS", pack)
|
||
}
|
||
}
|
||
}
|
||
|
||
// 生成名字
|
||
func (this *Scene) RandNickName() string {
|
||
//if rand.Int31n(100) < 60 {
|
||
pool := srvdata.PBDB_NameMgr.Datas.GetArr()
|
||
cnt := int32(len(pool))
|
||
if cnt > 0 {
|
||
return pool[rand.Int31n(cnt)].GetName()
|
||
}
|
||
//}
|
||
return "Guest"
|
||
}
|
||
|
||
func (this *Scene) GetRobotNum() int {
|
||
return this.robotNum
|
||
}
|
||
|
||
func (this *Scene) GetRealPlayerNum() int {
|
||
return this.realPlayerNum
|
||
}
|
||
|
||
func (this *Scene) GetBaseScore() int32 {
|
||
if this.BaseScore > 0 {
|
||
return this.BaseScore
|
||
}
|
||
return this.GetDBGameFree().GetBaseScore()
|
||
}
|
||
|
||
func (this *Scene) PlayerPoolOdds(p *Player) int32 {
|
||
config := ConfigMgrInst.GetConfig(p.Platform).PlayerPool
|
||
if config == nil {
|
||
return 0
|
||
}
|
||
|
||
if !config.GetPlayerPoolSwitch() || p == nil {
|
||
return 0
|
||
}
|
||
|
||
pCoin := p.TotalOut - p.PlayerTax - p.TotalIn
|
||
var gameCoin int64
|
||
var upLine, lowLine int64
|
||
|
||
lowLine = p.GetPoolLower(config)
|
||
upLine = p.GetPoolUpper(config)
|
||
|
||
odds := int32(p.GetPoolOdds(config))
|
||
|
||
p.TestLog = append(p.TestLog, fmt.Sprintf("个人水池调控 gameID:%v 兑换金币:%v 玩家初始值:%v, 游戏类型:%v, gameCoin:%v, 上线:%v, 下线:%v 概率:%v",
|
||
this.GameId, p.DiamondToCoin, pCoin, this.GetDBGameFree().GetGameType(), gameCoin, upLine, lowLine, odds))
|
||
|
||
return odds
|
||
}
|
||
|
||
// GetPlayerOdds 获取玩家发牌调控概率
|
||
func (this *Scene) GetPlayerOdds(p *Player, gameId int, hasRobot bool) int32 {
|
||
if !this.IsControl(hasRobot) {
|
||
return 0
|
||
}
|
||
|
||
if p == nil {
|
||
return 0
|
||
}
|
||
// 黑白名单概率
|
||
odds, ok := p.BlackWhiteOdds(gameId)
|
||
if ok {
|
||
return odds
|
||
}
|
||
|
||
// 新手补偿概率
|
||
odds, ok = p.NoviceOdds(gameId)
|
||
if ok {
|
||
return odds
|
||
}
|
||
|
||
var f, g, t, ret int32
|
||
// 个人水池概率
|
||
g = this.PlayerPoolOdds(p)
|
||
|
||
setting := CoinPoolMgr.GetCoinPoolSetting(this.Platform, this.GetGameFreeId(), this.GroupId)
|
||
if setting != nil && setting.GetSwitch() == 0 {
|
||
// 场次水池概率
|
||
f = CoinPoolMgr.GetCoinPoolOdds(this.Platform, this.GetGameFreeId(), this.GroupId)
|
||
|
||
cfg := ConfigMgrInst.GetConfig(p.Platform).PlayerPool
|
||
if cfg != nil && cfg.PlayerPoolSwitch {
|
||
if g > 0 {
|
||
t = f + (1000-f)*g/1000
|
||
ret = t
|
||
} else if g < 0 {
|
||
t = f + (1000+f)*g/1000
|
||
ret = t
|
||
} else {
|
||
ret = f
|
||
}
|
||
} else {
|
||
ret = f
|
||
}
|
||
//logger.Logger.Tracef("TienLenSceneData snid(%v) 水池配置 水位:%v 配置:%+v",
|
||
// p.SnId, CoinPoolMgr.GetCoin(this.GetGameFreeId(), this.Platform, this.GroupId), *setting)
|
||
p.TestLog = append(p.TestLog, fmt.Sprintf("水位:%v 水池配置:%+v",
|
||
CoinPoolMgr.GetCoin(this.GetGameFreeId(), this.Platform, this.GroupId), *setting))
|
||
} else {
|
||
ret = g
|
||
}
|
||
|
||
//logger.Logger.Tracef("TienLenSceneData snid(%v) 个人及场次水池调控 hasRobot:%v 个人水池:%v 场次水池:%v 概率:%v", p.SnId, hasRobot, g, f, ret)
|
||
p.TestLog = append(p.TestLog, fmt.Sprintf("个人及场次水池调控 有机器人:%v 个人水池:%v 场次水池:%v 概率:%v", hasRobot, g, f, ret))
|
||
return ret
|
||
}
|
||
|
||
type PlayerDataParam struct {
|
||
HasRobotGaming bool
|
||
Data *server.GWPlayerData
|
||
}
|
||
|
||
// SyncPlayerDatas 同步玩家游戏数据到worldsrv
|
||
// hasRobotGaming 本局是否有机器人参与游戏
|
||
// 返回 溢出金额
|
||
func (this *Scene) SyncPlayerDatas(param *PlayerDataParam) int64 {
|
||
if param == nil || param.Data == nil {
|
||
return 0
|
||
}
|
||
var n int64
|
||
// 比赛场,私人房,公共房无机器人不统计黑白名单输赢金额
|
||
if this.IsControl(param.HasRobotGaming) {
|
||
for _, v := range param.Data.Datas {
|
||
if v.WBGain == 0 {
|
||
v.WBGain = v.Gain
|
||
}
|
||
if v.WBGain != 0 {
|
||
if p := this.GetPlayer(v.SnId); p != nil {
|
||
n = p.WBUpdate(v.WBGain)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
this.SendToWorld(int(server.SSPacketID_PACKET_GW_PLAYERDATA), param.Data)
|
||
logger.Logger.Trace("Send PlayerData ===>", param.Data)
|
||
return n
|
||
}
|
||
|
||
type StaticParam struct {
|
||
SnId int32 // 玩家id
|
||
Gain int64 // 输赢金币(税后)
|
||
GainTax int64 // 赢取金币时的税收
|
||
IsAddTimes bool // 是否统计游戏次数
|
||
HasRobotGaming bool // 是否有机器人玩本局游戏
|
||
WinState int32 // 输赢状态 1 赢 2 输 3 和
|
||
}
|
||
|
||
// IsControl 是否调控
|
||
func (this *Scene) IsControl(hasRobotGaming bool) bool {
|
||
return !this.IsMatchScene() && !this.IsPrivateScene() && !(this.IsFreePublic() && !hasRobotGaming)
|
||
}
|
||
|
||
// Statistics 玩家游戏数据统计
|
||
// 包含水池统计,黑白名单统计,新手调控统计,个人水池统计
|
||
func (this *Scene) Statistics(param *StaticParam) {
|
||
if param == nil {
|
||
return
|
||
}
|
||
p := this.GetPlayer(param.SnId)
|
||
if p == nil || p.IsRob {
|
||
return
|
||
}
|
||
|
||
_, isNovice := p.NoviceOdds(int(this.GameId))
|
||
isControl := this.IsControl(param.HasRobotGaming) // 需要调控的房间
|
||
|
||
var wbLevel = p.WBLevel // 原来的黑白名单等级; 注意SyncPlayerDatas会修改WBLevel
|
||
var addGain int64 // 玩家溢出金额
|
||
// 黑白名单
|
||
// 解除黑白名单,记录黑白名单投入产出
|
||
addGain += this.SyncPlayerDatas(&PlayerDataParam{
|
||
HasRobotGaming: param.HasRobotGaming,
|
||
Data: &server.GWPlayerData{
|
||
Datas: []*server.PlayerData{
|
||
{
|
||
SnId: param.SnId,
|
||
Gain: param.Gain,
|
||
Tax: param.GainTax,
|
||
Coin: p.Coin,
|
||
GameCoinTs: p.GameCoinTs,
|
||
WinState: param.WinState,
|
||
},
|
||
},
|
||
GameFreeId: this.GetGameFreeId(),
|
||
SceneId: int32(this.SceneId),
|
||
},
|
||
})
|
||
|
||
logger.Logger.Tracef("Statistics gameId:%v wbLevel:%v gain:%v addGain:%v", this.GameId, wbLevel, param.Gain, addGain)
|
||
|
||
// 比赛场,私人房不统计
|
||
if this.IsMatchScene() || this.IsPrivateScene() {
|
||
return
|
||
}
|
||
|
||
var totalIn int64
|
||
var totalOut int64
|
||
now := time.Now()
|
||
if param.Gain > 0 {
|
||
totalOut = param.Gain + param.GainTax
|
||
} else {
|
||
totalIn = -param.Gain
|
||
}
|
||
|
||
var statics []*model.PlayerGameStatics
|
||
keyGameId := strconv.Itoa(this.GetGameId())
|
||
keyGameFreeId := strconv.Itoa(int(this.GetGameFreeId()))
|
||
// 当天数据统计
|
||
// 按场次分
|
||
if data, ok := p.TodayGameData.CtrlData[keyGameFreeId]; ok {
|
||
statics = append(statics, data)
|
||
} else {
|
||
gs := model.NewPlayerGameStatics()
|
||
p.TodayGameData.CtrlData[keyGameFreeId] = gs
|
||
statics = append(statics, gs)
|
||
}
|
||
// 按游戏分
|
||
if data, ok := p.TodayGameData.CtrlData[keyGameId]; ok {
|
||
statics = append(statics, data)
|
||
} else {
|
||
data = model.NewPlayerGameStatics()
|
||
p.TodayGameData.CtrlData[keyGameId] = data
|
||
statics = append(statics, data)
|
||
}
|
||
// 按场次分
|
||
if data, ok := p.GDatas[keyGameFreeId]; ok {
|
||
if data.FirstTime.IsZero() {
|
||
data.FirstTime = now
|
||
}
|
||
statics = append(statics, &data.Statics)
|
||
} else {
|
||
data = &model.PlayerGameInfo{FirstTime: now}
|
||
p.GDatas[keyGameFreeId] = data
|
||
statics = append(statics, &data.Statics)
|
||
}
|
||
// 按游戏分
|
||
if data, ok := p.GDatas[keyGameId]; ok {
|
||
if data.FirstTime.IsZero() {
|
||
data.FirstTime = now
|
||
}
|
||
statics = append(statics, &data.Statics)
|
||
} else {
|
||
data = &model.PlayerGameInfo{FirstTime: now}
|
||
p.GDatas[keyGameId] = data
|
||
statics = append(statics, &data.Statics)
|
||
}
|
||
|
||
// 新手输赢统计
|
||
if !model.GameParamData.CloseNovice && !common.InSliceInt(model.GameParamData.CloseNoviceGame, int(this.GameId)) && isControl && wbLevel == 0 && isNovice {
|
||
keyNoviceGameId := common.GetKeyNoviceGameId(int(this.GameId))
|
||
var gs *model.PlayerGameStatics
|
||
if data, ok := p.GDatas[keyNoviceGameId]; ok {
|
||
statics = append(statics, &data.Statics)
|
||
gs = &data.Statics
|
||
} else {
|
||
data = &model.PlayerGameInfo{FirstTime: time.Now(), Statics: *model.NewPlayerGameStatics()}
|
||
p.GDatas[keyNoviceGameId] = data
|
||
statics = append(statics, &data.Statics)
|
||
gs = &data.Statics
|
||
}
|
||
// 溢出
|
||
data := srvdata.PBDB_NewPlayerMgr.GetData(int32(this.GameId))
|
||
if data != nil {
|
||
switch data.GetCondition1() {
|
||
case 2: // gameId输赢金额
|
||
if gs != nil {
|
||
out := gs.TotalOut + totalOut
|
||
in := gs.TotalIn + totalIn
|
||
tax := gs.Tax + param.GainTax
|
||
cur := out - tax - in
|
||
if cur > data.GetConditionValue1() {
|
||
addGain += cur - data.GetConditionValue1()
|
||
}
|
||
}
|
||
}
|
||
switch data.GetCondition2() {
|
||
case 2: // gameId输赢金额
|
||
if gs != nil {
|
||
out := gs.TotalOut + totalOut
|
||
in := gs.TotalIn + totalIn
|
||
tax := gs.Tax + param.GainTax
|
||
cur := out - tax - in
|
||
if cur > data.GetConditionValue2() {
|
||
addGain += cur - data.GetConditionValue2()
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
logger.Logger.Tracef("Statistics Novice gameId:%v wbLevel:%v gain:%v addGain:%v", this.GameId, wbLevel, param.Gain, addGain)
|
||
|
||
// 个人输赢统计条件(个人水池)
|
||
// 黑白名单和新手调控,溢出金币统计到个人水池
|
||
cfg := ConfigMgrInst.GetConfig(p.Platform).PlayerPool
|
||
isPlayerPool := cfg != nil && cfg.PlayerPoolSwitch && isControl && ((wbLevel == 0 && !isNovice) || addGain > 0)
|
||
if isPlayerPool {
|
||
keyGameType := common.GetKeyGameType(int(this.GetDBGameFree().GetGameType()))
|
||
gs, ok := p.GDatas[keyGameType]
|
||
if !ok {
|
||
gs = &model.PlayerGameInfo{FirstTime: time.Now()}
|
||
p.GDatas[keyGameType] = gs
|
||
}
|
||
if addGain == 0 {
|
||
// 正常统计
|
||
// 游戏类型输赢统计(个人水池调控使用)
|
||
statics = append(statics, &gs.Statics)
|
||
} else {
|
||
// 溢出统计;只有多赢的值,多输的不计算
|
||
if wbLevel >= 0 {
|
||
gs.Statics.TotalOut += addGain
|
||
}
|
||
}
|
||
logger.Logger.Tracef("Statistics PlayerPool gameId:%v wbLevel:%v gain:%v addGain:%v", this.GameId, wbLevel, param.Gain, addGain)
|
||
}
|
||
|
||
for _, data := range statics {
|
||
if data != nil {
|
||
data.TotalIn += totalIn
|
||
data.TotalOut += totalOut
|
||
data.Tax += param.GainTax
|
||
if param.IsAddTimes {
|
||
data.GameTimes++
|
||
if param.Gain > 0 {
|
||
data.WinGameTimes++
|
||
data.WinGameTimesNum++
|
||
data.LoseGameTimesNum = 0
|
||
} else if param.Gain < 0 {
|
||
data.LoseGameTimes++
|
||
data.LoseGameTimesNum++
|
||
data.WinGameTimesNum = 0
|
||
} else {
|
||
data.DrawGameTimes++
|
||
data.WinGameTimesNum = 0
|
||
data.LoseGameTimesNum = 0
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 玩家身上元数据
|
||
if param.IsAddTimes {
|
||
p.GameTimes++
|
||
}
|
||
if param.Gain > 0 {
|
||
if param.IsAddTimes {
|
||
p.WinTimes++
|
||
}
|
||
p.WinCoin += totalOut
|
||
p.TaxCoin += param.GainTax
|
||
if isPlayerPool && srvdata.GameFreeMgr.IsPlayerPool(int(this.GameId)) {
|
||
p.TotalOut += totalOut
|
||
p.PlayerTax += param.GainTax
|
||
}
|
||
} else if param.Gain < 0 {
|
||
if param.IsAddTimes {
|
||
p.FailTimes++
|
||
}
|
||
p.FailCoin += totalIn
|
||
if isPlayerPool && srvdata.GameFreeMgr.IsPlayerPool(int(this.GameId)) {
|
||
p.TotalIn += totalIn
|
||
}
|
||
} else {
|
||
if param.IsAddTimes {
|
||
p.DrawTimes++
|
||
}
|
||
}
|
||
|
||
// 水池统计
|
||
if isControl && ((wbLevel == 0 && !isNovice) || addGain > 0) {
|
||
if addGain == 0 {
|
||
CoinPoolMgr.PushCoin(this.GetGameFreeId(), this.GroupId, this.Platform, -param.Gain)
|
||
} else {
|
||
// 溢出统计;只有多赢的值,多输的不计算
|
||
if wbLevel >= 0 {
|
||
CoinPoolMgr.PushCoin(this.GetGameFreeId(), this.GroupId, this.Platform, -addGain)
|
||
}
|
||
}
|
||
logger.Logger.Tracef("Statisticsis CoinPool gameId:%v wbLevel:%v gain:%v addGain:%v", this.GameId, wbLevel, param.Gain, addGain)
|
||
}
|
||
}
|
||
|
||
type StaticLabaParam struct {
|
||
SnId int32 // 玩家id
|
||
Gain int64 // 输赢金币(税后)
|
||
GainTax int64 // 赢取金币时的税收
|
||
IsAddTimes bool // 是否统计游戏次数
|
||
}
|
||
|
||
// StaticsLaba 拉霸游戏数据统计,一次下注记录一次
|
||
// 不含水池统计,黑白名单统计,在游戏中另外处理
|
||
func (this *Scene) StaticsLaba(param *StaticLabaParam) {
|
||
if param == nil {
|
||
return
|
||
}
|
||
p := this.GetPlayer(param.SnId)
|
||
if p == nil || p.IsRob {
|
||
return
|
||
}
|
||
|
||
// 比赛场,私人房不统计
|
||
if this.IsMatchScene() || this.IsPrivateScene() {
|
||
return
|
||
}
|
||
|
||
var totalIn int64
|
||
var totalOut int64
|
||
now := time.Now()
|
||
if param.Gain > 0 {
|
||
totalOut = param.Gain + param.GainTax
|
||
} else {
|
||
totalIn = -param.Gain
|
||
}
|
||
|
||
var statics []*model.PlayerGameStatics
|
||
keyGameId := strconv.Itoa(this.GetGameId())
|
||
keyGameFreeId := strconv.Itoa(int(this.GetGameFreeId()))
|
||
// 当天数据统计
|
||
// 按场次分
|
||
if data, ok := p.TodayGameData.CtrlData[keyGameFreeId]; ok {
|
||
statics = append(statics, data)
|
||
} else {
|
||
gs := model.NewPlayerGameStatics()
|
||
p.TodayGameData.CtrlData[keyGameFreeId] = gs
|
||
statics = append(statics, gs)
|
||
}
|
||
// 按游戏分
|
||
if data, ok := p.TodayGameData.CtrlData[keyGameId]; ok {
|
||
statics = append(statics, data)
|
||
} else {
|
||
data = model.NewPlayerGameStatics()
|
||
p.TodayGameData.CtrlData[keyGameId] = data
|
||
statics = append(statics, data)
|
||
}
|
||
// 按场次分
|
||
if data, ok := p.GDatas[keyGameFreeId]; ok {
|
||
if data.FirstTime.IsZero() {
|
||
data.FirstTime = now
|
||
}
|
||
statics = append(statics, &data.Statics)
|
||
} else {
|
||
data = &model.PlayerGameInfo{FirstTime: now}
|
||
p.GDatas[keyGameFreeId] = data
|
||
statics = append(statics, &data.Statics)
|
||
}
|
||
// 按游戏分
|
||
if data, ok := p.GDatas[keyGameId]; ok {
|
||
if data.FirstTime.IsZero() {
|
||
data.FirstTime = now
|
||
}
|
||
statics = append(statics, &data.Statics)
|
||
} else {
|
||
data = &model.PlayerGameInfo{FirstTime: now}
|
||
p.GDatas[keyGameId] = data
|
||
statics = append(statics, &data.Statics)
|
||
}
|
||
|
||
for _, data := range statics {
|
||
if data != nil {
|
||
data.TotalIn += totalIn
|
||
data.TotalOut += totalOut
|
||
data.Tax += param.GainTax
|
||
if param.IsAddTimes {
|
||
data.GameTimes++
|
||
if param.Gain > 0 {
|
||
data.WinGameTimes++
|
||
data.WinGameTimesNum++
|
||
data.LoseGameTimesNum = 0
|
||
} else if param.Gain < 0 {
|
||
data.LoseGameTimes++
|
||
data.LoseGameTimesNum++
|
||
data.WinGameTimesNum = 0
|
||
} else {
|
||
data.DrawGameTimes++
|
||
data.WinGameTimesNum = 0
|
||
data.LoseGameTimesNum = 0
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 玩家身上元数据
|
||
if param.IsAddTimes {
|
||
p.GameTimes++
|
||
}
|
||
if param.Gain > 0 {
|
||
if param.IsAddTimes {
|
||
p.WinTimes++
|
||
}
|
||
p.WinCoin += totalOut
|
||
p.TaxCoin += param.GainTax
|
||
} else if param.Gain < 0 {
|
||
if param.IsAddTimes {
|
||
p.FailTimes++
|
||
}
|
||
p.FailCoin += totalIn
|
||
} else {
|
||
if param.IsAddTimes {
|
||
p.DrawTimes++
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *Scene) TryRelease() {
|
||
if !this.IsMatchScene() && this.realPlayerNum == 0 {
|
||
this.Destroy(true)
|
||
}
|
||
}
|
||
func (this *Scene) GetMachineServerInfo(MachineId int32, platform string) *webapi.MachineInfo {
|
||
config := ConfigMgrInst.GetConfig(platform).MachineConfig
|
||
logger.Logger.Tracef("========GetMachineServerInfo=========== platform=%s, MachineId=%d ,config = %v", platform, MachineId, config)
|
||
if config == nil {
|
||
return nil
|
||
}
|
||
for _, info := range config.Info {
|
||
if info.MachineId == MachineId {
|
||
return info
|
||
}
|
||
}
|
||
return nil
|
||
}
|