You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

571 lines
15 KiB
Go

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 暂时没有特殊礼物需求,留空
//}