1180 lines
39 KiB
Go
Raw Normal View History

2025-06-08 00:52:17 +08:00
package room
import (
"encoding/json"
"fmt"
"game/common/proto/pb"
"github.com/fox/fox/ipb"
"github.com/fox/fox/log"
"sort"
"sync"
"time"
)
func (rm *ColorRoom) SceneUserSitDown(user *model.User) {
_ = user
rm.SendOnlinePlayerNum()
}
// CheckAndBet 检查并下注
func (rm *ColorRoom) CheckAndBet(user *model.User, bets []*pb.ColorPinoyLiveBetReq) {
if len(bets) == 0 {
log.Error(rm.Log("玩家(%d) bets data err :%v ", bets))
model.SendBetFailMessage(model.DataErr, user)
return
}
betInfos := [config.BET_TYPE_NUM]int64{}
betCountInfos := [config.BET_TYPE_NUM]int64{}
totalBetAmount := int64(0)
oneBetMessage := &pb.ColorPinoyLiveS2CRepetBet{}
oneBetMessage.Uid = user.UserID
oneBetMessage.BetInfo = []*pb.ColorPinoyLiveBetSuccessMessage{}
if rm.GetGameStatus() != pb.ColorPinoyLiveGameStatus_ColorPinoyLiveBetStatus {
log.Error(rm.Log("玩家(%d) UndoBet data err GetGameStatus:%v,LastTimeBet:%v ", user.UserID, rm.GetGameStatus(), user.LastTimeBet))
model.SendBetFailMessage(model.StatusError, user)
return
}
for _, bet := range bets {
// 判断下注下标和下注区域下标是否超出列表
if _, ok := pb.ColorPinoyLiveBetTypeJP_name[int32(bet.BetType)]; !ok ||
bet.BetLevel < 0 || bet.BetLevel >= int32(len(rm.RoomCfg.ColorPinoyLiveConfig.BetList)) ||
bet.BetIndex < 0 || bet.BetIndex >= int32(len(rm.RoomCfg.ColorPinoyLiveConfig.BetList[bet.BetLevel])) {
log.Error(rm.Log("玩家(%d) bets data err BetLevel:%d BetIndex:%d ", bet.BetLevel, bet.BetIndex))
model.SendBetFailMessage(model.DataErr, user)
return
}
// 下注总金额
betAmountCount := rm.RoomCfg.ColorPinoyLiveConfig.BetList[bet.BetLevel][bet.BetIndex]
bet.BetAmount = betAmountCount
if betAmountCount > user.Balance-totalBetAmount {
log.Debug(rm.Log("用户余额为:%v 总押注%d 押注%d", user.Balance, totalBetAmount, betAmountCount))
model.SendBetFailMessage(model.ScoreLess, user)
return
} else {
totalBetAmount += betAmountCount
betInfos[bet.BetType%config.BET_TYPE_NUM] += betAmountCount
betCountInfos[bet.BetType%config.BET_TYPE_NUM] += 1
}
}
if totalBetAmount <= 0 || totalBetAmount+user.TotalBet > rm.RoomCfg.ColorPinoyLiveConfig.TotalBetLimit {
log.Error(rm.Log("DataErr totalBetAmount:%d err ", totalBetAmount))
model.SendBetFailMessage(model.PlayerEarTopScore, user)
return
}
log.Debug(rm.LogEx(user, "下注区域最大金额:%v", rm.Cfg.AreaBetLimit))
for i, num := range betInfos {
// 投注大于下注区域限制
if (user.TotalBets[i] + num) > rm.Cfg.AreaBetLimit {
// log.Debug("PlayerEarTopScore totalBetAmount:%d err ", totalBetAmount)
model.SendBetFailMessage(model.PlayerEarTopScore, user)
return
}
}
user.AddBalance(-totalBetAmount)
if user.LastTimeBet == nil {
user.LastTimeBet = make([][]*pb.ColorPinoyLiveBetReq, 0)
}
user.LastTimeBet = append(user.LastTimeBet, bets)
user.TotalBet += totalBetAmount
// log.Debug("上次下注:", user.LastTimeBet)
rm.MutexData.Lock()
for i, num := range betInfos {
if num > 0 {
user.TotalBets[i] += num
rm.TotalBets[i] += num
SendSuccessMessage := new(pb.ColorPinoyLiveBetSuccessMessage)
SendSuccessMessage.BetType = pb.ColorPinoyLiveBetTypeJP(i)
SendSuccessMessage.UserBet = num
SendSuccessMessage.UserBets = user.TotalBets[i] + num
SendSuccessMessage.TotalBets = rm.TotalBets[i] + num
oneBetMessage.BetInfo = append(oneBetMessage.BetInfo, SendSuccessMessage)
}
}
// 统计个区域投注次数
// user.TotalBetsCount = make([]int64, config.BET_TYPE_NUM)
for i, count := range betCountInfos {
if count > 0 {
user.TotalBetsCount[i] += count
}
}
user.AllBet += totalBetAmount
user.NoBetCount = 0
oneBetMessage.UserScore = user.Balance
// oneBetMessage.UserBets = user.TotalBets[:]
rm.TotalBet += totalBetAmount
rm.MutexData.Unlock()
rm.Table.Broadcast(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeGameSeatUserBet), oneBetMessage)
live.PushColorBet(&lws.CPLBet{
Uid: user.UserID,
Nickname: user.UserInetr.GetNike(),
Bet: totalBetAmount,
Avatar: user.UserInetr.GetHead(),
})
}
func (rm *ColorRoom) UndoBet(user *model.User, undoType pb.ColorPinoyLiveUndoType) {
betInfos := [config.BET_TYPE_NUM]int64{}
betCountInfos := [config.BET_TYPE_NUM]int64{}
totalBetAmount := int64(0)
undoBetMessage := &pb.S2CUndoBet{}
undoBetMessage.Uid = user.UserID
undoBetMessage.BetInfo = []*pb.ColorPinoyLiveBetSuccessMessage{}
undoBetMessage.UndoType = undoType
if rm.GetGameStatus() != pb.ColorPinoyLiveGameStatus_ColorPinoyLiveBetStatus {
log.Error(rm.Log("玩家(%d) UndoBet data err GetGameStatus:%v,LastTimeBet:%v ", user.UserID, rm.GetGameStatus(), user.LastTimeBet))
model.SendBetFailMessage(model.StatusError, user)
return
}
if len(user.LastTimeBet) == 0 {
log.Error(rm.Log("玩家(%d) LastTimeBet null err:%v ", user.UserID, user.LastTimeBet))
model.SendBetFailMessage(model.LastBetNull, user)
return
}
var bets []*pb.ColorPinoyLiveBetReq
if undoType == pb.ColorPinoyLiveUndoType_ColorPinoyLiveUndoOne {
bets = user.LastTimeBet[len(user.LastTimeBet)-1]
} else if undoType == pb.ColorPinoyLiveUndoType_ColorPinoyLiveUndoAll {
for _, bet := range user.LastTimeBet {
bets = append(bets, bet...)
}
} else {
log.Error(rm.Log("玩家(%d) undoType err %v,", user.UserID, undoType))
model.SendBetFailMessage(model.DataErr, user)
return
}
if len(bets) == 0 {
log.Error(rm.Log("玩家(%d) bets err %v,", user.UserID, bets))
model.SendBetFailMessage(model.LastBetNull, user)
return
}
for _, bet := range bets {
// 判断下注下标和下注区域下标是否超出列表
if _, ok := pb.ColorPinoyLiveBetTypeJP_name[int32(bet.BetType)]; !ok {
log.Error(rm.Log("玩家(%d) bet err %v,", bet))
model.SendBetFailMessage(model.DataErr, user)
return
}
totalBetAmount += bet.BetAmount
betInfos[bet.BetType%config.BET_TYPE_NUM] += bet.BetAmount
betCountInfos[bet.BetType%config.BET_TYPE_NUM] += 1
}
if totalBetAmount > 0 {
user.AddBalance(totalBetAmount)
}
if user.LastTimeBet != nil && len(user.LastTimeBet) > 0 {
if undoType == pb.ColorPinoyLiveUndoType_ColorPinoyLiveUndoOne {
user.LastTimeBet = user.LastTimeBet[:len(user.LastTimeBet)-1]
} else {
user.LastTimeBet = nil
}
}
rm.MutexData.Lock()
for i, num := range betInfos {
user.TotalBets[i] -= num
rm.TotalBets[i] -= num
}
// 统计个区域投注次数
for i, count := range betCountInfos {
if count > 0 {
user.TotalBetsCount[i] -= count
}
if user.TotalBetsCount[i] < 0 {
user.TotalBetsCount[i] = 0
}
}
rm.TotalBet -= totalBetAmount
user.TotalBet -= totalBetAmount
user.AllBet -= totalBetAmount
user.NoBetCount = 0
for i, num := range betInfos {
SendSuccessMessage := new(pb.ColorPinoyLiveBetSuccessMessage)
SendSuccessMessage.SeatId = int32(user.SceneChairId)
SendSuccessMessage.BetType = pb.ColorPinoyLiveBetTypeJP(i)
SendSuccessMessage.UserBet = num
SendSuccessMessage.UserBets = user.TotalBets[i]
SendSuccessMessage.TotalBets = rm.TotalBets[i]
undoBetMessage.BetInfo = append(undoBetMessage.BetInfo, SendSuccessMessage)
}
rm.MutexData.Unlock()
// 玩家当前分数
undoBetMessage.UserScore = user.Balance
// log.Debug("undoBetMessage %v", undoBetMessage)
rm.Table.Broadcast(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeUndoBet), undoBetMessage)
}
func (rm *ColorRoom) KickOutUser(u *model.User) {
// delete(rm.AllUserList, k)
rm.DeletePlayer(u.UserID)
if u.SceneChairId != 0 {
rm.OnUserStanUp(u)
}
role := "机器人"
// rm.DeleteExitUserFromOnlineUserListSlice(u)
if !u.IsRobot {
rm.Table.KickOut(u.UserInetr)
role = "玩家"
}
log.Debug(rm.Log("删除(%s(%d) 金额:%d 输赢:%d", role, u.UserID, u.Balance, u.Balance-u.UserInetr.GetScore()))
rm.SendOnlinePlayerNum()
}
func (rm *ColorRoom) TransInoutGameBet(user *model.User, bet int64) error {
if config.CHIPS_DEBUG {
user.Balance -= bet
return nil
}
user.Mn.Lock()
defer user.Mn.Unlock()
transferInOutResp, err := rm.Table.TransInoutGameCarryAdd(user.UserInetr, rm.Table.GetLevel(), bet, "")
if err != nil {
return err
}
user.Balance = transferInOutResp.Balance
user.Carry = transferInOutResp.Carry
user.UserInetr.SetPreserve(transferInOutResp.Preserve)
// time.Sleep(10 * time.Second)
return nil
}
func (rm *ColorRoom) TransInoutGameEnd(user *model.User, bet int64, amountWin int64, tax int64) (int64, error) {
if config.CHIPS_DEBUG || user.IsRobot {
user.Balance += amountWin
return amountWin, nil
}
transferInOutResp, err := rm.Table.TransInoutGameEnd(user.UserInetr, rm.Table.GetLevel(), bet+tax, amountWin+tax, "")
if err != nil {
return 0, err
}
user.Balance = transferInOutResp.GetBalance()
if transferInOutResp.GetRealTransfer() == 0 {
return 0, errors.New("error")
}
user.TransBet += bet
user.TransWin += amountWin
// time.Sleep(10 * time.Second)
return transferInOutResp.RealTransfer, nil
}
func (rm *ColorRoom) ResetUserBet(user *model.User) {
rm.MutexData.Lock()
for i, bet := range user.TotalBets {
rm.TotalBets[i] -= bet
// rm.BetNumber[i] -= user.BetNumber[i]
}
rm.TotalBet -= user.TotalBet
rm.MutexData.Unlock()
user.TotalBet = 0
user.TotalBets = [config.BET_TYPE_NUM]int64{}
// user.BetNumber = [config.BET_TYPE_NUM]int64{}
}
func (rm *ColorRoom) StartTransInoutBet() {
wg := new(sync.WaitGroup)
var failUser []*model.User
failMutx := &sync.Mutex{}
rm.Traverse(func(u *model.User) bool {
wg.Add(1)
go func(user *model.User) {
defer wg.Done()
user.Mn.Lock()
defer user.Mn.Unlock()
if user.TotalBet > 0 {
_, err := rm.TransInoutGameEnd(user, user.TotalBet, 0, 0)
if err != nil {
func() {
failMutx.Lock()
defer failMutx.Unlock()
failUser = append(failUser, user)
}()
}
}
}(u)
return true
})
wg.Wait()
// 异步扣款完成后,处理部分扣款失败回滚操作
if len(failUser) > 0 {
pbMsg := &pb.ColorPinoyLiveS2CBetEndFailResult{
Code: 1,
}
for _, user := range failUser {
rm.ResetUserBet(user)
player := &pb.ColorPinoyLiveS2CRepetBet{}
player.UserScore = user.Balance
player.Uid = user.UserID
var bets []*pb.ColorPinoyLiveBetReq
for _, bet := range user.LastTimeBet {
bets = append(bets, bet...)
}
for _, bet := range bets {
// 判断下注下标和下注区域下标是否超出列表
if _, ok := pb.ColorPinoyLiveBetTypeJP_name[int32(bet.BetType)]; !ok {
log.Error(rm.Log("玩家(%d) bet err %v,", bet))
model.SendBetFailMessage(model.DataErr, user)
return
}
SendSuccessMessage := new(pb.ColorPinoyLiveBetSuccessMessage)
SendSuccessMessage.BetIndex = bet.BetIndex
SendSuccessMessage.BetLevel = bet.BetLevel
SendSuccessMessage.BetType = bet.BetType
SendSuccessMessage.SeatId = int32(user.SceneChairId)
SendSuccessMessage.UserBet = bet.BetAmount
SendSuccessMessage.TotalBets = rm.TotalBets[bet.BetType]
player.BetInfo = append(player.BetInfo, SendSuccessMessage)
}
pbMsg.Players = append(pbMsg.Players, player)
}
// log.Debug("玩家停止下注后 扣钱失败: %v", pbMsg)
rm.Table.Broadcast(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticePlayerBetEndResultFailed), pbMsg)
}
// 大客投注
var allWinner []*pb.ColorPinoyLiveBigWinner
rm.Traverse(func(user *model.User) bool {
if user.TotalBet > 0 {
allWinner = append(allWinner, &pb.ColorPinoyLiveBigWinner{NickName: user.UserInetr.GetNike(), Avatar: user.UserInetr.GetHead(), WinChips: user.TotalBet, AreaId: user.TotalBets[:]})
}
return true
})
rm.updateBigWinner(allWinner)
bigMsg := &pb.ColorPinoyLivePlayerBigWinner{BigBet: allWinner, Jackpot: rm.jackpotMgr.GetJackpot()}
rm.Table.Broadcast(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeGameBigWinner), bigMsg)
rm.TimerJob, _ = rm.Table.AddTimer(time.Duration(rm.RoomCfg.TimeConf.Endmove), func() {
rm.NotifyBigBetAreaMul()
})
allUserTotalBet := int64(0) // 所有玩家投注未中奖的总金额用于计算jackpot池
rm.Traverse(func(user *model.User) bool {
if user.TotalBet < 1 {
return true
}
allUserTotalBet += user.TotalBet
return true
})
log.Debug(rm.Log("本局总投注金额为:%v 赎回比例:%v 追加比例:%v 满额追加比例:%v", allUserTotalBet, rm.Cfg.JpXRate, rm.Cfg.JpYRate, rm.Cfg.JpXYRate))
rm.jackpotX, rm.jackpotY = rm.jackpotMgr.AddJp(allUserTotalBet, int64(rm.Cfg.JpXRate), int64(rm.Cfg.JpYRate), int64(rm.Cfg.JpXYRate))
if rm.jackpotX > 0 || rm.jackpotY > 0 {
rm.kafkaJackpotUserRepaid(rm.jackpotX, rm.jackpotY)
}
}
// 计算 下注区域中奖得分返回是否有jp奖jp奖位置中奖人数
func (rm *ColorRoom) CalculateJackpotScore() (pb.ColorPinoyLiveBetTypeJP, map[int64]int64) {
jackpotArea := pb.ColorPinoyLiveBetTypeJP(-1)
for _, winArea := range rm.PokerMsg.WinBetArea {
if !winArea.IsJackpot || !winArea.IsWin {
continue
}
color := getColorByBetArea(winArea.BetArea)
colorCount := getColorCount(rm.NormalDices, color)
if colorCount != 3 {
continue
}
jackpotArea = winArea.BetArea
rm.Traverse(func(user *model.User) bool {
if user.TotalBets[winArea.BetArea] <= 0 {
return true
}
rm.jackpotMgr.AddJpUser(user.UserID, user.TotalBets[winArea.BetArea])
return true
})
}
rm.jackpotUser, rm.costJackpot = rm.jackpotMgr.WinJackpot()
if rm.costJackpot > 0 {
rm.kafkaHitJackpot(rm.costJackpot, rm.jackpotUser)
}
log.Debug(rm.Log("本局是否中jackpot奖:%v, 玩家一起分走jackpot:%v, 当前jackpot值:%v", rm.costJackpot > 0, rm.costJackpot, rm.jackpotMgr.GetJackpot()))
return jackpotArea, rm.jackpotUser
}
// 计算 所有玩家的下注区域中奖得分
func (rm *ColorRoom) CalculateAllUserScore() {
// 赢钱会清空jackpot池
jpArea, userJackPot := rm.CalculateJackpotScore()
var jackpotUserName []string
rm.Traverse(func(user *model.User) bool {
msg := new(pb.ColorPinoyLiveUserSettleMsg)
msg.WinAreaOdd = rm.PokerMsg.WinBetArea
msg.UserBets = rm.CopyArr(user.TotalBets)
msg.UserRealWins = make([]int64, config.BET_TYPE_NUM)
msg.UserWins = make([]int64, config.BET_TYPE_NUM)
if user.TotalBet > 0 {
// 算分
jpScore := userJackPot[user.UserID]
rm.CalculateScore(user, jpArea, jpScore, msg)
if jpScore > 0 {
jackpotUserName = append(jackpotUserName, user.UserInetr.GetNike())
rm.BroadHitJackpot(user, jpScore)
}
}
// 统计玩家信息
if msg.TotalWin > user.TotalBet {
user.UserCount(true, msg.TotalWin)
} else {
user.UserCount(false, 0)
}
user.Balance += msg.TotalWin
msg.UserScore = user.Balance
user.SettleMsg = msg
return true
})
rm.Traverse(func(user *model.User) bool {
user.SettleMsg.JackpotUserName = jackpotUserName
return true
})
}
// 计算 下注区域中奖得分
func (rm *ColorRoom) CalculateScore(user *model.User, jpArea pb.ColorPinoyLiveBetTypeJP, jpScore int64, msg *pb.ColorPinoyLiveUserSettleMsg) {
for _, winArea := range msg.WinAreaOdd {
if msg.UserBets[winArea.BetArea] <= 0 {
continue
}
if jpArea != winArea.BetArea {
odds := winArea.Odd
// 奖金计算公式 Payouts =( Odds * Bet ) * ( 1 + Bonus) + Bet odds 是倍率 Bonus是猜中幸运骰子 的加成
// 本区域赢未扣税 倍率是百分值所以计算时要除以100
win2 := (odds * msg.UserBets[winArea.BetArea]) / 100
// 本区域赢扣税
Gold := win2 * (100 - rm.RoomCfg.Rate) / 100
// 算税()
msg.Tax += win2 - Gold
// 加回投注本金
Gold += msg.UserBets[winArea.BetArea]
msg.TotalWin += Gold
// 统计赢区的下注总额
msg.TotalWinBaseBet += msg.UserBets[winArea.BetArea]
msg.UserWins[winArea.BetArea] += win2
msg.UserRealWins[winArea.BetArea] += Gold
log.Debug(rm.LogEx(user, "算分 odds:%v 投注区:%v win2:%v Gold:%v", odds, winArea.BetArea, win2, Gold))
} else {
win2 := jpScore
// 本区域赢扣税
Gold := jpScore * (100 - rm.RoomCfg.Rate) / 100
// 算税()
msg.Tax += win2 - Gold
// 加回投注本金
Gold += msg.UserBets[winArea.BetArea]
msg.TotalWin += Gold
// 统计赢区的下注总额
msg.TotalWinBaseBet += msg.UserBets[winArea.BetArea]
msg.UserWins[winArea.BetArea] += win2
msg.UserRealWins[winArea.BetArea] += Gold
msg.JackpotWin = Gold
log.Debug(rm.LogEx(user, "算分 jackpot 投注区:%v win2:%v Gold:%v", winArea.BetArea, win2, Gold))
}
}
}
type areaWin struct {
areaId int64
win int64
}
// 更新大赢家
func (rm *ColorRoom) updateBigWinner(allWinner []*pb.ColorPinoyLiveBigWinner) {
// log.Debug(fmt.Sprintf("allWinner:%+v", allWinner))
rm.BigWinner = rm.BigWinner[:0]
sort.Slice(allWinner, func(i, j int) bool {
return allWinner[i].WinChips > allWinner[j].WinChips
})
if len(allWinner) > BigWinnerCount {
allWinner = allWinner[:BigWinnerCount]
}
for _, winner := range allWinner {
var areaWins []*areaWin
for areaId, win := range winner.AreaId {
if win > 0 {
areaWins = append(areaWins, &areaWin{areaId: int64(areaId), win: win})
}
}
sort.Slice(areaWins, func(i, j int) bool {
return areaWins[i].win > areaWins[j].win
})
if len(areaWins) > BigWinnerCount {
areaWins = areaWins[:BigWinnerCount]
}
winner.AreaId = make([]int64, 0, BigWinnerCount)
for _, area := range areaWins {
winner.AreaId = append(winner.AreaId, area.areaId)
}
}
rm.BigWinner = allWinner
}
// 和平台做结算
func (rm *ColorRoom) SetUserSettleMsg() {
var allWinner []*pb.ColorPinoyLiveBigWinner
rm.CalculateAllUserScore()
wg := new(sync.WaitGroup)
rm.Traverse(func(uu *model.User) bool {
wg.Add(1)
go func(u *model.User) {
defer wg.Done()
if u.TotalBet > 0 {
// 和平台做赢钱结算
// if msg.TotalWin > 0 {
_, err := rm.TransInoutGameEnd(u, 0, u.SettleMsg.TotalWin, u.SettleMsg.Tax)
if err != nil {
log.Error(rm.Log(err.Error()))
// model.SendBetFailMessage(model.BalanceError, u)
}
// }
}
}(uu)
return true
})
wg.Wait()
// 异步加钱完成后再执行后续的结算操作
rm.Traverse(func(u *model.User) bool {
msg := u.SettleMsg
if msg == nil || msg.TotalWin < 1 {
return true
}
winner := &pb.ColorPinoyLiveBigWinner{
NickName: u.UserInetr.GetNike(),
Avatar: u.UserInetr.GetHead(),
WinChips: msg.TotalWin,
AreaId: msg.UserRealWins,
}
allWinner = append(allWinner, winner)
log.Debug(rm.LogEx(u, "赢钱:%v", winner.WinChips))
return true
})
rm.updateBigWinner(allWinner)
rm.SetGameTrend()
rm.sendSettleMsg2Client()
// log.Debug(time.Now().Unix() - rm.endAt)
rm.Table.EndGame()
rm.NotifyLiveDelayUpdate() // 通知延迟更新服务器配置,切换维护状态
rm.TimerJob, _ = rm.Table.AddTimer(time.Duration(rm.RoomCfg.TimeConf.Endpay), func() {
rm.Rank()
})
}
func (rm *ColorRoom) CountUser(u *model.User) {
u.Icon = 0
// rm.OnlineUserList = append(rm.OnlineUserList, u)
}
func (rm *ColorRoom) ResetData(all bool) {
rm.TotalBets = [config.BET_TYPE_NUM]int64{}
rm.TotalBet = 0
rm.LuckyDice = 0
rm.NormalDices = make([]byte, 3)
rm.StartDices = make([]byte, 3)
rm.ResultImgs = make([]string, 0)
rm.InitBigOddsBetAreas()
if all {
rm.LiveMgr.Reset()
rm.Traverse(func(u *model.User) bool {
u.ResetUserData()
u.RetrunGold = 0
return true
})
}
}
func (rm *ColorRoom) GetPairDice(count int, startIndex int, endIndex int) []byte {
if gconfig.GConfig.IsProd() {
return nil
}
// PokerCard 表示一张扑克牌
type Dice struct {
Color int // 花色
Point int // 点数
}
type PairDice struct {
Cards []Dice
}
key := fmt.Sprintf("preset-cards:0:color:%d", rm.Table.GetId())
log.Debug(rm.Log("获取配牌配置 key:", key))
str := redisf.RSC.GetPairCard(key)
if str == "" {
return nil
}
pairCard := new(PairDice)
err := json.Unmarshal([]byte(str), pairCard)
if err != nil {
log.Debug(rm.Log("getPairCard:%v", err))
return nil
}
if len(pairCard.Cards) < 2 {
log.Error(rm.Log("getPairCard ", pairCard))
return nil
}
log.Debug(rm.Log("getPairCard pairCard:%v", pairCard))
var res []byte
for index, card := range pairCard.Cards {
if index >= startIndex && index < endIndex {
res = append(res, byte(card.Point))
if (len(res)) == count {
break
}
}
}
return res
}
func (rm *ColorRoom) GetGameTrend() (luckyRates []int32) {
// var mapLuckyRate = map[pb.ColorPinoyLiveDiceColorType]int32{}
// for _, trend := range rm.GameTrend.ListTrendGroup {
// mapLuckyRate[trend.LuckyDice]++
// }
// for i := pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_YELLOW; i <= pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_GREEN; i++ {
// luckyRates = append(luckyRates, 0)
// }
// if len(mapLuckyRate) > 0 {
// for k, v := range mapLuckyRate {
// // log.Debug(fmt.Sprintf("颜色:%v 数量:%v 总数量:%v 配置:%v", k, v, len(rm.GameTrend.ListTrendGroup), config.WinTrendNum))
// if int(k-1) < len(luckyRates) {
// luckyRates[k-1] = v * 10000 / int32(len(rm.GameTrend.ListTrendGroup))
// }
// }
// }
return luckyRates
}
func (rm *ColorRoom) SetGameTrend() {
trendGroup := new(pb.ColorPinoyLiveTrendGroup)
trendGroup.LuckyDice = pb.ColorPinoyLiveDiceColorType(model.GetColor(rm.LuckyDice))
for _, dice := range rm.NormalDices {
trendGroup.ThreeDice = append(trendGroup.ThreeDice, pb.ColorPinoyLiveDiceColorType(model.GetColor(dice)))
}
rm.GameTrend.ListTrendGroup = append(rm.GameTrend.ListTrendGroup, trendGroup)
// log.Debug("走势图 rm.GameTrend.ListTrendGroup: ", rm.GameTrend.ListTrendGroup)
winlen := len(rm.GameTrend.ListTrendGroup)
if winlen > config.WinTrendNum {
rm.GameTrend.ListTrendGroup = rm.GameTrend.ListTrendGroup[(winlen - config.WinTrendNum):]
}
if rm.ServerStatus == define.GameStatusNoraml {
str, err := json.Marshal(rm.GameTrend.ListTrendGroup)
if err != nil {
return
}
redisf.RSC.SetColorGameTrend(rm.TrendRedisKey, str)
// log.Debug("SetGameTrend 保存走势图到redis :", str)
}
}
// 获取投注区域的颜色
func getColorByBetArea(area pb.ColorPinoyLiveBetTypeJP) pb.ColorPinoyLiveDiceColorType {
switch area {
case pb.ColorPinoyLiveBetTypeJP_CLJ_Yellow, pb.ColorPinoyLiveBetTypeJP_CLJ_Double_Yellow, pb.ColorPinoyLiveBetTypeJP_CLJ_Three_Yellow:
return pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_YELLOW
case pb.ColorPinoyLiveBetTypeJP_CLJ_White, pb.ColorPinoyLiveBetTypeJP_CLJ_Double_White, pb.ColorPinoyLiveBetTypeJP_CLJ_Three_White:
return pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_WHITE
case pb.ColorPinoyLiveBetTypeJP_CLJ_Pink, pb.ColorPinoyLiveBetTypeJP_CLJ_Double_Pink, pb.ColorPinoyLiveBetTypeJP_CLJ_Three_Pink:
return pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_PINK
case pb.ColorPinoyLiveBetTypeJP_CLJ_Blue, pb.ColorPinoyLiveBetTypeJP_CLJ_Double_Blue, pb.ColorPinoyLiveBetTypeJP_CLJ_Three_Blue:
return pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_BLUE
case pb.ColorPinoyLiveBetTypeJP_CLJ_Red, pb.ColorPinoyLiveBetTypeJP_CLJ_Double_Red, pb.ColorPinoyLiveBetTypeJP_CLJ_Three_Red:
return pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_RED
case pb.ColorPinoyLiveBetTypeJP_CLJ_Green, pb.ColorPinoyLiveBetTypeJP_CLJ_Double_Green, pb.ColorPinoyLiveBetTypeJP_CLJ_Three_Green:
return pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_GREEN
}
return pb.ColorPinoyLiveDiceColorType_ColorPinoyLiveType_Void
}
func getColorCount(result []byte, color pb.ColorPinoyLiveDiceColorType) int {
count := 0
for _, c := range result {
if model.GetColor(c) == int32(color) {
count++
}
}
return count
}
func stringDices(result []byte) string {
s := ""
for _, c := range result {
s += fmt.Sprintf("%v", pb.ColorPinoyLiveDiceColorType(model.GetColor(c)))
}
return s
}
// 检查投掷结果是否匹配某个下注区域
func isWinningArea(result []byte, area pb.ColorPinoyLiveBetTypeJP) (win bool, bigPos pb.ColorPinoyLiveBigBetAreaPos, colorCount int) {
color := getColorByBetArea(area)
colorCount = getColorCount(result, color)
if colorCount == 0 {
return false, 0, colorCount
}
// 单色投注区,查看开出几个该颜色
if area < pb.ColorPinoyLiveBetTypeJP_CLJ_Double_Yellow {
if colorCount == 1 {
return true, pb.ColorPinoyLiveBigBetAreaPos_BBA_Single_0, colorCount
} else if colorCount == 2 {
return true, pb.ColorPinoyLiveBigBetAreaPos_BBA_Single_1, colorCount
} else {
return true, pb.ColorPinoyLiveBigBetAreaPos_BBA_Single_2, colorCount
}
} else if area < pb.ColorPinoyLiveBetTypeJP_CLJ_Three_Yellow {
if colorCount > 1 {
return true, pb.ColorPinoyLiveBigBetAreaPos_BBA_Double, colorCount
}
} else {
if colorCount > 2 {
return true, pb.ColorPinoyLiveBigBetAreaPos_BBA_Three, colorCount
}
}
return false, 0, colorCount
}
// 计算开奖结果
func (rm *ColorRoom) CompareDiceResult() {
var wins []*pb.ColorPinoyLiveBetAreaOdd
// // 存储中奖区域
result := rm.NormalDices
log.Debug(rm.Log("开奖结果:%v", stringDices(result)))
rm.afterBetAreaOdds = rm.afterBetAreaOdds[0:0]
// 检查所有下注区域是否中奖
for pos, area := range rm.betEndBetAreasOdds {
betAreaOdd := &pb.ColorPinoyLiveBetAreaOdd{
BetArea: area.BetType,
Odd: area.Odd[0],
ViewOdd: 0,
IsBigOdd: area.IsBigOdd,
BigSingleColorOddPos: area.BigSingleColorOddPos,
IsWin: false,
IsJackpot: area.IsJackpot,
}
if pos/6 == 0 {
// 第一行投注区域,赔率是多个赔率中的一个
betAreaOdd.Odd = area.Odd[area.BigSingleColorOddPos]
} else {
betAreaOdd.Odd = area.Odd[0]
}
betAreaOdd.ViewOdd = betAreaOdd.Odd
// 更新实际赔率
isWin, winOddPos, colorCount := isWinningArea(result, area.BetType)
betAreaOdd.IsWin = isWin
if betAreaOdd.IsWin {
if betAreaOdd.IsJackpot && colorCount == 3 {
betAreaOdd.Odd = 0
} else {
if winOddPos == pb.ColorPinoyLiveBigBetAreaPos_BBA_Single_0 {
betAreaOdd.Odd = area.Odd[0]
} else if winOddPos == pb.ColorPinoyLiveBigBetAreaPos_BBA_Single_1 {
betAreaOdd.Odd = area.Odd[1]
} else if winOddPos == pb.ColorPinoyLiveBigBetAreaPos_BBA_Single_2 {
betAreaOdd.Odd = area.Odd[2]
}
// 爆奖需要修正
if betAreaOdd.IsBigOdd && winOddPos > betAreaOdd.BigSingleColorOddPos {
betAreaOdd.Odd = area.Odd[area.BigSingleColorOddPos]
}
}
wins = append(wins, betAreaOdd)
}
// 修正牌局记录倍率
tmpAreaOdd := &pb.ColorPinoyLiveBetAreaOdd{
BetArea: betAreaOdd.BetArea,
Odd: betAreaOdd.Odd,
ViewOdd: betAreaOdd.ViewOdd,
IsBigOdd: betAreaOdd.IsBigOdd,
BigSingleColorOddPos: betAreaOdd.BigSingleColorOddPos,
IsWin: betAreaOdd.IsWin,
IsJackpot: betAreaOdd.IsJackpot,
}
if !tmpAreaOdd.IsWin && pos/6 == 0 &&
(betAreaOdd.BigSingleColorOddPos == pb.ColorPinoyLiveBigBetAreaPos_BBA_Single_1 ||
betAreaOdd.BigSingleColorOddPos == pb.ColorPinoyLiveBigBetAreaPos_BBA_Single_2) {
tmpAreaOdd.Odd = area.Odd[0]
if !tmpAreaOdd.IsBigOdd {
tmpAreaOdd.ViewOdd = tmpAreaOdd.Odd
}
}
if !tmpAreaOdd.IsWin && pos/6 == 1 && tmpAreaOdd.IsBigOdd {
tmpAreaOdd.Odd = rm.RoomCfg.ColorPinoyLiveConfig.WinDoubleColorMul[0].Mul
}
if !tmpAreaOdd.IsWin && pos/6 == 2 && tmpAreaOdd.IsBigOdd {
tmpAreaOdd.Odd = rm.RoomCfg.ColorPinoyLiveConfig.WinThreeColorMul[0].Mul
}
rm.afterBetAreaOdds = append(rm.afterBetAreaOdds, tmpAreaOdd)
log.Debug(rm.Log("开奖,区域:%v 是否中奖:%v 实际赔率:%v 显示赔率:%v 是否爆奖:%v 爆奖位置:%v", betAreaOdd.BetArea, betAreaOdd.IsWin, betAreaOdd.Odd,
betAreaOdd.ViewOdd, betAreaOdd.IsBigOdd, betAreaOdd.BigSingleColorOddPos))
}
rm.PokerMsg.WinBetArea = wins
}
// 检查用户是否被踢掉
func (rm *ColorRoom) checkUserBet() {
kickMsg, isKick := redisf.RSC.IsGameMaintenance(gconfig.GConfig.GRoomConfig.ChannelId, gconfig.GConfig.GServConfig.GameId)
rm.Traverse(func(u *model.User) bool {
u.NoBetCount++
if isKick {
msg := new(pb.ColorPinoyLiveKickOutUserMsg)
// msg.KickOutReason = fmt.Sprintf("you did not bet %d games", rm.RoomCfg.LongHuConfig.NoBetCountMax)
msg.Reason = int32(pb.ColorPinoyLiveLeaveReason_ColorPinoyLiveLeaveReason_Maintaince)
msg.KickOutReason = kickMsg
u.SendMsg(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeKickOutUser), msg)
u.NoBetCount = 0
rm.KickOutUser(u)
return true
}
if rm.ServerStatus != define.GameStatusNoraml || u.UserInetr.NeedKickout() {
msg := new(pb.ColorPinoyLiveKickOutUserMsg)
// msg.KickOutReason = fmt.Sprintf("game server maintenance ")
msg.Reason = int32(pb.ColorPinoyLiveLeaveReason_ColorPinoyLiveLeaveReason_PLAYER_QUIT_ROOM)
u.SendMsg(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeKickOutUser), msg)
rm.KickOutUser(u)
return true
}
if redisf.RSC.IsUserLiveBan(u.UserInetr.GetOpToken(), int64(gconfig.GConfig.GRoomConfig.GameId), u.UserID) {
msg := new(pb.ColorPinoyLiveKickOutUserMsg)
msg.Reason = int32(pb.ColorPinoyLiveLeaveReason_ColorPinoyLiveLeaveReason_Ban)
u.SendMsg(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeKickOutUser), msg)
rm.KickOutUser(u)
return true
}
// if u.NoBetCount >= (rm.RoomCfg.ColorPinoyLiveConfig.NoBetCountMax + 1) {
// msg := new(pb.ColorPinoyLiveKickOutUserMsg)
// // msg.KickOutReason = fmt.Sprintf("you did not bet %d games", rm.RoomCfg.LongHuConfig.NoBetCountMax)
// msg.Reason = 1
// u.SendMsg(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeKickOutUser), msg)
// // 踢掉用户
// u.NoBetCount = 0
// rm.KickOutUser(u)
// return true
// }
return true
})
}
// 初始走势图
func (rm *ColorRoom) InitWinTrend() {
rm.TrendRedisKey = fmt.Sprintf("pb.:%d:%d:trend", gconfig.GConfig.GDataConfig.VersionMode, rm.RoomCfg.Level)
if rm.ServerStatus == define.GameStatusNoraml {
winTrend := redisf.RSC.GetColorGameTrend(rm.TrendRedisKey)
if winTrend != "" {
rm.GameTrend = new(pb.ColorPinoyLiveTrend)
rm.GameTrend.ListTrendGroup = []*pb.ColorPinoyLiveTrendGroup{}
err := json.Unmarshal([]byte(winTrend), &rm.GameTrend.ListTrendGroup)
winlen := len(rm.GameTrend.ListTrendGroup)
// log.Debug("初始化走势图1:", len(rm.GameTrend.ListTrendGroup))
if winlen > config.WinTrendNum {
rm.GameTrend.ListTrendGroup = rm.GameTrend.ListTrendGroup[(winlen - config.WinTrendNum):]
// log.Debug("初始化走势图2:", len(rm.GameTrend.ListTrendGroup))
}
// log.Debug("初始化走势图:", rm.GameTrend.ListTrendGroup)
if err != nil {
log.Error(rm.Log("初始化走势图:%v", err))
}
}
}
}
func (rm *ColorRoom) DeleteExitUserFromOnlineUserListSlice(user *model.User) {
rm.MutexUserList.Lock()
defer rm.MutexUserList.Unlock()
for k, v := range rm.OnlineUserList {
if user == v {
rm.OnlineUserList = append(rm.OnlineUserList[:k], rm.OnlineUserList[k+1:]...)
break
}
}
}
func (rm *ColorRoom) SelectUserListBalanceTopSitDownChair() {
rm.MutexUserList.Lock()
rm.SceneInfo.ClearSceneChairId()
rm.SceneInfo.Init()
index := len(rm.OnlineUserList)
if index >= config.SEAT_NUM {
index = config.SEAT_NUM
}
cou := model.Usercount{}
cou = rm.OnlineUserList
sort.Sort(cou)
for i := 0; i < index; i++ {
u := rm.OnlineUserList[i]
ChairId := i + 1
if rm.SceneInfo.SitScene(u, ChairId) {
u.SceneChairId = ChairId
}
}
rm.MutexUserList.Unlock()
}
func (rm *ColorRoom) CopyArr(arr [config.BET_TYPE_NUM]int64) []int64 {
slice := make([]int64, len(arr))
copy(slice, arr[:])
return slice
}
func (rm *ColorRoom) GameDiscard() {
rm.TimerJob.Cancel()
rm.GameUserDiscard()
// rm.TimerJob, _ = rm.Table.AddTimer(1000, func() {
// rm.LiveCnt(rm.Ready, false, true, []bool{true}...)
// })
rm.ResetData(false)
rm.Traverse(func(user *model.User) bool {
if rm.LiveMgr.MaintenanceStatus == 1 {
rm.sendUserMainte(user, int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeGameMainte))
}
if rm.LiveMgr.DiscardStatus == 1 {
rm.sendUserMainte(user, int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeDiscard))
}
return true
})
rm.Ready()
}
func (rm *ColorRoom) sendUserMainte(user *model.User, cmd int32) {
userinfo := new(pb.ColorPinoyLiveUserInfo)
userinfo.NikeName = user.UserInetr.GetNike()
userinfo.UserGlod = user.Balance
userinfo.Head = user.UserInetr.GetHead()
userinfo.UserID = user.UserID
_ = user.UserInetr.SendMsg(cmd, &pb.ColorPinoyLiveMainteNtf{
UserInfo: userinfo,
MaintMsg: rm.LiveMgr.MainteMsg,
ReturnGold: user.RetrunGold,
})
}
func (rm *ColorRoom) GameUserDiscard() {
rm.MutexStatus.RLock()
defer rm.MutexStatus.RUnlock()
log.Debug(rm.Log("流局,状态:%v,分出去的jackpot:%v", rm.GetGameStatus(), rm.costJackpot))
// 回退
if rm.GetGameStatus() >= pb.ColorPinoyLiveGameStatus_ColorPinoyLiveEndBetMovie && rm.GetGameStatus() < pb.ColorPinoyLiveGameStatus_ColorPinoyLiveSettleStatus {
rm.jackpotMgr.RollBackJpXAndJpY(0, 0, rm.jackpotX, rm.jackpotY)
rm.kafkaBackJackpot(0, rm.jackpotX, rm.jackpotY, rm.jackpotUser)
} else if rm.GetGameStatus() >= pb.ColorPinoyLiveGameStatus_ColorPinoyLiveSettleStatus {
rm.jackpotMgr.RollBackJpXAndJpY(rm.costJackpot, rm.jackpotFunding, rm.jackpotX, rm.jackpotY)
rm.kafkaBackJackpot(rm.costJackpot, rm.jackpotX, rm.jackpotY, rm.jackpotUser)
}
var betCount int64
GameTotalBets := make([]int64, config.BET_TYPE_NUM)
var PlayerData []*pb.ColorPinoyLivePlayerData
copyBetAreaMul := rm.copyBetAreaOdds()
wg := new(sync.WaitGroup)
playerDataMu := new(sync.Mutex)
rm.Traverse(func(v *model.User) bool {
wg.Add(1)
monitor.GoSafe(func(u *model.User) {
defer wg.Done()
u.RetrunGold = u.TotalBet
msg := new(pb.ColorPinoyLiveUserSettleMsg)
msg.UserBets = rm.CopyArr(u.TotalBets)
msg.UserRealWins = make([]int64, config.BET_TYPE_NUM)
msg.UserWins = make([]int64, config.BET_TYPE_NUM)
msg.WinAreaOdd = rm.PokerMsg.WinBetArea
msg.UserScore = u.Balance
u.SettleMsg = msg
// 写入数据库统计信息
if u.TotalBet > 0 {
for i, bet := range u.TotalBets {
betCount += bet
GameTotalBets[i] += bet
}
// 玩家下注区域统计
u.SettleMsg.UserBetsCount = make([]int64, config.BET_TYPE_NUM)
for i, count := range u.TotalBetsCount {
u.SettleMsg.UserBetsCount[i] = count
}
if rm.GetGameStatus() < pb.ColorPinoyLiveGameStatus_ColorPinoyLiveEndBetMovie {
u.AddBalance(u.TotalBet)
} else if rm.GetGameStatus() < pb.ColorPinoyLiveGameStatus_ColorPinoyLiveSettleStatus {
_, err := rm.TransInoutGameEnd(u, u.TransWin, u.TransBet, 0)
if err != nil {
log.Error(rm.Log("discard error:%v, game_no:%s, uid:%d, TransWin:%d, TransBet:%d", err, rm.Table.GetGameRoundId(), u.UserID, u.TransWin, u.TransBet))
}
} else {
if rm.LiveMgr.DiscardStatus == 1 {
_, err := rm.TransInoutGameEnd(u, u.TransWin, u.TransBet, 0)
if err != nil {
log.Error(rm.Log("discard error:%v, game_no:%s, uid:%d, TransWin:%d, TransBet:%d", err, rm.Table.GetGameRoundId(), u.UserID, u.TransWin, u.TransBet))
}
} else {
return
}
}
func() {
playerDataMu.Lock()
defer playerDataMu.Unlock()
PlayerData = append(PlayerData, &pb.ColorPinoyLivePlayerData{
Uid: u.UserID,
TotalBets: u.SettleMsg.UserBets, // 玩家各个区域的总下注额
TotalBet: u.TotalBet,
Profit: u.SettleMsg.TotalWin,
Tax: u.SettleMsg.Tax,
Balance: u.Balance,
PreBalance: u.PreBalance,
UserWins: u.SettleMsg.UserWins, // 玩家赢取的下注区域总下注额
UserRealWins: u.SettleMsg.UserRealWins, // 玩家赢取的下注区域总下注额 扣税后
AreaOdds: copyBetAreaMul, // 投注区域倍率
StartTime: u.StartAt,
TransBet: u.TransBet,
TransWin: u.TransWin,
DevMode: u.UserInetr.GetDevMode(),
UserBetsCount: u.SettleMsg.UserBetsCount,
IsDiscard: 1,
})
}()
}
u.ResetUserData()
}, v)
return true
})
wg.Wait()
// 发布事件
if PlayerData == nil || len(PlayerData) == 0 {
return
}
// 开奖结果
gameDetail := &pb.ColorPinoyLiveDetail{DealerName: rm.dealerName, ResultImg: rm.ResultImgs}
gameDetail.BetAreaMul = copyBetAreaMul
gameRecordData := &pb.ColorPinoyLiveEnd{
GameNo: fmt.Sprintf("%d|%d|%d", gconfig.GConfig.GRoomConfig.GameId, rm.Table.GetId(), time.Now().UnixMilli()),
StartTime: rm.startAt,
EndTime: rm.endAt,
Level: gconfig.GConfig.GRoomConfig.Level,
BaseBet: rm.RoomCfg.BaseBet,
PlayerData: PlayerData,
TaxRate: rm.RoomCfg.Rate,
TotalBet: betCount,
TotalBets: GameTotalBets[:],
OpToken: gconfig.GConfig.GServConfig.ChannelId,
Detail: gameDetail,
IsDiscard: 1,
}
log.Debug("GameUserDiscard")
go func() {
err := gconfig.Produce(context.Background(), define.TopicColoLiveGameGameEnd, gameRecordData)
if err != nil {
log.Error(rm.Log("[%s] fail to Produce TongitsGameEndEvent(%+v), err: %v", gameRecordData.GameNo, gameRecordData, err))
}
}()
}
func (rm *ColorRoom) LoadDealerNames() {
ssv := redisf.RSC.DealerNameGet(gconfig.GConfig.GDataConfig.VersionMode, gconfig.GConfig.GRoomConfig.GameId, GameName)
var dealerNames []string
_ = json.Unmarshal([]byte(ssv), &dealerNames)
rm.dealerName = dealerNames
log.Debug(rm.Log("dealerNames:%v", rm.dealerName))
}
// 发送垫资kafka
func (rm *ColorRoom) kafkaJackpotFunding(funding int64) {
msg := &events.JackpotEvent{
EventType: events.JackpotEvent_et_funding,
GameId: rm.RoomCfg.GameId,
Time: time.Now().UnixMilli(),
Funding: &events.JackpotEvent_Funding{Funding: funding},
GameNo: rm.Table.GetGameRoundId(),
}
go func() {
err := gconfig.Produce(context.Background(), define.TopicJackpot, msg)
if err != nil {
log.Error(rm.Log("kafka JackpotEvent_et_funding err: %v", err))
}
}()
log.Debug(rm.Log("kafka 垫资:%v", funding))
}
// 发送赎回及追加kafka
func (rm *ColorRoom) kafkaJackpotUserRepaid(jpx, jpy int64) {
msg := &events.JackpotEvent{
EventType: events.JackpotEvent_et_user_repaid,
GameId: rm.RoomCfg.GameId,
Time: time.Now().UnixMilli(),
UserRepaid: &events.JackpotEvent_UserRepaid{JackpotX: jpx, JackpotY: jpy},
GameNo: rm.Table.GetGameRoundId(),
}
go func() {
err := gconfig.Produce(context.Background(), define.TopicJackpot, msg)
if err != nil {
log.Error(rm.Log("kafka JackpotEvent_et_user_repaid err: %v", err))
}
}()
log.Debug(rm.Log("kafka 赎回jpx:%v 追加jpy:%v", jpx, jpy))
}
// 中jackpot分奖
func (rm *ColorRoom) kafkaHitJackpot(jackpot int64, userJp map[int64]int64) {
msg := &events.JackpotEvent{
EventType: events.JackpotEvent_et_hit_jackpot,
GameId: rm.RoomCfg.GameId,
Time: time.Now().UnixMilli(),
HitJackpot: &events.JackpotEvent_HitJackpot{SumJackpot: jackpot, UserJackpot: userJp},
GameNo: rm.Table.GetGameRoundId(),
}
go func() {
err := gconfig.Produce(context.Background(), define.TopicJackpot, msg)
if err != nil {
log.Error(rm.Log("kafka JackpotEvent_HitJackpot err: %v", err))
}
}()
log.Debug(rm.Log("kafka 中jackpot:%v", jackpot))
}
func (rm *ColorRoom) kafkaBackJackpot(jackpot, jpx, jpy int64, userJp map[int64]int64) {
userJp2 := make(map[int64]int64)
for k, v := range userJp {
userJp2[k] = -v
}
msg := &events.JackpotEvent{
EventType: events.JackpotEvent_et_game_discard,
GameId: rm.RoomCfg.GameId,
Time: time.Now().UnixMilli(),
GameDiscard: &events.JackpotEvent_GameDiscard{
Jackpot: -jackpot,
JackpotX: -jpx,
JackpotY: -jpy,
UserJackpot: userJp2,
},
GameNo: rm.Table.GetGameRoundId(),
}
go func() {
err := gconfig.Produce(context.Background(), define.TopicJackpot, msg)
if err != nil {
log.Error(rm.Log("kafka JackpotEvent_HitJackpot err: %v", err))
}
}()
log.Debug(rm.Log("kafka 回退jackpot:%v jpx:%v jpy:%v", -jackpot, -jpx, -jpy))
}