package room import ( "encoding/json" "game/common/proto/pb" "github.com/fox/fox/log" ) // const ( // LiveProcessInit = iota // LiveProcessStart // LiveProcessWait // LiveProcessWaitDone // LiveProcessFuncStart // LiveProcessFuncDone // ) // // var LiveProcessStatusName = map[int]string{ // LiveProcessInit: "LiveProcessInit", // LiveProcessStart: "LiveProcessStart", // LiveProcessWait: "LiveProcessWait", // LiveProcessWaitDone: "LiveProcessWaitDone", // LiveProcessFuncStart: "LiveProcessFuncStart", // LiveProcessFuncDone: "LiveProcessFuncDone", // } type LiveMgr struct { // LiveWg *sync.WaitGroup // Count int // 当前数量 // Mu *sync.Mutex MaintenanceStatus int32 // 维护状态 0 正常 1 维护 // ProcessStatus int // 进程状态 Restting bool // 重置状态 MainteMsg string DiscardMsg string DiscardStatus int DiscardRestting bool // 重置状态 RankList *pb.ColorPinoyLiveRankList HasMainte bool } func NewLiveMgr() *LiveMgr { return &LiveMgr{ // LiveWg: new(sync.WaitGroup), // Mu: new(sync.Mutex), RankList: new(pb.ColorPinoyLiveRankList), } } func (lm *LiveMgr) Reset() { lm.Restting = false lm.DiscardRestting = false lm.DiscardStatus = 0 } // func (lm *LiveMgr) IsAdd() bool { // lm.Mu.Lock() // defer lm.Mu.Unlock() // return lm.Count > 0 // } // // func (lm *LiveMgr) Add() { // log.Debug("LiveMgr add") // lm.Mu.Lock() // defer lm.Mu.Unlock() // lm.LiveWg.Add(1) // lm.Count++ // } // // func (lm *LiveMgr) Done() { // log.Debug("LiveMgr Done") // lm.Mu.Lock() // defer lm.Mu.Unlock() // if lm.Count == 0 { // return // } // lm.LiveWg.Done() // lm.Count-- // } // // func (lm *LiveMgr) Wait() { // log.Debug("LiveMgr Wait") // lm.LiveWg.Wait() // } func (lm *LiveMgr) NeedMaintenance() bool { return !lm.HasMainte && (lm.MaintenanceStatus == 1 || lm.DiscardStatus == 1) } func (rm *ColorRoom) LiveDelayUpdate() error { event := &events.ServCmdKafka{ ServCmd: common.ServCmd_sc_live_delay_update, } data := &common.ServLiveDelayUpdate{ GameId: gconfig.GConfig.GRoomConfig.GameId, MainteStatus: rm.LiveMgr.MaintenanceStatus, MainteMsg: rm.LiveMgr.MainteMsg, } event.Data, _ = proto.Marshal(data) err := gconfig.Produce(context.Background(), define.TopicSysServerCmd, event) if err != nil { log.Error(rm.Log("fail to Produce Event(%+v), err: %v", event, err)) return err } return nil } func (rm *ColorRoom) NotifyLiveDelayUpdate() { if !gconfig.DelayUpdateServer { return } if rm.LiveDelayUpdate() != nil { return } gconfig.DelayUpdateServer = false } func (rm *ColorRoom) ServerMaintenanceKickPlayer() { rm.Traverse(func(u *model.User) bool { kMsg := new(pb.ColorPinoyLiveKickOutUserMsg) kMsg.Reason = int32(pb.ColorPinoyLiveLeaveReason_ColorPinoyLiveLeaveReason_Server_Update) u.SendMsg(int32(pb.ColorPinoyLiveSendToClientMessageType_ColorPinoyLiveNoticeKickOutUser), kMsg) rm.KickOutUser(u) return true }) } func (rm *ColorRoom) SyncServerMaintenance(st int32, ss string) { _ = st _ = ss rm.LoadDealerNames() // 可能即将变为 normal if gconfig.GConfig.GServConfig.Status != define.GameStatusNoraml { rm.LiveMgr.MaintenanceStatus = 0 rm.LiveMgr.MainteMsg = "" return } ssv := redisf.RSC.LiveMainteGet(gconfig.GConfig.GDataConfig.VersionMode, gconfig.GConfig.GRoomConfig.GameId) resp := new(pb.ColorPinoyLiveCommResp) _ = json.Unmarshal([]byte(ssv), resp) rm.LiveMgr.MaintenanceStatus = resp.MaintainStatus rm.LiveMgr.MainteMsg = resp.MaintainMsg } func (rm *ColorRoom) OnLiveGameMessage(subCmd int32, buffer []byte) ([]byte, error) { // log.Debug("收到后台消息:", subCmd) var result proto.Message _, err := rm.Table.RunAndWait(func() any { switch subCmd { case int32(pb.ColorPinoyLiveProcessCmd_ColorPinoyLiveMSGGameGetStatus): result = rm.LiveGetGameStatus(buffer) case int32(pb.ColorPinoyLiveProcessCmd_ColorPinoyLiveMSGReady): result = rm.LiveGameReady(buffer) // 点击finish case int32(pb.ColorPinoyLiveProcessCmd_ColorPinoyLiveMSGBetting): result = rm.LiveGameBetting(buffer) // 点击start case int32(pb.ColorPinoyLiveProcessCmd_ColorPinoyLiveMSGMStartDice): result = rm.LiveGameStartDice(buffer) case int32(pb.ColorPinoyLiveProcessCmd_ColorPinoyLiveMSGMResultImg): result = rm.LiveGameResultImg(buffer) // case int32(pb.ColorPinoyLiveProcessCmd_ColorPinoyLiveMSGLucky): // result = rm.LiveGameLucky(buffer) case int32(pb.ColorPinoyLiveProcessCmd_ColorPinoyLiveMSGResult): result = rm.LiveGameResult(buffer) case int32(pb.ColorPinoyLiveProcessCmd_ColorPinoyLiveMSGMMainteSet): result = rm.LiveGameMainte(buffer) case int32(pb.ColorPinoyLiveProcessCmd_ColorPinoyLiveMSGMDiscard): result = rm.LiveGameDiscard(buffer) case int32(pb.ColorPinoyLiveProcessCmd_ColorPinoyLiveMSGMRankList): result = rm.LiveGameRankList(buffer) case int32(pb.ColorPinoyLiveProcessCmd_ColorPinoyLiveMSGSetDealer): result = rm.LiveGameSetDealerName(buffer) default: log.Error(rm.Log("no protocol")) return nil } return result }) if err == nil && result != nil { b, _ := proto.Marshal(result) canLog := true if subCmd == int32(pb.ColorPinoyLiveProcessCmd_ColorPinoyLiveMSGGameGetStatus) { if rd := rand.RandInt(0, 100); rd < 90 { canLog = false } } if canLog { j, _ := json.Marshal(result) log.Debug(rm.Log("返回后台消息 subCmd:%d, msg:%s", subCmd, string(j))) } return b, nil } return nil, err } func (rm *ColorRoom) getStatus() (int32, int64) { switch rm.Status { case pb.ColorPinoyLiveGameStatus_ColorPinoyLiveStartUnReady: return int32(rm.Status), rm.StatusTime + int64(rm.RoomCfg.TimeConf.Readymove) case pb.ColorPinoyLiveGameStatus_ColorPinoyLiveStartReady: return int32(rm.Status), rm.StatusTime + int64(rm.RoomCfg.TimeConf.Startmove) case pb.ColorPinoyLiveGameStatus_ColorPinoyLiveStartMovie: return int32(pb.ColorPinoyLiveGameStatus_ColorPinoyLiveBetStatus), rm.StatusTime + int64(rm.RoomCfg.TimeConf.Startbet) case pb.ColorPinoyLiveGameStatus_ColorPinoyLiveBetStatus: return int32(rm.Status), rm.StatusTime + int64(rm.RoomCfg.TimeConf.Startbet) case pb.ColorPinoyLiveGameStatus_ColorPinoyLiveEndBetMovie: return int32(rm.Status), rm.StatusTime + int64(rm.RoomCfg.TimeConf.Endmove) case pb.ColorPinoyLiveGameStatus_ColorPinoyLiveOpenThreeDice: return int32(rm.Status), rm.StatusTime + int64(rm.RoomCfg.TimeConf.OpenThreeDice) case pb.ColorPinoyLiveGameStatus_ColorPinoyLiveSettleStatus: return int32(rm.Status), rm.StatusTime + int64(rm.RoomCfg.TimeConf.Endpay) case pb.ColorPinoyLiveGameStatus_ColorPinoyLiveRankStatus: return int32(rm.Status), rm.StatusTime + int64(rm.RoomCfg.TimeConf.Rank) default: return int32(rm.Status), rm.StatusTime } } func (rm *ColorRoom) LiveStatus() *pb.ColorPinoyLiveCommResp { resp := &pb.ColorPinoyLiveCommResp{ GameId: gconfig.GConfig.GRoomConfig.GameId, MaintainStatus: rm.LiveMgr.MaintenanceStatus, MaintainMsg: rm.LiveMgr.MainteMsg, Times: rm.RoomCfg.TimeConf.Get(), GameNo: rm.Table.GetGameRoundId(), DealerName: rm.dealerName, Jackpot: rm.jackpotMgr.GetJackpotCopy(), } resp.GameStatus, resp.Countdown = rm.getStatus() resp.BetAreaMul = rm.betEndBetAreasOdds for _, dice := range rm.StartDices { resp.StartDice = append(resp.StartDice, pb.ColorPinoyLiveDiceColorType(model.GetColor(dice))) } resp.ResultImg = rm.ResultImgs switch rm.Status { case pb.ColorPinoyLiveGameStatus_ColorPinoyLiveOpenThreeDice: resp.LuckyStar = pb.ColorPinoyLiveDiceColorType(model.GetColor(rm.LuckyDice)) for _, dice := range rm.NormalDices { resp.DrawResult = append(resp.DrawResult, pb.ColorPinoyLiveDiceColorType(model.GetColor(dice))) } case pb.ColorPinoyLiveGameStatus_ColorPinoyLiveSettleStatus, pb.ColorPinoyLiveGameStatus_ColorPinoyLiveRankStatus: resp.LuckyStar = pb.ColorPinoyLiveDiceColorType(model.GetColor(rm.LuckyDice)) for _, dice := range rm.NormalDices { resp.DrawResult = append(resp.DrawResult, pb.ColorPinoyLiveDiceColorType(model.GetColor(dice))) } resp.RankList = rm.LiveMgr.RankList default: } // 结束下注后,后台可看到更新爆奖后的投注面板 if rm.Status > pb.ColorPinoyLiveGameStatus_ColorPinoyLiveBetStatus { resp.BetAreaMul = rm.betEndBetAreasOdds } return resp } func (rm *ColorRoom) LiveGetGameStatus(buffer []byte) proto.Message { _ = buffer return rm.LiveStatus() } func (rm *ColorRoom) LiveGameReady(buffer []byte) proto.Message { _ = buffer log.Debug(rm.Log("LiveGameReady")) // rm.MutexStatus.Lock() // defer rm.MutexStatus.Unlock() resp := rm.LiveStatus() if rm.LiveMgr.MaintenanceStatus == 1 { resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorMainteStatus) return resp } if rm.Status != pb.ColorPinoyLiveGameStatus_ColorPinoyLiveRankStatus { resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorGameSatus) return resp } rm.Ready() resp.GameStatus, resp.Countdown = rm.getStatus() return resp } func (rm *ColorRoom) LiveGameBetting(buffer []byte) proto.Message { _ = buffer log.Debug(rm.Log("LiveGameBetting")) // rm.MutexStatus.Lock() // defer rm.MutexStatus.Unlock() resp := rm.LiveStatus() if rm.LiveMgr.MaintenanceStatus == 1 { resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorMainteStatus) return resp } if rm.Status != pb.ColorPinoyLiveGameStatus_ColorPinoyLiveStartReady { resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorGameSatus) return resp } rm.StartBet() return resp } func (rm *ColorRoom) LiveGameStartDice(buffer []byte) proto.Message { log.Debug(rm.Log("LiveGameStartDice")) resp := rm.LiveStatus() if rm.LiveMgr.MaintenanceStatus == 1 { resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorMainteStatus) return resp } if rm.Status != pb.ColorPinoyLiveGameStatus_ColorPinoyLiveEndBetMovie { resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorGameSatus) return resp } req := new(pb.ColorPinoyLiveStartDice) _ = proto.Unmarshal(buffer, req) if len(req.GetStartDice()) != 3 { resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorDice) return resp } for i := 0; i < len(req.GetStartDice()); i++ { rm.StartDices[i] = byte(req.GetStartDice()[i]) } log.Debug(rm.Log("req:", req.GetStartDice(), ",StartDice:", rm.StartDices)) resp.StartDice = make([]pb.ColorPinoyLiveDiceColorType, 0) for _, dice := range rm.StartDices { resp.StartDice = append(resp.StartDice, pb.ColorPinoyLiveDiceColorType(model.GetColor(dice))) } resp.ResultImg = rm.ResultImgs return resp } func (rm *ColorRoom) LiveGameResultImg(buffer []byte) proto.Message { resp := rm.LiveStatus() if rm.LiveMgr.MaintenanceStatus == 1 { resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorMainteStatus) return resp } req := new(pb.ColorPinoyLiveResultImg) _ = proto.Unmarshal(buffer, req) rm.ResultImgs = append(rm.ResultImgs, req.GetResultImg()...) log.Debug(rm.Log("req:", req.GetResultImg(), ",ResultImg:", rm.ResultImgs)) resp.StartDice = make([]pb.ColorPinoyLiveDiceColorType, 0) for _, dice := range rm.StartDices { resp.StartDice = append(resp.StartDice, pb.ColorPinoyLiveDiceColorType(model.GetColor(dice))) } resp.ResultImg = rm.ResultImgs return resp } func (rm *ColorRoom) LiveGameResult(buffer []byte) proto.Message { // rm.MutexStatus.Lock() // defer rm.MutexStatus.Unlock() log.Debug(rm.Log("LiveGameResult")) resp := rm.LiveStatus() if rm.LiveMgr.MaintenanceStatus == 1 { resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorMainteStatus) return resp } log.Debug(rm.Log("LiveGameResult status:%v ", rm.Status)) if rm.Status != pb.ColorPinoyLiveGameStatus_ColorPinoyLiveEndBetMovie { resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorGameSatus) return resp } req := new(pb.ColorPinoyLiveResult) _ = proto.Unmarshal(buffer, req) if len(req.GetColor()) != 3 { resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorDice) return resp } else { for i := 0; i < len(req.GetColor()); i++ { if !model.IsLogic(int32(req.GetColor()[i])) { resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorDice) return resp } rm.NormalDices[i] = byte(req.GetColor()[i]) } } log.Debug(rm.Log("LiveGameResult req:%v NormalDices:%v", req.GetColor(), rm.NormalDices)) rm.Table.Run(rm.openThreeDice) return resp } func (rm *ColorRoom) LiveGameMainte(buffer []byte) proto.Message { req := new(pb.ColorPinoyLiveMaintain) _ = proto.Unmarshal(buffer, req) b, _ := json.Marshal(req) log.Debug(rm.Log("LiveGameMainte:%v", string(b))) resp := rm.LiveStatus() if rm.LiveMgr.Restting { resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorMainteStatus) resp.Msg = "Restting" return resp } if req.TargetStatus == rm.LiveMgr.MaintenanceStatus { resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorMainteStatus) return resp } if rm.GetGameStatus() == pb.ColorPinoyLiveGameStatus_ColorPinoyLiveSettleStatus { resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorGameSatus) resp.Msg = "SettleStatus" return resp } defer func() { _ = pushGate.NotifyConfigUpdated(msg.ConfigUpdateType_ConfigUpdateTypeLiveConfig) rm.SetLiveGameStatus() }() if req.TargetStatus == 0 { rm.LiveMgr.MaintenanceStatus = 0 rm.LiveMgr.MainteMsg = "" rm.LiveMgr.HasMainte = false } else { rm.LiveMgr.MaintenanceStatus = req.TargetStatus rm.LiveMgr.MainteMsg = req.GetMsg() rm.LiveMainteCnt() } resp.MaintainStatus = rm.LiveMgr.MaintenanceStatus resp.MaintainMsg = rm.LiveMgr.MainteMsg resp.GameStatus, resp.Countdown = rm.getStatus() br, _ := json.Marshal(resp) redisf.RSC.LiveMainteSet(gconfig.GConfig.GDataConfig.VersionMode, gconfig.GConfig.GRoomConfig.GameId, string(br)) redisf.RSC.LiveMainteLobbySet(gconfig.GConfig.GDataConfig.VersionMode, gconfig.GConfig.GRoomConfig.GameId, rm.LiveMgr.MaintenanceStatus, rm.LiveMgr.MainteMsg) return resp } func (rm *ColorRoom) LiveMainteCnt() { rm.LiveMainte() } func (rm *ColorRoom) LiveMainte() { if rm.LiveMgr.MaintenanceStatus == 1 { rm.LiveMgr.HasMainte = true rm.LiveMgr.Restting = true } if rm.LiveMgr.DiscardStatus == 1 { rm.LiveMgr.DiscardRestting = true } rm.GameDiscard() // rm.LiveMgr.SetProcessStatus(LiveProcessInit) if rm.LiveMgr.MaintenanceStatus == 1 { rm.LiveMgr.Restting = false } if rm.LiveMgr.DiscardStatus == 1 { rm.LiveMgr.DiscardRestting = false rm.LiveMgr.DiscardStatus = 0 } } func (rm *ColorRoom) LiveGameDiscard(_ []byte) proto.Message { log.Debug(rm.Log("LiveGameDiscard")) resp := rm.LiveStatus() if rm.LiveMgr.MaintenanceStatus == 1 { log.Error(rm.Log("rm.LiveMgr.MaintenanceStatus")) resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorMainteStatus) return resp } if rm.LiveMgr.DiscardRestting { resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorMainteStatus) resp.Msg = "DiscardRestting" return resp } // if rm.GetGameStatus() == pb.ColorPinoyLiveGameStatus_ColorPinoyLiveSettleStatus { // resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorGameSatus) // resp.Msg = "SettleStatus" // return resp // } rm.LiveMgr.DiscardStatus = 1 rm.LiveMgr.DiscardMsg = "" rm.LiveMainteCnt() resp.GameStatus, resp.Countdown = rm.getStatus() return resp } func (rm *ColorRoom) LiveGameRankList(buffer []byte) proto.Message { _ = buffer return rm.LiveMgr.RankList } func (rm *ColorRoom) LiveGameSetDealerName(buffer []byte) proto.Message { resp := rm.LiveStatus() if rm.LiveMgr.MaintenanceStatus == 1 { resp.Code = int32(pb.ColorPinoyLiveProcessError_ColorPinoyLiveProcessErrorMainteStatus) return resp } req := new(pb.ColorPinoyLiveSetDealer) _ = proto.Unmarshal(buffer, req) rm.UpdateDealerName(req.DealerName) log.Debug(rm.Log("set dealer:", req.DealerName)) resp.DealerName = rm.dealerName return resp } // 长度0 维护, 长度1 设置状态 , 长度2 设置排行榜 func (rm *ColorRoom) SetLiveGameStatus(pushRank ...int) { lScene := &lws.CPLScene{ Status: int32(rm.Status), RankList: nil, MaintainStatus: rm.LiveMgr.MaintenanceStatus, } if rm.LiveMgr.RankList != nil && (rm.Status == pb.ColorPinoyLiveGameStatus_ColorPinoyLiveSettleStatus || rm.Status == pb.ColorPinoyLiveGameStatus_ColorPinoyLiveRankStatus) { lScene.RankList = &lws.CPLRankList{ PlayerData: nil, GameNo: rm.LiveMgr.RankList.GameNo, } for _, dd := range rm.LiveMgr.RankList.PlayerData { lScene.RankList.PlayerData = append(lScene.RankList.PlayerData, &lws.CPLPlayerData{ Uid: dd.Uid, Profit: dd.Profit, Nickname: dd.Nickname, Avatar: dd.Avatar, }) } } if len(pushRank) == 0 { live.PushScene(lScene) } else if len(pushRank) == 1 { live.PushStatus(&lws.CPLStatus{Status: lScene.Status}) } else if len(pushRank) == 2 { live.PushColorRank(lScene.RankList) } go redisf.RSC.SetLiveGameStatus(lScene, gconfig.GConfig.GRoomConfig.GameId, gconfig.GConfig.GDataConfig.VersionMode) }