package crash import ( "fmt" "server/call" "server/common" "server/db" "server/game" "server/pb" "time" timewheel "github.com/liangdas/mqant/module/modules/timer" ) type Table struct { *game.Table Result int64 StartFlyTime int64 FlyTime int } func NewTable() game.SubTable { t := &Table{} return t } func (t *Table) Init(table *game.Table) { t.Table = table table.NewMillionSubTable() table.MillionSubTableInter = t } func (t *Table) Reset() { t.StartFlyTime = 0 t.FlyTime = 0 t.MillionSubTable.Reset() } func (t *Table) Enter(player *game.Player) { player.SubPlayer = NewPlayer(player) } func (t *Table) StartGame() { dur := t.Config.BetTime t.OperateTimeout = dur*1000 + time.Now().UnixMilli() t.StartFlyingTimer(time.Duration(dur) * time.Second) resp := &pb.CrashMsgGameStartResp{ TimeLeft: int64(dur), } t.Broadcast(int(pb.GameProtocol_GameStartResp), resp) } // SettleResult 获取结算结果 func (t *Table) SettleResult() { // diff := time.Now().UnixMilli() - t.StartFlyTime // t.Debug("fly diff:%v", diff) t.Result = GetOdds(int64(t.FlyTime)) + 100 t.Debug("result:%v", t.Result) l := len(t.History) t.History = append([]int64{t.Result}, t.History...) if l >= MaxHistoryLen { t.History = t.History[:MaxHistoryLen] } if call.IsMainServer(game.ThisGameID) { db.Redis().SetJsonData(common.GetRedisKeyGameResult(game.ThisGameID, t.Room.RoomId()), t.History) } } func (t *Table) Settle() { t.Debug("settle") t.SettleResult() dur := t.Config.SettleTime * 1000 t.SettleGameTimer(time.Duration(dur) * time.Millisecond) now := time.Now().UnixMilli() t.OperateTimeout = now + dur for _, v := range t.GetSeats() { p := v.(*game.Player).SubPlayer.(*Player) p.MillionSettle() } for _, v := range t.GetSeats() { p := v.(*game.Player).SubPlayer.(*Player) resp := &pb.CrashMsgGameSettleResp{ TimeLeft: dur, Result: t.Result, SettleAmount: p.FinalSettle, } p.Send(int(pb.GameProtocol_GameSettleResp), resp) } } // GetResult 返回开奖区域 func (t *Table) GetResult() (string, string) { res := fmt.Sprintf("%v", t.Result) return res, res } // MaxSeats 返回最大座位数 func (t *Table) MaxSeats() int { return game.MillionMaxSeat } func (t *Table) Destroy() { t.Debug("sub Destroy") } // StartFlyingTimer 火箭飞行计时器 func (t *Table) StartFlyingTimer(dur time.Duration) { t.Timer = fmt.Sprintf("flying_%v", t.TableId()) timewheel.GetTimeWheel().AddTimerCustom(dur, t.Timer, nil, func(arge interface{}) { t.Debug("flying timer callback") t.PutQueue("nf", t.Fly) }) } // Fly 火箭开始飞行 func (t *Table) Fly() { t.Debug("start flying") waterCon := call.GetConfigWaterReal(game.ThisGameID, t.Room.RoomId()) rtp := waterCon.Rtp if waterCon.Value > waterCon.WaterUp { rtp = waterCon.UpRtp } else if waterCon.Value < waterCon.WaterLower { rtp = waterCon.DownRtp } t.FlyTime = t.CalFlyingTime(rtp) t.StartFlyTime = time.Now().UnixMilli() t.Status = pb.GameStatus_GameStatusSpecial t.Timer = fmt.Sprintf("fly_%v", t.TableId()) // t.OperateTimeout = t.StartFlyTime dur := time.Duration(t.FlyTime) * time.Millisecond timewheel.GetTimeWheel().AddTimerCustom(dur, t.Timer, nil, func(arge interface{}) { t.Put("nf", func() { t.DelaySettle() }) }) t.Debug("flyTime:%v", t.FlyTime) t.Broadcast(int(pb.CrashProtocol_CrashFlyingStartResp), &pb.GameCommonResp{}) // 设定玩家自动退出 for _, v := range t.GetSeats() { p := v.(*game.Player).SubPlayer.(*Player) p.AutoCashoutOdd = p.SetAutoCashoutOdd if p.AutoCashoutOdd == 0 || p.TotalBet == 0 { continue } p.AutoCashoutTimer = fmt.Sprintf("autocashout%v", p.UID) timewheel.GetTimeWheel().AddTimerCustom(time.Duration(GetFlyTime(p.AutoCashoutOdd-100))*time.Millisecond, p.AutoCashoutTimer, nil, func(arge interface{}) { t.PutQueue("nf", func() { p.AutoCashOut() }) }) } } func (t *Table) CalFlyingTime(rtp int64) int { t.Debug("CalFlyingTime rtp:%v", rtp) var odd int64 = 100 origin := t.Ran.Int63n(MaxWeight) // 随机一个数 for i := int64(100); i <= MaxOdd; i++ { // 判断随机数落在哪个权重区间 total := rtp * MaxWeight / i / 100 // 由于rtp为万分位,i为扩大了一百倍的倍率,所以分母需要再除以100 if origin >= total { odd = i break } } odd -= 100 // 获取的倍数为赢的额外倍数 period := GetFlyTime(odd) t.Debug("period:%v,odd:%v", period, odd) if period <= 0 { return t.Ran.Intn(95) + 5 } return int(period) } // CalOdds 计算赔率 func (t *Table) CalOdds() (odds int64) { now := time.Now().UnixMilli() diff := now - t.StartFlyTime return GetOdds(diff) } // DelaySettle 判断是否延迟结算 func (t *Table) DelaySettle() { // 当前还未退出的真实玩家为0,延长飞行时间 // if t.CountRealPlayings() == 0 && t.FlyTime < MaxFlyTime { // // 延迟飞行不会飞到jackpot // mf := MaxFlyTime - t.FlyTime - 100 // if mf <= 0 { // t.Table.Settle() // return // } // if mf > 3000 { // mf = 3000 // } // t.FlyTime += t.Ran.Intn(mf) // now := time.Now().UnixMilli() // diff := int64(t.FlyTime) - (now - t.StartFlyTime) // if t.FlyTime > MaxFlyTime { // diff = int64(MaxFlyTime) - (now - t.StartFlyTime) // } // t.Debug("fly delay:%v,diff:%v", t.FlyTime, diff) // t.Timer = fmt.Sprintf("table%vdelaySettle", t.TableId()) // if diff <= 0 { // t.Table.Settle() // } else { // timewheel.GetTimeWheel().AddTimerCustom(time.Duration(diff)*time.Millisecond, t.Timer, nil, func(arge interface{}) { // t.Put("settle") // }) // } // return // } t.Table.Settle() }