package sugarrush import ( "encoding/json" "mongo.games.com/game/common" "mongo.games.com/game/gamerule/sugarrush" "mongo.games.com/game/gamesrv/base" "mongo.games.com/game/gamesrv/slotspkg/slots" "mongo.games.com/game/gamesrv/slotspkg/slots/types/cli" "mongo.games.com/game/model" "mongo.games.com/game/proto" "mongo.games.com/game/protocol/server" protocol "mongo.games.com/game/protocol/sugarrush" "mongo.games.com/goserver/core" "mongo.games.com/goserver/core/logger" "time" ) // //////////////////////////////////////////////////////////// var ScenePolicySugarRushSington = &ScenePolicySugarRush{} type ScenePolicySugarRush struct { base.BaseScenePolicy states [sugarrush.SugarRushStateMax]base.SceneState } // 创建场景扩展数据 func (this *ScenePolicySugarRush) CreateSceneExData(s *base.Scene) interface{} { sceneEx := NewSugarRushSceneData(s) if sceneEx != nil { if sceneEx.GetInit() { s.SetExtraData(sceneEx) } } return sceneEx } // 创建玩家扩展数据 func (this *ScenePolicySugarRush) CreatePlayerExData(s *base.Scene, p *base.Player) interface{} { playerEx := &SugarRushPlayerData{Player: p} p.SetExtraData(playerEx) return playerEx } // 场景开启事件 func (this *ScenePolicySugarRush) OnStart(s *base.Scene) { logger.Logger.Trace("(this *ScenePolicySugarRush) OnStart, sceneId=", s.GetSceneId()) sceneEx := NewSugarRushSceneData(s) if sceneEx != nil { if sceneEx.GetInit() { s.SetExtraData(sceneEx) s.ChangeSceneState(sugarrush.SugarRushStateStart) } } } // 场景关闭事件 func (this *ScenePolicySugarRush) OnStop(s *base.Scene) { logger.Logger.Trace("(this *ScenePolicySugarRush) OnStop , sceneId=", s.GetSceneId()) } // 场景心跳事件 func (this *ScenePolicySugarRush) OnTick(s *base.Scene) { if s == nil { return } if s.GetSceneState() != nil { s.GetSceneState().OnTick(s) } } // 玩家进入事件 func (this *ScenePolicySugarRush) OnPlayerEnter(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicySugarRush) OnPlayerEnter, sceneId=", s.GetSceneId(), " player=", p.Name) if sceneEx, ok := s.GetExtraData().(*SugarRushSceneData); ok { playerEx := &SugarRushPlayerData{Player: p} playerEx.init() d := p.GameData[sugarrush.GameDataKey] if d != nil { m := make(map[string]string) json.Unmarshal(d.Data.([]byte), &m) playerEx.PullPlayer(m) } else { m := make(map[string]string) //json.Unmarshal(d.Data.([]byte), &m) playerEx.PullPlayer(m) } playerEx.SlotsSession.SetCoin(playerEx.Coin /* * sugarrush.NowByte*/) playerEx.Clear() sceneEx.players[p.SnId] = playerEx p.SetExtraData(playerEx) SugarRushSendRoomInfo(s, sceneEx, playerEx, false) s.FirePlayerEvent(p, base.PlayerEventEnter, nil) } } // 玩家离开事件 func (this *ScenePolicySugarRush) OnPlayerLeave(s *base.Scene, p *base.Player, reason int) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicySugarRush) OnPlayerLeave, sceneId=", s.GetSceneId(), " player=", p.SnId) if playerEx, ok := p.ExtraData.(*SugarRushPlayerData); ok { playerEx.LabaLog.Save(2) // 没有收到结束消息,算2秒游戏时长 m := playerEx.PushPlayer() if m != nil && len(m) > 0 { b, err := json.Marshal(m) if err != nil { logger.Logger.Error("OnPlayerLeave, json.Marshal error:", err) } else { p.GameData[sugarrush.GameDataKey] = &model.PlayerGameData{ Platform: p.Platform, SnId: p.SnId, Id: sugarrush.GameDataKey, Data: b, } } } } if sceneEx, ok := s.ExtraData.(*SugarRushSceneData); ok { s.FirePlayerEvent(p, base.PlayerEventLeave, nil) sceneEx.OnPlayerLeave(p, reason) } } // 玩家掉线 func (this *ScenePolicySugarRush) OnPlayerDropLine(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicySugarRush) OnPlayerDropLine, sceneId=", s.GetSceneId(), " player=", p.SnId) s.FirePlayerEvent(p, base.PlayerEventDropLine, nil) } // 玩家重连 func (this *ScenePolicySugarRush) OnPlayerRehold(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicySugarRush) OnPlayerRehold, sceneId=", s.GetSceneId(), " player=", p.SnId) if sceneEx, ok := s.GetExtraData().(*SugarRushSceneData); ok { if playerEx, ok := p.GetExtraData().(*SugarRushPlayerData); ok { SugarRushSendRoomInfo(s, sceneEx, playerEx, true) } } } // 返回房间 func (this *ScenePolicySugarRush) OnPlayerReturn(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicySugarRush) OnPlayerReturn, GetSceneId()=", s.GetSceneId(), " player=", p.Name) if sceneEx, ok := s.GetExtraData().(*SugarRushSceneData); ok { if playerEx, ok := p.GetExtraData().(*SugarRushPlayerData); ok { //if p.IsMarkFlag(base.PlayerState_Auto) { // p.UnmarkFlag(base.PlayerState_Auto) // p.SyncFlag() //} //发送房间信息给自己 SugarRushSendRoomInfo(s, sceneEx, playerEx, true) s.FirePlayerEvent(p, base.PlayerEventReturn, nil) } } } func SugarRushSendRoomInfo(s *base.Scene, sceneEx *SugarRushSceneData, playerEx *SugarRushPlayerData, reload bool) { pack := SugarRushCreateRoomInfoPacket(s, sceneEx, playerEx, reload) logger.Logger.Trace("RoomInfo: ", pack) playerEx.SendToClient(int(protocol.SugarRushPID_PACKET_SUGARRUSH_SCSUGARRUSHROOMINFO), pack) } func SugarRushCreateRoomInfoPacket(s *base.Scene, sceneEx *SugarRushSceneData, playerEx *SugarRushPlayerData, reload bool) interface{} { //房间信息 pack := &protocol.SCSugarRushRoomInfo{ RoomId: s.SceneId, GameId: s.GameId, RoomMode: s.SceneMode, SceneType: s.GetSceneType(), Params: common.CopySliceInt64ToInt32(s.Params), NumOfGames: proto.Int(sceneEx.NumOfGames), State: proto.Int(s.SceneState.GetState()), ParamsEx: s.GetDBGameFree().OtherIntParams, GameFreeId: proto.Int32(s.GetDBGameFree().Id), //BetLimit: s.GetDBGameFree().BetLimit, } //自己的信息 if playerEx != nil { pd := &protocol.SugarRushPlayerData{ SnId: proto.Int32(playerEx.SnId), Name: proto.String(playerEx.Name), Head: proto.Int32(playerEx.Head), Sex: proto.Int32(playerEx.Sex), Coin: proto.Int64(playerEx.Coin), Pos: proto.Int(playerEx.Pos), Flag: proto.Int(playerEx.GetFlag()), City: proto.String(playerEx.City), HeadOutLine: proto.Int32(playerEx.HeadOutLine), VIP: proto.Int32(playerEx.VIP), } pack.Player = pd } //get data Response, err := slots.SlotsMgrSington.Enter(playerEx.SlotsSession, int64(s.GameId)) if err != nil { logger.Logger.Error("slots enter err:", err) } //sceneEx.EnterResponseFixCoin(Response, reload) Response.BetSizes = []int64{100, 1000, 2000, 5000, 7500, 20000} Response.BetChangeList = []float64{} sceneEx.BetLevel = Response.BetLevels pi, _ := json.Marshal(Response) pack.PlayerInfo = string(pi) proto.SetDefaults(pack) return pack } func (this *ScenePolicySugarRush) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { if s == nil || p == nil { return false } logger.Logger.Trace("(this *ScenePolicySugarRush) OnPlayerOp, sceneId=", s.GetSceneId(), " player=", p.SnId, " opcode=", opcode, " params=", params) if s.GetSceneState() != nil { if s.GetSceneState().OnPlayerOp(s, p, opcode, params) { p.SetLastOPTimer(time.Now()) return true } return false } return true } func (this *ScenePolicySugarRush) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicySugarRush) OnPlayerEvent, sceneId=", s.GetSceneId(), " player=", p.SnId, " eventcode=", evtcode, " params=", params) if s.GetSceneState() != nil { s.GetSceneState().OnPlayerEvent(s, p, evtcode, params) } } // 当前状态能否换桌 func (this *ScenePolicySugarRush) CanChangeCoinScene(s *base.Scene, p *base.Player) bool { if s == nil || p == nil { return false } if s.GetSceneState() != nil { return s.GetSceneState().CanChangeCoinScene(s, p) } return false } // 状态基类 type SceneBaseStateSugarRush struct { } func (this *SceneBaseStateSugarRush) GetTimeout(s *base.Scene) int { if sceneEx, ok := s.GetExtraData().(*SugarRushSceneData); ok { return int(time.Now().Sub(sceneEx.GetStateStartTime()) / time.Second) } return 0 } func (this *SceneBaseStateSugarRush) CanChangeTo(s base.SceneState) bool { return true } // 当前状态能否换桌 func (this *SceneBaseStateSugarRush) CanChangeCoinScene(s *base.Scene, p *base.Player) bool { return true } func (this *SceneBaseStateSugarRush) OnEnter(s *base.Scene) { if sceneEx, ok := s.GetExtraData().(*SugarRushSceneData); ok { sceneEx.SetStateStartTime(time.Now()) } } func (this *SceneBaseStateSugarRush) OnLeave(s *base.Scene) {} func (this *SceneBaseStateSugarRush) OnTick(s *base.Scene) { if time.Now().Sub(s.GameStartTime) > time.Second*3 { if sceneEx, ok := s.ExtraData.(*SugarRushSceneData); ok { for _, p := range sceneEx.players { if p.IsOnLine() { p.leaveTime = 0 continue } p.leaveTime++ if p.leaveTime < 60*2 { continue } //踢出玩家 sceneEx.PlayerLeave(p.Player, common.PlayerLeaveReason_LongTimeNoOp, true) } } s.GameStartTime = time.Now() } } func (this *SceneBaseStateSugarRush) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { return false } func (this *SceneBaseStateSugarRush) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { } // //////////////////////////////////////////////////////////// // 开始状态 // //////////////////////////////////////////////////////////// type SceneStateStartSugarRush struct { SceneBaseStateSugarRush } func (this *SceneStateStartSugarRush) GetState() int { return sugarrush.SugarRushStateStart } func (this *SceneStateStartSugarRush) CanChangeTo(s base.SceneState) bool { return false } // 当前状态能否换桌 func (this *SceneStateStartSugarRush) CanChangeCoinScene(s *base.Scene, p *base.Player) bool { if playerEx, ok := p.GetExtraData().(*SugarRushPlayerData); ok { if playerEx.isFree { return false } } return true } func (this *SceneStateStartSugarRush) GetTimeout(s *base.Scene) int { return 0 } func (this *SceneStateStartSugarRush) OnEnter(s *base.Scene) { this.SceneBaseStateSugarRush.OnEnter(s) if sceneEx, ok := s.GetExtraData().(*SugarRushSceneData); ok { sceneEx.SetGameNowTime(time.Now()) } } // 状态离开时 func (this *SceneStateStartSugarRush) OnLeave(s *base.Scene) { this.SceneBaseStateSugarRush.OnLeave(s) logger.Logger.Tracef("(this *SceneStateStartSugarRush) OnLeave, sceneid=%v", s.GetSceneId()) } // 玩家操作 func (this *SceneStateStartSugarRush) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { logger.Logger.Tracef("(this *SceneStateStartSugarRush) OnPlayerOp, sceneid=%v params=%v", s.GetSceneId(), params) if this.SceneBaseStateSugarRush.OnPlayerOp(s, p, opcode, params) { return true } if sceneEx, ok := s.GetExtraData().(*SugarRushSceneData); ok { if playerEx, ok := p.GetExtraData().(*SugarRushPlayerData); ok { switch opcode { case sugarrush.SugarRushPlayerOpStart: playerEx.Clear() if len(params) < 2 { pack := &protocol.SCSugarRushBilled{ OpRetCode: proto.Int32(1), } proto.SetDefaults(pack) logger.Logger.Trace("SCSugarRushBilled", pack.String()) playerEx.SendToClient(int(protocol.SugarRushPID_PACKET_SUGARRUSH_SCSUGARRUSHBILLED), pack) return true } cval := params[0] playerEx.BetMode = params[1] //playerEx.SlotsSession.SetCoin(playerEx.Coin) //logger.Logger.Trace("=============init dif coin", playerEx.Coin-playerEx.SlotsSession.Coin()) index := slots.SlotsMgrSington.PPGetBetIndex(playerEx.SlotsSession, "SugarRush", float64(cval*20)) if index == nil { pack := &protocol.SCSugarRushBilled{ OpRetCode: proto.Int32(2), } proto.SetDefaults(pack) logger.Logger.Trace("SCSugarRushBilled:", pack.String()) playerEx.SendToClient(int(protocol.SugarRushPID_PACKET_SUGARRUSH_SCSUGARRUSHBILLED), pack) return true } needCoin := cval * 20 * sceneEx.BetLevel[index[1]] if needCoin > playerEx.Coin && !playerEx.isFree { pack := &protocol.SCSugarRushBilled{ OpRetCode: proto.Int32(3), } proto.SetDefaults(pack) logger.Logger.Trace("SCSugarRushBilled:", pack.String()) playerEx.SendToClient(int(protocol.SugarRushPID_PACKET_SUGARRUSH_SCSUGARRUSHBILLED), pack) return true } //get data Response, err := slots.SlotsMgrSington.Play(playerEx.SlotsSession, &base.SpinReq{ GameId: int64(sceneEx.GameId), BetSizeIndex: index[0], BetLevelIndex: index[1], BetLineIndex: 0, BetMode: playerEx.BetMode, Ts: time.Now().Unix(), }) //sceneEx.PlayResponseFixCoin(Response) if err != nil { logger.Logger.Error("slots Play err:", err) pack := &protocol.SCSugarRushBilled{ OpRetCode: proto.Int32(3), } proto.SetDefaults(pack) logger.Logger.Trace("SCSugarRushBilled:", pack.String()) playerEx.SendToClient(int(protocol.SugarRushPID_PACKET_SUGARRUSH_SCSUGARRUSHBILLED), pack) return true } var ActualWin = Response.ActualWin s.SetGameNowTime(time.Now()) midNodes := Response.NodeTree.Nodes[1] lastNodes := Response.NodeTree.Nodes[2] playerEx.isFree = false var needWinBilled = true var totalIn, totalOut int64 //下注 if midNodes.Type == "BaseSpin" && lastNodes.Type == "FreeSpin" { playerEx.isFree = true needWinBilled = false if lastNodes.ProgressValue == 0 { //第一次触发 playerEx.totalBet = Response.ActualBet playerEx.AddCoin(-playerEx.totalBet, common.GainWay_HundredSceneLost, base.SyncFlag_ToClient, "system", s.GetSceneName()) totalIn = playerEx.totalBet } if lastNodes.ProgressValue == lastNodes.ProgressMax { needWinBilled = true } } else { //正常模式 playerEx.totalBet = Response.ActualBet totalIn = playerEx.totalBet playerEx.AddCoin(-playerEx.totalBet, common.GainWay_HundredSceneLost, base.SyncFlag_ToClient, "system", s.GetSceneName()) } if needWinBilled { var taxCoin int64 if ActualWin > 0 { //税收比例 taxRate := sceneEx.GetDBGameFree().GetTaxRate() if taxRate < 0 || taxRate > 10000 { taxRate = 500 } taxCoin = ActualWin * int64(taxRate) / 10000 playerEx.AddServiceFee(taxCoin) playerEx.taxCoin = taxCoin playerEx.winCoin = ActualWin - taxCoin ActualWin = playerEx.winCoin } totalOut = ActualWin playerEx.AddCoin(ActualWin, common.GainWay_HundredSceneWin, 0, "system", s.GetSceneName()) //免费游戏结束或者正常模式 sceneEx.StaticsLaba(&base.StaticLabaParam{ SnId: playerEx.SnId, Gain: ActualWin - playerEx.totalBet, GainTax: playerEx.taxCoin, IsAddTimes: true, }) } playerEx.SlotsSession.SetCoin(Response.Coin) pi, _ := json.Marshal(Response) gameEndStr := string(pi) pack := &protocol.SCSugarRushBilled{ OpRetCode: proto.Int32(0), GameEndStr: proto.String(gameEndStr), } proto.SetDefaults(pack) logger.Logger.Trace("SCSugarRushBilled", pack.String()) playerEx.SendToClient(int(protocol.SugarRushPID_PACKET_SUGARRUSH_SCSUGARRUSHBILLED), pack) if playerEx.Coin != ActualWin { logger.Logger.Error("==========playerEx.Coin != Response.Coin==============", playerEx.Coin, ActualWin) } // 记录本次操作 SugarRushAndSaveLog(sceneEx, playerEx, Response, totalIn, totalOut) case 1000: playerEx.Save(0) } } } return true } // 玩家事件 func (this *SceneStateStartSugarRush) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { logger.Logger.Trace("(this *SceneStateStartSugarRush) OnPlayerEvent, sceneId=", s.GetSceneId(), " player=", p.SnId, " evtcode=", evtcode) this.SceneBaseStateSugarRush.OnPlayerEvent(s, p, evtcode, params) } func (this *SceneStateStartSugarRush) OnTick(s *base.Scene) { this.SceneBaseStateSugarRush.OnTick(s) } // ////////////////////////////////////////////////////////////////////////////// func (this *ScenePolicySugarRush) RegisteSceneState(state base.SceneState) { if state == nil { return } stateid := state.GetState() if stateid < 0 || stateid >= sugarrush.SugarRushStateMax { return } this.states[stateid] = state } func (this *ScenePolicySugarRush) GetSceneState(s *base.Scene, stateid int) base.SceneState { if stateid >= 0 && stateid < sugarrush.SugarRushStateMax { return this.states[stateid] } return nil } func SugarRushAndSaveLog(sceneEx *SugarRushSceneData, playerEx *SugarRushPlayerData, Response *cli.SlotsPlayResponse, totalIn, totalOut int64) { if !playerEx.IsRob { info, err := model.MarshalGameNoteByROLL(Response) if err == nil { logid, _ := model.AutoIncGameLogId() playerEx.currentLogId = logid playerEx.Cache(sceneEx.Scene, &base.SaveGameDetailedParam{ LogId: logid, Detail: info, }, &base.SaveGamePlayerListLogParam{ LogId: logid, Platform: playerEx.Platform, Snid: playerEx.SnId, PlayerName: playerEx.Name, TotalIn: totalIn, TotalOut: totalOut, TaxCoin: playerEx.taxCoin, BetAmount: totalIn, WinAmountNoAnyTax: totalOut - totalIn - playerEx.taxCoin, IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player), IsFree: playerEx.isFree, }) } } //统计输下注金币数 if !sceneEx.Testing && !playerEx.IsRob { playerBet := &server.PlayerData{ SnId: proto.Int32(playerEx.SnId), Bet: proto.Int64(playerEx.CurrentBet), Gain: proto.Int64(Response.ActualWin + playerEx.taxCoin), Tax: proto.Int64(playerEx.taxCoin), Coin: proto.Int64(playerEx.GetCoin()), GameCoinTs: proto.Int64(playerEx.GameCoinTs), } gwPlayerBet := &server.GWPlayerData{ SceneId: sceneEx.SceneId, GameFreeId: proto.Int32(sceneEx.GetDBGameFree().GetId()), } gwPlayerBet.Datas = append(gwPlayerBet.Datas, playerBet) sceneEx.SyncPlayerDatas(&base.PlayerDataParam{ HasRobotGaming: false, Data: gwPlayerBet, }) } playerEx.taxCoin = 0 playerEx.winCoin = 0 if sceneEx.CheckNeedDestroy() && !playerEx.isFree { sceneEx.SceneDestroy(true) } } func init() { //主状态 ScenePolicySugarRushSington.RegisteSceneState(&SceneStateStartSugarRush{}) core.RegisteHook(core.HOOK_BEFORE_START, func() error { base.RegisteScenePolicy(common.GameId_SugarRush, sugarrush.RoomMode_Classic, ScenePolicySugarRushSington) return nil }) }