2025-06-08 00:52:17 +08:00

1180 lines
39 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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))
}