You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
5.5 KiB
216 lines
5.5 KiB
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() |
|
}
|
|
|