package fortunedragon import ( "encoding/json" "mongo.games.com/game/protocol/server" "time" "mongo.games.com/goserver/core" "mongo.games.com/goserver/core/logger" "mongo.games.com/game/common" "mongo.games.com/game/gamerule/fortunedragon" "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/fortunedragon" ) // //////////////////////////////////////////////////////////// var ScenePolicyFortuneDragonSington = &ScenePolicyFortuneDragon{} type ScenePolicyFortuneDragon struct { base.BaseScenePolicy states [fortunedragon.FortuneDragonStateMax]base.SceneState } // 创建场景扩展数据 func (this *ScenePolicyFortuneDragon) CreateSceneExData(s *base.Scene) interface{} { sceneEx := NewFortuneDragonSceneData(s) if sceneEx != nil { if sceneEx.GetInit() { s.SetExtraData(sceneEx) } } return sceneEx } // 创建玩家扩展数据 func (this *ScenePolicyFortuneDragon) CreatePlayerExData(s *base.Scene, p *base.Player) interface{} { playerEx := &FortuneDragonPlayerData{Player: p} p.SetExtraData(playerEx) return playerEx } // 场景开启事件 func (this *ScenePolicyFortuneDragon) OnStart(s *base.Scene) { logger.Logger.Trace("(this *ScenePolicyFortuneDragon) OnStart, sceneId=", s.GetSceneId()) sceneEx := NewFortuneDragonSceneData(s) if sceneEx != nil { if sceneEx.GetInit() { s.SetExtraData(sceneEx) s.ChangeSceneState(fortunedragon.FortuneDragonStateStart) } } } // 场景关闭事件 func (this *ScenePolicyFortuneDragon) OnStop(s *base.Scene) { logger.Logger.Trace("(this *ScenePolicyFortuneDragon) OnStop , sceneId=", s.GetSceneId()) } // 场景心跳事件 func (this *ScenePolicyFortuneDragon) OnTick(s *base.Scene) { if s == nil { return } if s.GetSceneState() != nil { s.GetSceneState().OnTick(s) } } // 玩家进入事件 func (this *ScenePolicyFortuneDragon) OnPlayerEnter(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyFortuneDragon) OnPlayerEnter, sceneId=", s.GetSceneId(), " player=", p.Name) if sceneEx, ok := s.GetExtraData().(*FortuneDragonSceneData); ok { playerEx := &FortuneDragonPlayerData{Player: p} playerEx.init() d := p.GameData[fortunedragon.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 * fortunedragon.NowByte) playerEx.Clear() sceneEx.players[p.SnId] = playerEx p.SetExtraData(playerEx) FortuneDragonSendRoomInfo(s, sceneEx, playerEx) s.FirePlayerEvent(p, base.PlayerEventEnter, nil) } } // 玩家离开事件 func (this *ScenePolicyFortuneDragon) OnPlayerLeave(s *base.Scene, p *base.Player, reason int) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyFortuneDragon) OnPlayerLeave, sceneId=", s.GetSceneId(), " player=", p.SnId) if playerEx, ok := p.ExtraData.(*FortuneDragonPlayerData); 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[fortunedragon.GameDataKey] = &model.PlayerGameData{ Platform: p.Platform, SnId: p.SnId, Id: fortunedragon.GameDataKey, Data: b, } } } } if sceneEx, ok := s.ExtraData.(*FortuneDragonSceneData); ok { s.FirePlayerEvent(p, base.PlayerEventLeave, nil) sceneEx.OnPlayerLeave(p, reason) } } // 玩家掉线 func (this *ScenePolicyFortuneDragon) OnPlayerDropLine(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyFortuneDragon) OnPlayerDropLine, sceneId=", s.GetSceneId(), " player=", p.SnId) s.FirePlayerEvent(p, base.PlayerEventDropLine, nil) } // 玩家重连 func (this *ScenePolicyFortuneDragon) OnPlayerRehold(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyFortuneDragon) OnPlayerRehold, sceneId=", s.GetSceneId(), " player=", p.SnId) if sceneEx, ok := s.GetExtraData().(*FortuneDragonSceneData); ok { if playerEx, ok := p.GetExtraData().(*FortuneDragonPlayerData); ok { FortuneDragonSendRoomInfo(s, sceneEx, playerEx) } } } // 返回房间 func (this *ScenePolicyFortuneDragon) OnPlayerReturn(s *base.Scene, p *base.Player) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyFortuneDragon) OnPlayerReturn, GetSceneId()=", s.GetSceneId(), " player=", p.Name) if sceneEx, ok := s.GetExtraData().(*FortuneDragonSceneData); ok { if playerEx, ok := p.GetExtraData().(*FortuneDragonPlayerData); ok { //if p.IsMarkFlag(base.PlayerState_Auto) { // p.UnmarkFlag(base.PlayerState_Auto) // p.SyncFlag() //} //发送房间信息给自己 FortuneDragonSendRoomInfo(s, sceneEx, playerEx) s.FirePlayerEvent(p, base.PlayerEventReturn, nil) } } } func FortuneDragonSendRoomInfo(s *base.Scene, sceneEx *FortuneDragonSceneData, playerEx *FortuneDragonPlayerData) { pack := FortuneDragonCreateRoomInfoPacket(s, sceneEx, playerEx) logger.Logger.Trace("RoomInfo: ", pack) playerEx.SendToClient(int(protocol.FortuneDragonPID_PACKET_FORTUNEDRAGON_SCFORTUNEDRAGONROOMINFO), pack) } func FortuneDragonCreateRoomInfoPacket(s *base.Scene, sceneEx *FortuneDragonSceneData, playerEx *FortuneDragonPlayerData) interface{} { //房间信息 pack := &protocol.SCFortuneDragonRoomInfo{ 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.FortuneDragonPlayerData{ 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 *ScenePolicyFortuneDragon) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { if s == nil || p == nil { return false } logger.Logger.Trace("(this *ScenePolicyFortuneDragon) 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 *ScenePolicyFortuneDragon) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { if s == nil || p == nil { return } logger.Logger.Trace("(this *ScenePolicyFortuneDragon) OnPlayerEvent, sceneId=", s.GetSceneId(), " player=", p.SnId, " eventcode=", evtcode, " params=", params) if s.GetSceneState() != nil { s.GetSceneState().OnPlayerEvent(s, p, evtcode, params) } } // 当前状态能否换桌 func (this *ScenePolicyFortuneDragon) 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 SceneBaseStateFortuneDragon struct { } func (this *SceneBaseStateFortuneDragon) GetTimeout(s *base.Scene) int { if sceneEx, ok := s.GetExtraData().(*FortuneDragonSceneData); ok { return int(time.Now().Sub(sceneEx.GetStateStartTime()) / time.Second) } return 0 } func (this *SceneBaseStateFortuneDragon) CanChangeTo(s base.SceneState) bool { return true } // 当前状态能否换桌 func (this *SceneBaseStateFortuneDragon) CanChangeCoinScene(s *base.Scene, p *base.Player) bool { return true } func (this *SceneBaseStateFortuneDragon) OnEnter(s *base.Scene) { if sceneEx, ok := s.GetExtraData().(*FortuneDragonSceneData); ok { sceneEx.SetStateStartTime(time.Now()) } } func (this *SceneBaseStateFortuneDragon) OnLeave(s *base.Scene) {} func (this *SceneBaseStateFortuneDragon) OnTick(s *base.Scene) { if time.Now().Sub(s.GameStartTime) > time.Second*3 { if sceneEx, ok := s.ExtraData.(*FortuneDragonSceneData); 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 *SceneBaseStateFortuneDragon) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { return false } func (this *SceneBaseStateFortuneDragon) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { } // //////////////////////////////////////////////////////////// // 开始状态 // //////////////////////////////////////////////////////////// type SceneStateStartFortuneDragon struct { SceneBaseStateFortuneDragon } func (this *SceneStateStartFortuneDragon) GetState() int { return fortunedragon.FortuneDragonStateStart } func (this *SceneStateStartFortuneDragon) CanChangeTo(s base.SceneState) bool { return false } // 当前状态能否换桌 func (this *SceneStateStartFortuneDragon) CanChangeCoinScene(s *base.Scene, p *base.Player) bool { if playerEx, ok := p.GetExtraData().(*FortuneDragonPlayerData); ok { if playerEx.isFree { return false } } return true } func (this *SceneStateStartFortuneDragon) GetTimeout(s *base.Scene) int { return 0 } func (this *SceneStateStartFortuneDragon) OnEnter(s *base.Scene) { this.SceneBaseStateFortuneDragon.OnEnter(s) if sceneEx, ok := s.GetExtraData().(*FortuneDragonSceneData); ok { sceneEx.SetGameNowTime(time.Now()) } } // 状态离开时 func (this *SceneStateStartFortuneDragon) OnLeave(s *base.Scene) { this.SceneBaseStateFortuneDragon.OnLeave(s) logger.Logger.Tracef("(this *SceneStateStartFortuneDragon) OnLeave, sceneid=%v", s.GetSceneId()) } // 玩家操作 func (this *SceneStateStartFortuneDragon) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool { logger.Logger.Tracef("(this *SceneStateStartFortuneDragon) OnPlayerOp, sceneid=%v params=%v", s.GetSceneId(), params) if this.SceneBaseStateFortuneDragon.OnPlayerOp(s, p, opcode, params) { return true } if sceneEx, ok := s.GetExtraData().(*FortuneDragonSceneData); ok { if playerEx, ok := p.GetExtraData().(*FortuneDragonPlayerData); ok { switch opcode { case fortunedragon.FortuneDragonPlayerOpStart: playerEx.Clear() if len(params) < 4 { pack := &protocol.SCFortuneDragonBilled{ OpRetCode: proto.Int32(1), } proto.SetDefaults(pack) logger.Logger.Trace("SCFortuneDragonBilled", pack.String()) playerEx.SendToClient(int(protocol.FortuneDragonPID_PACKET_FORTUNEDRAGON_SCFORTUNEDRAGONBILLED), pack) return true } playerEx.BetSizeIndex = params[0] playerEx.BetLevelIndex = params[1] playerEx.BetLineIndex = params[2] 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.SCFortuneDragonBilled{ OpRetCode: proto.Int32(1), } proto.SetDefaults(pack) logger.Logger.Trace("SCFortuneDragonBilled:", pack.String()) playerEx.SendToClient(int(protocol.FortuneDragonPID_PACKET_FORTUNEDRAGON_SCFORTUNEDRAGONBILLED), pack) return true } playerEx.BetMode = params[3] //playerEx.SlotsSession.SetCoin(playerEx.Coin * fortunedragon.NowByte) //logger.Logger.Trace("=====================init===== playerEx.Coin===", playerEx.Coin) //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 { data = assemble.DataToCli(Response).(assemble.GameEnd) if data.Results[0].FreeStatus == 1 || data.Results[0].FreeNumMax == 0 { //logger.Logger.Trace("=====================AddCoin=====TotalBet===", -data.TotalBet) //第一次触发或者正常模式 playerEx.AddCoin(int64(-data.TotalBet), common.GainWay_HundredSceneLost, base.SyncFlag_ToClient, "system", s.GetSceneName()) playerEx.totalBet = int64(data.TotalBet) } 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 data.Results[0].FreeStatus == 3 || data.Results[0].FreeNumMax == 0 { //logger.Logger.Trace("=====================AddCoin=====RoundReward===", data.RoundReward) playerEx.AddCoin(int64(data.RoundReward), common.GainWay_HundredSceneWin, 0, "system", s.GetSceneName()) //免费游戏结束或者正常模式 sceneEx.StaticsLaba(&base.StaticLabaParam{ SnId: playerEx.SnId, Gain: int64(data.RoundReward - data.TotalBet), GainTax: int64(taxCoin), IsAddTimes: true, }) } if data.Results[0].FreeNum > 0 { playerEx.isFree = true } else { playerEx.isFree = false } } else { logger.Logger.Error("slots Play err:", err) } playerEx.SlotsSession.SetCoin(int64(data.FinalCoin) * fortunedragon.NowByte) //logger.Logger.Trace("=====================end===== playerEx.Coin===", playerEx.Coin) //logger.Logger.Trace("=====================end===== data.FinalCoin===", data.FinalCoin) pack := &protocol.SCFortuneDragonBilled{ OpRetCode: proto.Int32(0), GameEndStr: proto.String(gameEndStr), } proto.SetDefaults(pack) logger.Logger.Trace("SCFortuneDragonBilled", pack.String()) playerEx.SendToClient(int(protocol.FortuneDragonPID_PACKET_FORTUNEDRAGON_SCFORTUNEDRAGONBILLED), pack) if playerEx.Coin != int64(data.FinalCoin) { logger.Logger.Error("==========playerEx.Coin != Response.Coin==============", playerEx.Coin, data.FinalCoin) } // 记录本次操作 FortuneDragonAndSaveLog(sceneEx, playerEx, data) } } } return true } // 玩家事件 func (this *SceneStateStartFortuneDragon) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) { logger.Logger.Trace("(this *SceneStateStartFortuneDragon) OnPlayerEvent, sceneId=", s.GetSceneId(), " player=", p.SnId, " evtcode=", evtcode) this.SceneBaseStateFortuneDragon.OnPlayerEvent(s, p, evtcode, params) } func (this *SceneStateStartFortuneDragon) OnTick(s *base.Scene) { this.SceneBaseStateFortuneDragon.OnTick(s) } // ////////////////////////////////////////////////////////////////////////////// func (this *ScenePolicyFortuneDragon) RegisteSceneState(state base.SceneState) { if state == nil { return } stateid := state.GetState() if stateid < 0 || stateid >= fortunedragon.FortuneDragonStateMax { return } this.states[stateid] = state } func (this *ScenePolicyFortuneDragon) GetSceneState(s *base.Scene, stateid int) base.SceneState { if stateid >= 0 && stateid < fortunedragon.FortuneDragonStateMax { return this.states[stateid] } return nil } func FortuneDragonAndSaveLog(sceneEx *FortuneDragonSceneData, playerEx *FortuneDragonPlayerData, 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(logid, info, &base.GameDetailedParam{}) 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 } validFlow := totalin + totalout validBet := common.AbsI64(totalin - totalout) logParam := &base.SaveGamePlayerListLogParam{ Platform: playerEx.Platform, Channel: playerEx.Channel, Promoter: playerEx.BeUnderAgentCode, PackageTag: playerEx.PackageID, InviterId: playerEx.InviterId, LogId: logid, TotalIn: totalin, TotalOut: totalout, TaxCoin: playerEx.taxCoin, BetAmount: totalin, WinAmountNoAnyTax: totalout - totalin - playerEx.taxCoin, ValidBet: validBet, ValidFlow: validFlow, IsFirstGame: sceneEx.IsPlayerFirst(playerEx.Player), } sceneEx.SaveGamePlayerListLog(playerEx.SnId, logParam) } } //统计输下注金币数 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() { //主状态 ScenePolicyFortuneDragonSington.RegisteSceneState(&SceneStateStartFortuneDragon{}) core.RegisteHook(core.HOOK_BEFORE_START, func() error { base.RegisteScenePolicy(common.GameId_FortuneDragon, fortunedragon.RoomMode_Classic, ScenePolicyFortuneDragonSington) return nil }) }