package live_logic import ( "database/sql" "dcg/app/user_center/usercenter" "dcg/config" "dcg/game/manager" "dcg/game/pb" pbCommon "dcg/game/pb/common" pbGameZhg "dcg/game/pb/game/zhg" pbMq "dcg/game/pb/mq" 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 *LiveGameLogic } func NewZhgLiveGameLogic(svcCtx *svc.ServiceContext) *LiveGameLogic { cmdParser := cmd.NewCMDParser( cmd.Pattern{ Prefix: "q", Alias: []string{"查询"}, ContentMaxLen: 0, }, cmd.Pattern{ Prefix: "j", Alias: []string{"加入", "加入游戏"}, ContentMaxLen: 0, }, cmd.Pattern{ Prefix: "c", Alias: []string{"换兵"}, ContentMaxLen: 1, }, cmd.Pattern{ Prefix: "w", Alias: []string{"我在哪"}, ContentMaxLen: 0, }, cmd.Pattern{ Prefix: "s", ContentMaxLen: 4, Distinct: sql.NullBool{Bool: false, Valid: true}, }, cmd.Pattern{ Prefix: "m", ContentMaxLen: 1, }, cmd.Pattern{ Prefix: "r", ContentMaxLen: 1, }, cmd.Pattern{ Prefix: "bq", Alias: []string{"购买粮草", "买粮草"}, ContentMaxLen: 2, }, cmd.Pattern{ Prefix: "bw", Alias: []string{"购买精英", "买精英"}, ContentMaxLen: 2, }, cmd.Pattern{ Prefix: "zw", Alias: []string{"装备精英"}, ContentMaxLen: 2, }, cmd.Pattern{ Prefix: "zz", Alias: []string{"使用称号"}, ContentMaxLen: 2, }, cmd.Pattern{ Prefix: "结算", Alias: nil, ContentMaxLen: 2, }, ) cmdParser.SetDistinct(true) resp := &ZhgGameLogic{ svcCtx: svcCtx, LiveGameLogic: NewLiveGameLogic(pbRoom.GameType_ZHG, cmdParser), } resp.RegisterCMDHandler(resp.handleQuery, "q") resp.RegisterCMDHandler(resp.handleJoinGame, "j") resp.RegisterCMDHandler(resp.handleCreateUnit, "c") resp.RegisterCMDHandler(resp.handleWai, "w") resp.RegisterCMDHandler(resp.handleOutbreak, "s") resp.RegisterCMDHandler(resp.handleMove, "m") resp.RegisterCMDHandler(resp.handleMode, "r") // resp.RegisterCMDHandler(resp.handleBuyFood, "bq") resp.RegisterCMDHandler(resp.handleBuyElite, "bw") resp.RegisterCMDHandler(resp.handleChangeElite, "zw") resp.RegisterCMDHandler(resp.handleChangeTitle, "zz") // resp.RegisterCMDHandler(resp.handleRankSubmit, "结算") // gift resp.RegisterGiftHandler(resp.handleGift) return resp.LiveGameLogic } func (h *ZhgGameLogic) handleQuery(roomId int64, _ []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoomId(roomId) 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, }) } } room.Broadcast(pb.PushUserQuery, resp) } func (h *ZhgGameLogic) handleJoinGame(roomId int64, _ []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoomId(roomId) if err != nil { return } logger.SLog.Debugf("用户 [%s] 加入游戏", user.Username) 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, } } room.Broadcast(pb.PushZhgJoinGame, resp) } func (h *ZhgGameLogic) handleOutbreak(roomId int64, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoomId(roomId) 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, content, user) } } func (h *ZhgGameLogic) handleOutbreakFood(room *manager.Room, content []rune, user *pbCommon.PbUser) { if len(content) < 1 { return } zhgCfg := config.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 } } 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(roomId int64, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoomId(roomId) 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(roomId int64, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoomId(roomId) 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(roomId int64, _ []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoomId(roomId) if err != nil { return } logger.SLog.Debugf("用户 [%s] 我在哪", user.Username) room.Broadcast(pb.PushZhgWhere, &pbGameZhg.Wai{User: user}) } func (h *ZhgGameLogic) handleMode(roomId int64, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoomId(roomId) 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(roomId int64, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoomId(roomId) if err != nil { return } if len(content) == 0 { return } cost, err := strconv.ParseInt(string(content), 10, 0) if err != nil { return } zhgCfg := config.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(roomId int64, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoomId(roomId) 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(roomId int64, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoomId(roomId) 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(roomId int64, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoomId(roomId) 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(roomId int64, content []rune, user *pbCommon.PbUser) { room, err := manager.GameManager.RoomByLiveRoomId(roomId) if err != nil { return } if len(content) == 0 { return } var isAdminUser bool for _, i := range config.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) } 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(roomId int64, user *pbCommon.PbUser, gift *pbMq.MqGift) { // TODO 暂时没有特殊礼物需求,留空 }