package modules import ( "context" "fmt" "go_dreamfactory/comm" "go_dreamfactory/lego/base" "go_dreamfactory/lego/core" "go_dreamfactory/lego/core/cbase" "go_dreamfactory/lego/sys/log" "go_dreamfactory/pb" cfg "go_dreamfactory/sys/configure/structs" "strconv" "github.com/spf13/cast" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" ) /* 基础业务模块实现 封装一些通用的接口提供给业务模块使用 */ type ModuleBase struct { cbase.ModuleBase module core.IModule service base.IRPCXService options IOptions scomp comm.ISC_GateRouteComp //网关服务组件 //常用的一些通用模块 在底层注册好 ModuleUser comm.IUser //用户模块 ModuleItems comm.IItems //道具背包模块 ModuleHero comm.IHero //英雄模块 ModuleEquipment comm.IEquipment //装备模块 ModuleTask comm.ITask //任务 } //重构模块配置对象 func (this *ModuleBase) NewOptions() (options core.IModuleOptions) { return new(Options) } //模块初始化接口 func (this *ModuleBase) Init(service core.IService, module core.IModule, options core.IModuleOptions) (err error) { err = this.ModuleBase.Init(service, module, options) this.service = service.(base.IRPCXService) this.module = module this.options = options.(IOptions) return } //模块启动接口 func (this *ModuleBase) Start() (err error) { err = this.ModuleBase.Start() var comp core.IServiceComp //注册远程路由 if comp, err = this.service.GetComp(comm.SC_ServiceGateRouteComp); err != nil { return } this.scomp = comp.(comm.ISC_GateRouteComp) var module core.IModule if module, err = this.service.GetModule(comm.ModuleUser); err != nil { return } this.ModuleUser = module.(comm.IUser) if module, err = this.service.GetModule(comm.ModuleItems); err != nil { return } this.ModuleItems = module.(comm.IItems) if module, err = this.service.GetModule(comm.ModuleHero); err != nil { return } this.ModuleHero = module.(comm.IHero) if module, err = this.service.GetModule(comm.ModuleEquipment); err != nil { return } this.ModuleEquipment = module.(comm.IEquipment) if module, err = this.service.GetModule(comm.ModuleTask); err != nil { return } this.ModuleTask = module.(comm.ITask) return } func (this *ModuleBase) GetUserSession(uid string) (session comm.IUserSession, ok bool) { var udata *pb.CacheUser if udata = this.ModuleUser.GetUserSession(uid); udata == nil { ok = false return } session = this.scomp.GetUserSession(udata) ok = true return } func (this *ModuleBase) PutUserSession(session comm.IUserSession) { session.Reset() this.scomp.PutUserSession(session) return } //向指定用户发送消息 func (this *ModuleBase) SendMsgToUser(mainType, subType string, msg proto.Message, user *pb.CacheUser) (err error) { session := this.scomp.GetUserSession(user) session.SendMsg(mainType, subType, msg) err = session.Push() this.scomp.PutUserSession(session) return } //向多个用户发送消息 func (this *ModuleBase) SendMsgToUsers(mainType, subType string, msg proto.Message, user ...*pb.CacheUser) (err error) { var ( gateways map[string]map[string][]string = make(map[string]map[string][]string) cluster map[string][]string gateway []string ok bool ) for _, v := range user { if cluster, ok = gateways[v.ServiceTag]; !ok { gateways[v.ServiceTag] = make(map[string][]string) } if gateway, ok = cluster[v.GatewayServiceId]; !ok { gateway = make([]string, 0) cluster[v.GatewayServiceId] = gateway } gateway = append(gateway, v.SessionId) } reply := &pb.RPCMessageReply{} data, _ := anypb.New(msg) for k, v := range gateways { for k1, v1 := range v { if _, err = this.service.AcrossClusterRpcGo(context.Background(), k1, fmt.Sprintf("%s/%s", comm.Service_Gateway, k), string(comm.Rpc_GatewayAgentSendMsg), &pb.BatchMessageReq{ UserSessionIds: v1, MainType: mainType, SubType: subType, Data: data, }, reply); err != nil { log.Errorf("SendMsgToUsers:%s.%s->%s.%s err:%v", k1, k, mainType, subType, err) } } } return } //校验消耗资源 func (this *ModuleBase) CheckConsumeRes(session comm.IUserSession, res []*cfg.Game_atn, bPush bool) (code pb.ErrorCode) { var ( err error resID int amount int32 ) source := &comm.ModuleCallSource{ Module: string(this.module.GetType()), FuncName: "CheckConsumeRes", Describe: "消耗资源", } //校验消费资源是否充足 for _, v := range res { if v.A == comm.AttrType { //用户属性资源 if amount = this.ModuleUser.QueryAttributeValue(session.GetUserId(), v.T); amount < v.N { code = pb.ErrorCode_ResNoEnough this.Errorf("道具不足:A:%s,T:%s,N:%d", v.A, v.T, v.N) return } } else if v.A == comm.ItemType { //道具资源 if resID, err = strconv.Atoi(v.T); err != nil { code = pb.ErrorCode_ConfigurationException return } if amount = int32(this.ModuleItems.QueryItemAmount(source, session.GetSessionId(), int32(resID))); amount < v.N { code = pb.ErrorCode_ResNoEnough this.Errorf("道具不足:A:%s,T:%s,N:%d", v.A, v.T, v.N) return } } // else if v.A == comm.HeroType { //卡片资源 // if resID, err = strconv.Atoi(v.T); err != nil { // code = pb.ErrorCode_ConfigurationException // return // } // if amount = int32(this.ModuleHero.QueryHeroAmount(uid, int32(resID))); amount < v.N { // code = pb.ErrorCode_ResNoEnough // return // } // } //不存在消耗武器的情况 // } else if v.A == comm.EquipmentType { // if resID, err = strconv.Atoi(v.T); err != nil { // code = pb.ErrorCode_ConfigurationException // return // } // if amount = int32(equipment.QueryEquipmentAmount(source, uid, int32(resID))); amount < v.N { // code = pb.ErrorCode_ResNoEnough // return // } // } } for _, v := range res { if v.A == comm.AttrType { //用户属性资源 this.ModuleUser.AddAttributeValue(session, v.T, -1*v.N, bPush) } else if v.A == comm.ItemType { //道具资源 resID, _ = strconv.Atoi(v.T) this.ModuleItems.AddItem(source, session, int32(resID), -1*v.N, bPush) } // else if v.A == comm.HeroType { //卡片资源 // resID, _ = strconv.Atoi(v.T) // this.ModuleHero.ConsumeCard(uid, int32(resID), -1*v.N) // } // } else if v.A == comm.EquipmentType { // resID, _ = strconv.Atoi(v.T) // equipment.AddNewEquipments(source, uid, resID, -1*v.N) // } } return } //发放资源 func (this *ModuleBase) DispenseRes(session comm.IUserSession, res []*cfg.Game_atn, bPush bool) (code pb.ErrorCode) { var ( resID int ) source := &comm.ModuleCallSource{ Module: string(this.module.GetType()), FuncName: "DispenseRes", Describe: "发放资源", } for _, v := range res { this.Debugf("发放资源 DispenseRes:A = %s, T:%s, N:%d", v.A, v.T, v.N) if v.A == comm.AttrType { //用户属性资源 code = this.ModuleUser.AddAttributeValue(session, v.T, v.N, bPush) } else if v.A == comm.ItemType { //道具资源 resID = cast.ToInt(v.T) // resID, _ = strconv.Atoi(v.T) code = this.ModuleItems.AddItem(source, session, int32(resID), v.N, bPush) } else if v.A == comm.HeroType { //卡片资源 resID, _ = strconv.Atoi(v.T) hero, err := this.ModuleHero.CreateRepeatHero(session.GetUserId(), int32(resID), v.N) if err != nil { code = pb.ErrorCode_HeroMaxCount } // 创建英雄成功 向客户端推送数据 session.SendMsg("hero", "addnewhero", &pb.HeroAddNewHeroPush{Hero: hero, Count: v.N}) // if bPush { // if session, ok := this.GetUserSession(uid); ok { // session.SendMsg("hero", "addnewhero", &pb.HeroAddNewHeroPush{Hero: hero, Count: v.N}) // err = session.Push() // } // } } else if v.A == comm.EquipmentType { resID, _ = strconv.Atoi(v.T) code = this.ModuleEquipment.AddNewEquipments(source, session, map[int32]uint32{int32(resID): uint32(v.N)}, bPush) } } return } //日志接口 func (this *ModuleBase) Debugf(format string, a ...interface{}) { if this.options.GetDebug() { this.options.GetLog().Debugf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...) } } func (this *ModuleBase) Infof(format string, a ...interface{}) { if this.options.GetDebug() { this.options.GetLog().Infof(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...) } } func (this *ModuleBase) Warnf(format string, a ...interface{}) { if this.options.GetDebug() { this.options.GetLog().Warnf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...) } } func (this *ModuleBase) Errorf(format string, a ...interface{}) { if this.options.GetLog() != nil { this.options.GetLog().Errorf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...) } } func (this *ModuleBase) Panicf(format string, a ...interface{}) { if this.options.GetLog() != nil { this.options.GetLog().Panicf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...) } } func (this *ModuleBase) Fatalf(format string, a ...interface{}) { if this.options.GetLog() != nil { this.options.GetLog().Fatalf(fmt.Sprintf("[Module:%s] ", this.module.GetType())+format, a...) } }