package fortunetiger import ( "encoding/json" "mongo.games.com/game/common" "mongo.games.com/game/gamerule/fortunetiger" "mongo.games.com/game/gamesrv/base" "mongo.games.com/game/gamesrv/slotspkg/assemble" "mongo.games.com/game/gamesrv/slotspkg/slots" "mongo.games.com/game/model" "mongo.games.com/game/proto" protocol "mongo.games.com/game/protocol/fortunetiger" "mongo.games.com/game/protocol/server" "mongo.games.com/goserver/core" "mongo.games.com/goserver/core/logger" "time" ) // //////////////////////////////////////////////////////////// var ScenePolicyFortuneTigerSington = &ScenePolicyFortuneTiger{} type ScenePolicyFortuneTiger struct { base.BaseScenePolicy states [fortunetiger.FortuneTigerStateMax]base.SceneState } // 创建场景扩展数据 func (this *ScenePolicyFortuneTiger) CreateSceneExData(s *base.Scene) interface{} { sceneEx := NewFortuneTigerSceneData(s) if sceneEx != nil { if sceneEx.GetInit() { s.SetExtraData(sceneEx) } } return sceneEx } // 创建玩家扩展数据 func (this *ScenePolicyFortuneTiger) CreatePlayerExData(s *base.Scene, p *base.Player) interface{} { playerEx := &FortuneTigerPlayerData{Player: p} p.SetExtraData(playerEx) return playerEx } // 场景开启事件 func (this *ScenePolicyFortuneTiger) OnStart(s *base.Scene) { logger.Logger.Trace("(this *ScenePolicyFortuneTiger) OnStart, sceneId=", s.GetSceneId()) sceneEx := NewFortuneTigerSceneData(s) if sceneEx != nil { if sceneEx.GetInit() { s.SetExtraData(sceneEx) s.ChangeSceneState(fortunetiger.FortuneTigerStateStart) } } } // 场景关闭事件 func (this *ScenePolicyFortuneTiger) OnStop(s *base.Scene) { logger.Logger.Trace("(this *ScenePolicyFortuneTiger) OnStop , sceneId=", s.GetSceneId()) } // 场景心跳事件 func (this *ScenePolicyFortuneTiger) OnTick(s *base.Scene) { if s == nil { return } if s.GetSceneState() != nil { s.GetSceneState().OnTick(s) } } // 玩家进入事件 func (this *ScenePolicyFortuneTiger) OnPlayerEnter(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyFortuneTiger) OnPlayerEnter, sceneId=", s.GetSceneId(), " player=", p.Name) if sceneEx, ok := s.GetExtraData().(*FortuneTigerSceneData); ok { playerEx := &FortuneTigerPlayerData{Player: p} playerEx.init() d := p.GameData[fortunetiger.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 * fortunetiger.NowByte) playerEx.Clear() sceneEx.players[p.SnId] = playerEx p.SetExtraData(playerEx) FortuneTigerSendRoomInfo(s, sceneEx, playerEx) s.FirePlayerEvent(p, base.PlayerEventEnter, nil) } } // 玩家离开事件 func (this *ScenePolicyFortuneTiger) OnPlayerLeave(s *base.Scene, p *base.Player, reason int) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyFortuneTiger) OnPlayerLeave, sceneId=", s.GetSceneId(), " player=", p.SnId) if playerEx, ok := p.ExtraData.(*FortuneTigerPlayerData); ok { 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[fortunetiger.GameDataKey] = &model.PlayerGameData{ Platform: p.Platform, SnId: p.SnId, Id: fortunetiger.GameDataKey, Data: b, } } } } if sceneEx, ok := s.ExtraData.(*FortuneTigerSceneData); ok { s.FirePlayerEvent(p, base.PlayerEventLeave, nil) sceneEx.OnPlayerLeave(p, reason) } } // 玩家掉线 func (this *ScenePolicyFortuneTiger) OnPlayerDropLine(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyFortuneTiger) OnPlayerDropLine, sceneId=", s.GetSceneId(), " player=", p.SnId) s.FirePlayerEvent(p, base.PlayerEventDropLine, nil) } // 玩家重连 func (this *ScenePolicyFortuneTiger) OnPlayerRehold(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyFortuneTiger) OnPlayerRehold, sceneId=", s.GetSceneId(), " player=", p.SnId) if sceneEx, ok := s.GetExtraData().(*FortuneTigerSceneData); ok { if playerEx, ok := p.GetExtraData().(*FortuneTigerPlayerData); ok { FortuneTigerSendRoomInfo(s, sceneEx, playerEx) } } } // 返回房间 func (this *ScenePolicyFortuneTiger) OnPlayerReturn(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyFortuneTiger) OnPlayerReturn, GetSceneId()=", s.GetSceneId(), " player=", p.Name) if sceneEx, ok := s.GetExtraData().(*FortuneTigerSceneData); ok { if playerEx, ok := p.GetExtraData().(*FortuneTigerPlayerData); ok { //if p.IsMarkFlag(base.PlayerState_Auto) { // p.UnmarkFlag(base.PlayerState_Auto) // p.SyncFlag() //} //发送房间信息给自己 FortuneTigerSendRoomInfo(s, sceneEx, playerEx) s.FirePlayerEvent(p, base.PlayerEventReturn, nil) } } } func FortuneTigerSendRoomInfo(s *base.Scene, sceneEx *FortuneTigerSceneData, playerEx *FortuneTigerPlayerData) { pack := FortuneTigerCreateRoomInfoPacket(s, sceneEx, playerEx) logger.Logger.Trace("RoomInfo: ", pack) playerEx.SendToClient(int(protocol.FortuneTigerPID_PACKET_FORTUNETIGER_SCFORTUNETIGERROOMINFO), pack) } func FortuneTigerCreateRoomInfoPacket(s *base.Scene, sceneEx *FortuneTigerSceneData, playerEx *FortuneTigerPlayerData) interface{} { //房间信息 pack := &protocol.SCFortuneTigerRoomInfo{ 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.FortuneTigerPlayerData{ 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 { data := assemble.DataToCli(Response).(assemble.TableInfo) pi, _ := json.Marshal(data) pack.PlayerInfo = string(pi) if sceneEx.BetConfig == nil { sceneEx.BetConfig = &data.BetConfig } } else { logger.Logger.Error("slots enter err:", err) } proto.SetDefaults(pack) return pack } func (this *ScenePolicyFortuneTiger) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { if s == nil || p == nil { return false } logger.Logger.Trace("(this *ScenePolicyFortuneTiger) 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 *ScenePolicyFortuneTiger) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyFortuneTiger) OnPlayerEvent, sceneId=", s.GetSceneId(), " player=", p.SnId, " eventcode=", evtcode, " params=", params) if s.GetSceneState() != nil { s.GetSceneState().OnPlayerEvent(s, p, evtcode, params) } } // 当前状态能否换桌 func (this *ScenePolicyFortuneTiger) 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 SceneBaseStateFortuneTiger struct { } func (this *SceneBaseStateFortuneTiger) GetTimeout(s *base.Scene) int { if sceneEx, ok := s.GetExtraData().(*FortuneTigerSceneData); ok { return int(time.Now().Sub(sceneEx.GetStateStartTime()) / time.Second) } return 0 } func (this *SceneBaseStateFortuneTiger) CanChangeTo(s base.SceneState) bool { return true } // 当前状态能否换桌 func (this *SceneBaseStateFortuneTiger) CanChangeCoinScene(s *base.Scene, p *base.Player) bool { return true } func (this *SceneBaseStateFortuneTiger) OnEnter(s *base.Scene) { if sceneEx, ok := s.GetExtraData().(*FortuneTigerSceneData); ok { sceneEx.SetStateStartTime(time.Now()) } } func (this *SceneBaseStateFortuneTiger) OnLeave(s *base.Scene) {} func (this *SceneBaseStateFortuneTiger) OnTick(s *base.Scene) { if time.Now().Sub(s.GameStartTime) > time.Second*3 { if sceneEx, ok := s.ExtraData.(*FortuneTigerSceneData); 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 *SceneBaseStateFortuneTiger) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { return false } func (this *SceneBaseStateFortuneTiger) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { } // //////////////////////////////////////////////////////////// // 开始状态 // //////////////////////////////////////////////////////////// type SceneStateStartFortuneTiger struct { SceneBaseStateFortuneTiger } func (this *SceneStateStartFortuneTiger) GetState() int { return fortunetiger.FortuneTigerStateStart } func (this *SceneStateStartFortuneTiger) CanChangeTo(s base.SceneState) bool { return false } // 当前状态能否换桌 func (this *SceneStateStartFortuneTiger) CanChangeCoinScene(s *base.Scene, p *base.Player) bool { if playerEx, ok := p.GetExtraData().(*FortuneTigerPlayerData); ok { if playerEx.isRespin { return false } } return true } func (this *SceneStateStartFortuneTiger) GetTimeout(s *base.Scene) int { return 0 } func (this *SceneStateStartFortuneTiger) OnEnter(s *base.Scene) { this.SceneBaseStateFortuneTiger.OnEnter(s) if sceneEx, ok := s.GetExtraData().(*FortuneTigerSceneData); ok { sceneEx.SetGameNowTime(time.Now()) } } // 状态离开时 func (this *SceneStateStartFortuneTiger) OnLeave(s *base.Scene) { this.SceneBaseStateFortuneTiger.OnLeave(s) logger.Logger.Tracef("(this *SceneStateStartFortuneTiger) OnLeave, sceneid=%v", s.GetSceneId()) } // 玩家操作 func (this *SceneStateStartFortuneTiger) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { logger.Logger.Tracef("(this *SceneStateStartFortuneTiger) OnPlayerOp, sceneid=%v params=%v", s.GetSceneId(), params) if this.SceneBaseStateFortuneTiger.OnPlayerOp(s, p, opcode, params) { return true } if sceneEx, ok := s.GetExtraData().(*FortuneTigerSceneData); ok { if playerEx, ok := p.GetExtraData().(*FortuneTigerPlayerData); ok { switch opcode { case fortunetiger.FortuneTigerPlayerOpStart: playerEx.Clear() if len(params) < 3 { pack := &protocol.SCFortuneTigerBilled{ OpRetCode: proto.Int32(1), } proto.SetDefaults(pack) logger.Logger.Trace("SCFortuneTigerBilled", pack.String()) playerEx.SendToClient(int(protocol.FortuneTigerPID_PACKET_FORTUNETIGER_SCFORTUNETIGERBILLED), pack) return true } playerEx.BetSizeIndex = params[0] playerEx.BetLevelIndex = params[1] playerEx.BetLineIndex = params[2] //playerEx.BetMode = params[3] needCoin := sceneEx.BetConfig.BetSize[params[0]] * float64(sceneEx.BetConfig.BetLevel[params[1]]) * float64(sceneEx.BetConfig.BetLines[params[2]]) if needCoin > float64(playerEx.Coin) { pack := &protocol.SCFortuneTigerBilled{ OpRetCode: proto.Int32(1), } proto.SetDefaults(pack) logger.Logger.Trace("SCFortuneTigerBilled:", pack.String()) playerEx.SendToClient(int(protocol.FortuneTigerPID_PACKET_FORTUNETIGER_SCFORTUNETIGERBILLED), pack) return true } //playerEx.SlotsSession.SetCoin(playerEx.Coin * fortunetiger.NowByte) //logger.Logger.Trace("=============init dif coin", playerEx.Coin-playerEx.SlotsSession.Coin()/fortunetiger.NowByte) //get data Response, err := slots.SlotsMgrSington.Play(playerEx.SlotsSession, &base.SpinReq{ GameId: int64(sceneEx.GameId), BetSizeIndex: playerEx.BetSizeIndex, BetLevelIndex: playerEx.BetLevelIndex, BetLineIndex: playerEx.BetLineIndex, BetMode: playerEx.BetMode, Ts: time.Now().Unix(), }) var gameEndStr string var data assemble.GameEnd if err == nil { s.SetGameNowTime(time.Now()) data = assemble.DataToCli(Response).(assemble.GameEnd) var respinStatus int if data.Results[0].ArrSpins[0].Special != nil { respinStatus = data.Results[0].ArrSpins[0].Special.(SpinLock).ReSpinStatus } if respinStatus == 0 || respinStatus == 1 { //第一次触发或者正常模式 //logger.Logger.Trace("=============addcoin1111 ", -data.TotalBet) playerEx.AddCoin(int64(-data.TotalBet), common.GainWay_HundredSceneLost, base.SyncFlag_ToClient, "system", s.GetSceneName()) playerEx.totalBet = int64(data.TotalBet) //logger.Logger.Trace("=======bet======dif++++ ", float64(playerEx.Coin)-data.BetAfterCoin) } var taxCoin float64 if data.RoundReward > 0 { //税收比例 taxRate := sceneEx.GetDBGameFree().GetTaxRate() if taxRate < 0 || taxRate > 10000 { taxRate = 500 } taxCoin = data.RoundReward * float64(taxRate) / 10000 data.RoundReward = data.RoundReward - taxCoin playerEx.AddServiceFee(int64(taxCoin)) playerEx.taxCoin = int64(taxCoin) playerEx.winCoin = int64(data.RoundReward) } pi, _ := json.Marshal(data) gameEndStr = string(pi) if respinStatus == 0 || respinStatus == 3 { //logger.Logger.Trace("===win==========addcoin222 ", data.RoundReward) playerEx.AddCoin(int64(data.RoundReward), common.GainWay_HundredSceneWin, 0, "system", s.GetSceneName()) //logger.Logger.Trace("=======win======dif++++ ", float64(playerEx.Coin)-data.FinalCoin) //免费游戏结束或者正常模式 sceneEx.StaticsLaba(&base.StaticLabaParam{ SnId: playerEx.SnId, Gain: int64(data.RoundReward - data.TotalBet), GainTax: int64(taxCoin), IsAddTimes: true, }) } if respinStatus == 0 || respinStatus == 3 { playerEx.isRespin = false } else { playerEx.isRespin = true } } else { logger.Logger.Error("slots Play err:", err) } playerEx.SlotsSession.SetCoin(int64(data.FinalCoin) * fortunetiger.NowByte) //logger.Logger.Trace("======end=======init dif coin", playerEx.Coin-playerEx.SlotsSession.Coin()/fortunetiger.NowByte) if playerEx.Coin != int64(data.FinalCoin) { logger.Logger.Error("==========playerEx.Coin != data.FinalCoin==============", (float64(playerEx.Coin)-data.FinalCoin)/10000) } pack := &protocol.SCFortuneTigerBilled{ OpRetCode: proto.Int32(0), GameEndStr: proto.String(gameEndStr), } proto.SetDefaults(pack) logger.Logger.Trace("SCFortuneTigerBilled", pack.String()) playerEx.SendToClient(int(protocol.FortuneTigerPID_PACKET_FORTUNETIGER_SCFORTUNETIGERBILLED), pack) // 记录本次操作 FortuneTigerAndSaveLog(sceneEx, playerEx, data) } } } return true } // 玩家事件 func (this *SceneStateStartFortuneTiger) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { logger.Logger.Trace("(this *SceneStateStartFortuneTiger) OnPlayerEvent, sceneId=", s.GetSceneId(), " player=", p.SnId, " evtcode=", evtcode) this.SceneBaseStateFortuneTiger.OnPlayerEvent(s, p, evtcode, params) } func (this *SceneStateStartFortuneTiger) OnTick(s *base.Scene) { this.SceneBaseStateFortuneTiger.OnTick(s) } // ////////////////////////////////////////////////////////////////////////////// func (this *ScenePolicyFortuneTiger) RegisteSceneState(state base.SceneState) { if state == nil { return } stateid := state.GetState() if stateid < 0 || stateid >= fortunetiger.FortuneTigerStateMax { return } this.states[stateid] = state } func (this *ScenePolicyFortuneTiger) GetSceneState(s *base.Scene, stateid int) base.SceneState { if stateid >= 0 && stateid < fortunetiger.FortuneTigerStateMax { return this.states[stateid] } return nil } func FortuneTigerAndSaveLog(sceneEx *FortuneTigerSceneData, playerEx *FortuneTigerPlayerData, data assemble.GameEnd) { if !playerEx.IsRob { data.SnId = playerEx.SnId if data.Results[0].FreeStatus != 1 && data.Results[0].FreeNumMax != 0 { data.TotalBet = 0 } info, err := model.MarshalGameNoteByROLL(data) if err == nil { logid, _ := model.AutoIncGameLogId() playerEx.currentLogId = logid sceneEx.SaveGameDetailedLog(&base.SaveGameDetailedParam{ LogId: logid, Detail: info, GameTime: 2, }) var totalin, totalout int64 if data.Results[0].FreeStatus == 1 || data.Results[0].FreeNumMax == 0 { totalin = playerEx.totalBet } if data.Results[0].FreeStatus == 3 || data.Results[0].FreeNumMax == 0 { totalout = int64(data.RoundReward) + playerEx.taxCoin } sceneEx.SaveGamePlayerListLog(&base.SaveGamePlayerListLogParam{ LogId: logid, Platform: playerEx.Platform, Snid: playerEx.SnId, PlayerName: playerEx.Name, Channel: playerEx.Channel, ChannelId: playerEx.ChannelId, TotalIn: totalin, TotalOut: totalout, TaxCoin: playerEx.taxCoin, BetAmount: totalin, WinAmountNoAnyTax: totalout - totalin - playerEx.taxCoin, IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player), IsFree: totalin == 0, GameTime: 2, }) } } //统计输下注金币数 if !sceneEx.Testing && !playerEx.IsRob { playerBet := &server.PlayerData{ SnId: proto.Int32(playerEx.SnId), Bet: proto.Int64(playerEx.CurrentBet), Gain: proto.Int64(int64(data.RoundReward) + 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() && data.Results[0].FreeNum <= 0 { sceneEx.SceneDestroy(true) } } func init() { //主状态 ScenePolicyFortuneTigerSington.RegisteSceneState(&SceneStateStartFortuneTiger{}) core.RegisteHook(core.HOOK_BEFORE_START, func() error { base.RegisteScenePolicy(common.GameId_FortuneTiger, fortunetiger.RoomMode_Classic, ScenePolicyFortuneTigerSington) return nil }) }