package live_logic import ( "database/sql" "dcg/app/user_center/usercenter" "dcg/game/manager" "dcg/game/pb" pbCommon "dcg/game/pb/common" pbGameZhg "dcg/game/pb/game/zhg" pbRoom "dcg/game/pb/room" pbVars "dcg/game/pb/vars" "dcg/game/svc" "dcg/pkg/cmd" "dcg/pkg/grpcx" "git.noahlan.cn/northlan/ntools-go/logger" "github.com/shopspring/decimal" "strconv" "strings" ) type ZhgGameLogic struct { svcCtx *svc.ServiceContext tmpOutbreakCountMap map[string]int64 } func NewZhgLiveGameLogic(svcCtx *svc.ServiceContext) *ZhgGameLogic { return &ZhgGameLogic{ svcCtx: svcCtx, tmpOutbreakCountMap: make(map[string]int64), } } func (h *ZhgGameLogic) WithCmdParserLogic(p []cmd.Pattern) LogicOption { pattern := []cmd.Pattern{ { Prefix: "q", Alias: []string{"查询"}, ContentMaxLen: 0, }, { Prefix: "j", Alias: []string{"加入", "加入游戏"}, ContentMaxLen: 0, }, { Prefix: "c", Alias: []string{"换兵"}, ContentMaxLen: 1, }, { Prefix: "w", Alias: []string{"我在哪"}, ContentMaxLen: 0, }, { Prefix: "s", ContentMaxLen: 4, Distinct: sql.NullBool{Bool: false, Valid: true}, }, { Prefix: "m", ContentMaxLen: 1, }, { Prefix: "r", ContentMaxLen: 1, }, { Prefix: "bq", Alias: []string{"购买粮草", "买粮草"}, ContentMaxLen: 2, }, { Prefix: "bw", Alias: []string{"购买精英", "买精英"}, ContentMaxLen: 2, }, { Prefix: "zw", Alias: []string{"装备精英"}, ContentMaxLen: 2, }, { Prefix: "zz", Alias: []string{"使用称号"}, ContentMaxLen: 2, }, { Prefix: "结算", Alias: nil, ContentMaxLen: 2, }, } pattern = append(pattern, p...) cmdParser := cmd.NewCMDParser(pattern...) cmdParser.SetDistinct(true) return WithCmdParser(cmdParser) } func (h *ZhgGameLogic) WithGameType() LogicOption { return WithGameType(pbRoom.GameType_name[int32(pbRoom.GameType_ZHG)]) } func (h *ZhgGameLogic) WithCmdHandlers() LogicOption { return func(logic LiveLogic) { logic.RegisterCMDHandler(h.handleQuery, "q") logic.RegisterCMDHandler(h.handleJoinGame, "j") logic.RegisterCMDHandler(h.handleCreateUnit, "c") logic.RegisterCMDHandler(h.handleWai, "w") logic.RegisterCMDHandler(h.handleOutbreak, "s") logic.RegisterCMDHandler(h.handleMove, "r") logic.RegisterCMDHandler(h.handleMode, "m") logic.RegisterCMDHandler(h.handleBuyFood, "bq") logic.RegisterCMDHandler(h.handleBuyElite, "bw") logic.RegisterCMDHandler(h.handleChangeElite, "zw") logic.RegisterCMDHandler(h.handleChangeTitle, "zz") logic.RegisterCMDHandler(h.handleRankSubmit, "结算") } } func (h *ZhgGameLogic) handleQuery(liveRoom *LiveRoom, _ string, _ []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoom(liveRoom.RoomId, liveRoom.Platform) if err != nil { return } logger.SLog.Debugf("用户 [%s] 查询", user.Username) resp := &pbGameZhg.UserQueryMsg{ User: user, } // details if details, err := h.svcCtx.UserCenterRpc.GetUserDetails(h.svcCtx.Ctx, &usercenter.UserIdReq{UserId: user.UserId}); err == nil { resp.Coin = details.Coin if details.CurrentTitle != nil { resp.CurrentTitle = &pbCommon.TitleItem{ Id: details.CurrentTitle.Id, Name: details.CurrentTitle.Name, Sort: details.CurrentTitle.Sort, Remain: details.CurrentTitle.Remain, } } if details.CurrentElite != nil { resp.CurrentElite = &pbGameZhg.EliteItem{ Id: details.CurrentElite.Id, Sort: details.CurrentElite.Sort, Remain: details.CurrentElite.Remain, } } resp.Titles = make([]*pbCommon.TitleItem, 0, len(details.Titles)) for _, item := range details.Titles { resp.Titles = append(resp.Titles, &pbCommon.TitleItem{ Id: item.Id, Name: item.Name, Sort: item.Sort, Remain: item.Remain, }) } resp.Elites = make([]*pbGameZhg.EliteItem, 0, len(details.Elites)) for _, item := range details.Elites { resp.Elites = append(resp.Elites, &pbGameZhg.EliteItem{ Id: item.Id, Sort: item.Sort, Remain: item.Remain, }) } } // rank if rpcRank, err := h.svcCtx.UserCenterRpc.UserRankPvp(h.svcCtx.Ctx, &usercenter.UserRankReq{ UserId: user.UserId, Username: user.Username, AllRankType: true, }); err == nil { resp.Rank = make([]*pbGameZhg.UserQueryMsg_RankItem, 0, len(rpcRank.Items)) for _, item := range rpcRank.Items { resp.Rank = append(resp.Rank, &pbGameZhg.UserQueryMsg_RankItem{ RankType: int32(item.RankType), Score: item.Score, Rank: item.Pos, }) } } grade, err := h.svcCtx.UserCenterRpc.GetUserGrade(h.svcCtx.Ctx, &usercenter.UserIdReq{UserId: user.UserId}) if err != nil { return } resp.Grade = &pbGameZhg.Grade{ Grade: grade.Grade.Grade, Level: grade.Grade.Level, Star: grade.Grade.Star, BravePoint: grade.Grade.BravePoint, } room.Broadcast(pb.PushUserQuery, resp) } func (h *ZhgGameLogic) handleJoinGame(liveRoom *LiveRoom, _ string, _ []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoom(liveRoom.RoomId, liveRoom.Platform) if err != nil { return } details, err := h.svcCtx.UserCenterRpc.GetUserDetails(h.svcCtx.Ctx, &usercenter.UserIdReq{ UserId: user.UserId, }) if err != nil { return } resp := &pbGameZhg.JoinGame{ User: user, NobilityLevel: details.NobilityLevel, Coin: details.Coin, } if details.CurrentTitle != nil { resp.CurrentTitle = &pbCommon.TitleItem{ Id: details.CurrentTitle.Id, Name: details.CurrentTitle.Name, Sort: details.CurrentTitle.Sort, Remain: details.CurrentTitle.Remain, } } if details.CurrentElite != nil { resp.CurrentElite = &pbGameZhg.EliteItem{ Id: details.CurrentElite.Id, Sort: details.CurrentElite.Sort, Remain: details.CurrentElite.Remain, } } grade, err := h.svcCtx.UserCenterRpc.GetUserGrade(h.svcCtx.Ctx, &usercenter.UserIdReq{UserId: user.UserId}) if err != nil { return } resp.Grade = &pbGameZhg.Grade{ Grade: grade.Grade.Grade, Level: grade.Grade.Level, Star: grade.Grade.Star, BravePoint: grade.Grade.BravePoint, } logger.SLog.Debugf("用户 [%s] 加入游戏", user.Username) room.Broadcast(pb.PushZhgJoinGame, resp) } func (h *ZhgGameLogic) handleOutbreak(liveRoom *LiveRoom, prefix string, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoom(liveRoom.RoomId, liveRoom.Platform) if err != nil { return } if len(content) == 0 { logger.SLog.Debugf("用户 [%s] 普通暴兵", user.Username) room.Broadcast(pb.PushZhgOutbreak, &pbGameZhg.Outbreak{User: user}) } else { h.handleOutbreakFood(room, prefix, content, user) } } func (h *ZhgGameLogic) handleOutbreakFood(room *manager.Room, prefix string, content []rune, user *pbCommon.PbUser) { if len(content) < 1 { return } zhgCfg := h.svcCtx.Config.Game.Zhg // s1,10s2,10s3,10s4,10 11,0 111, contentStr := string(content) var unitTypeStr string var count int64 var err error idxSplit := strings.IndexRune(contentStr, ' ') if idxSplit == -1 { // 没有分隔符,判断内容位数? unitTypeStr = string(content) count = zhgCfg.OutbreakCount } else { unitTypeStr = string(content[:idxSplit]) if idxSplit == len(content)-1 { count = zhgCfg.OutbreakCount } else { count, err = strconv.ParseInt(string(content[idxSplit+1:]), 10, 0) if err != nil { return } } if count > zhgCfg.OutbreakMaxCount { count = zhgCfg.OutbreakMaxCount } if count <= 0 { count = zhgCfg.OutbreakCount } } //if allCount, ok := h.tmpOutbreakCountMap[msgId]; ok { // if allCount+count > zhgCfg.OutbreakMaxCount { // return // } //} unitType, err := strconv.Atoi(unitTypeStr) if err != nil { return } var cost int64 if unitCost, ok := zhgCfg.OutbreakCostDict[unitType]; ok { // 四舍五入计算 cost = decimal.NewFromInt(count).Mul(decimal.NewFromFloat(unitCost)).Round(0).IntPart() } else { return } logger.SLog.Debugf("用户 [%s] 粮草暴兵", user.Username) room.Broadcast(pb.PushZhgOutbreakFood, &pbGameZhg.OutbreakFood{ User: user, UnitType: unitTypeStr, Count: int32(count), Cost: cost, }) } func (h *ZhgGameLogic) handleCreateUnit(liveRoom *LiveRoom, _ string, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoom(liveRoom.RoomId, liveRoom.Platform) if err != nil { return } logger.SLog.Debugf("用户 [%s] 切换单位", user.Username) if len(content) < 1 { return } room.Broadcast(pb.PushZhgCreateUnit, &pbGameZhg.CreateUnit{ User: user, Unit: string(content[0]), }) } func (h *ZhgGameLogic) handleMove(liveRoom *LiveRoom, _ string, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoom(liveRoom.RoomId, liveRoom.Platform) if err != nil { return } logger.SLog.Debugf("用户 [%s] 切换路线", user.Username) if len(content) < 1 { return } room.Broadcast(pb.PushZhgMove, &pbGameZhg.Move{ User: user, Line: string(content[0]), }) } func (h *ZhgGameLogic) handleWai(liveRoom *LiveRoom, _ string, _ []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoom(liveRoom.RoomId, liveRoom.Platform) if err != nil { return } logger.SLog.Debugf("用户 [%s] 我在哪", user.Username) room.Broadcast(pb.PushZhgWhere, &pbGameZhg.Wai{User: user}) } func (h *ZhgGameLogic) handleMode(liveRoom *LiveRoom, _ string, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoom(liveRoom.RoomId, liveRoom.Platform) if err != nil { return } logger.SLog.Debugf("用户 [%s] 兵营模式", user.Username) if len(content) < 1 { return } room.Broadcast(pb.PushZhgMode, &pbGameZhg.BuildingMode{ User: user, Mode: string(content[0]), }) } func (h *ZhgGameLogic) handleBuyFood(liveRoom *LiveRoom, _ string, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoom(liveRoom.RoomId, liveRoom.Platform) if err != nil { return } if len(content) == 0 { return } cost, err := strconv.ParseInt(string(content), 10, 0) if err != nil { return } zhgCfg := h.svcCtx.Config.Game.Zhg food := decimal.NewFromInt(cost).Mul(decimal.NewFromFloat32(zhgCfg.CoinFoodRatio)).Round(0).IntPart() logger.SLog.Debugf("用户 [%s] 买粮草 花费[%d] 买到[%d]", user.Username, cost, food) room.Broadcast(pb.PushZhgBuyFood, &pbGameZhg.BuyBattleFood{ UserId: user.UserId, Cost: cost, Food: food, }) } func (h *ZhgGameLogic) handleBuyElite(liveRoom *LiveRoom, _ string, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoom(liveRoom.RoomId, liveRoom.Platform) if err != nil { return } if len(content) == 0 { return } eliteSort, err := strconv.ParseInt(string(content), 10, 0) if err != nil { return } resp := &pbCommon.UserBuyGoodsMsg{ User: user, Goods: pbVars.Goods_Elite, } rpcResp, err := h.svcCtx.UserCenterRpc.BuyElite(h.svcCtx.Ctx, &usercenter.EliteReq{ UserId: user.UserId, Sort: int32(eliteSort), }) if err != nil { // rpc错误 resp.Code, _, _ = grpcx.WrapGrpcErr(err) logger.SLog.Error("兑换精英单位时发生RPC错误", err) } else { resp.Code = 200 resp.GoodsId = rpcResp.EliteId resp.Count = 1 resp.Cost = rpcResp.Cost resp.Duration = rpcResp.Duration } logger.SLog.Debugf("用户 [%s] 买精英单位 花费[%d] 买到[%d]", user.Username, resp.Cost, resp.GoodsId) room.Broadcast(pb.PushBuyGoods, resp) } func (h *ZhgGameLogic) handleChangeElite(liveRoom *LiveRoom, _ string, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoom(liveRoom.RoomId, liveRoom.Platform) if err != nil { return } if len(content) == 0 { return } eliteSort, err := strconv.ParseInt(string(content), 10, 0) if err != nil { return } resp := &pbGameZhg.ChangeElite{ User: user, EliteId: 0, } rpcResp, err := h.svcCtx.UserCenterRpc.ChangeElite(h.svcCtx.Ctx, &usercenter.EliteReq{ UserId: user.UserId, Sort: int32(eliteSort), }) if err != nil { resp.Code, _, _ = grpcx.WrapGrpcErr(err) logger.SLog.Error("切换精英单位时发生RPC错误", err) } else { resp.Code = 200 resp.EliteId = rpcResp.EliteId } logger.SLog.Debugf("用户 [%s] 切换精英单位到 %d", user.Username, resp.EliteId) room.Broadcast(pb.PushZhgChangeElite, resp) } func (h *ZhgGameLogic) handleChangeTitle(liveRoom *LiveRoom, _ string, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoom(liveRoom.RoomId, liveRoom.Platform) if err != nil { return } if len(content) == 0 { return } titleSort, err := strconv.ParseInt(string(content), 10, 0) if err != nil { return } resp := &pbGameZhg.ChangeTitle{ User: user, } rpcResp, err := h.svcCtx.UserCenterRpc.ChangeTitle(h.svcCtx.Ctx, &usercenter.TitleReq{ UserId: user.UserId, Sort: int32(titleSort), }) if err != nil { resp.Code, _, _ = grpcx.WrapGrpcErr(err) logger.SLog.Error("切换称号时发生RPC错误", err) } else { resp.Code = 200 resp.TitleId = rpcResp.TitleId resp.Name = rpcResp.Name } logger.SLog.Debugf("用户 [%s] 切换称号到 %s", user.Username, resp.Name) room.Broadcast(pb.PushZhgChangeTitle, resp) } func (h *ZhgGameLogic) handleRankSubmit(liveRoom *LiveRoom, _ string, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoom(liveRoom.RoomId, liveRoom.Platform) if err != nil { return } if len(content) == 0 { return } var isAdminUser bool for _, i := range h.svcCtx.Config.Game.AdminUserId { if user.UserId == i { isAdminUser = true break } } if !isAdminUser { return } rankType := pbVars.RankType_General if r, err := strconv.ParseInt(string(content), 10, 0); err == nil { rankType = pbVars.RankType(r) } else { // 无效的rankTye return } rpcResp, err := h.svcCtx.UserCenterRpc.RankPvpSubmit(h.svcCtx.Ctx, &usercenter.RankPvpSubmitReq{ RankType: rankType, AllRankType: false, }) if err != nil { code, msg, _ := grpcx.WrapGrpcErr(err) logger.SLog.Errorf("结算排行榜时RPC错误 code:[%d] msg:[%s] %v", code, msg, err) return } resp := &pbGameZhg.RankRvpSubmitResult{ Items: make([]*pbGameZhg.RankRvpSubmitResult_Item, 0, len(rpcResp.Items)), } for _, item := range rpcResp.Items { tmp := &pbGameZhg.RankRvpSubmitResult_Item{ RankType: item.RankType, Results: make([]*pbGameZhg.RankRvpSubmitResult_Result, 0, len(item.Results)), } for _, result := range item.Results { tmp.Results = append(tmp.Results, &pbGameZhg.RankRvpSubmitResult_Result{ UserId: result.UserId, Username: result.Username, Avatar: result.Avatar, Coin: result.Coin, Title: result.Title, }) } resp.Items = append(resp.Items, tmp) } logger.SLog.Debugf("用户 [%s] 结算排行榜 %d\n%+v", user.Username, rankType, resp) room.Broadcast(pb.PushZhgRankSubmit, resp) } //func (h *ZhgGameLogic) handleGift(liveRoom *LiveRoom, user *pbCommon.PbUser, gift *pbMq.MqGift) { // // TODO 暂时没有特殊礼物需求,留空 //}