From 5bf13fe2037fe0b3253b146de2f6f5891e073dee Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Wed, 23 Aug 2023 16:14:10 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=9C=BA=E5=99=A8=E4=BA=BA?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- comm/const.go | 88 +++++------ modules/robot/client.go | 102 ++++++++++--- modules/robot/configure.go | 75 +++++++++ modules/robot/core.go | 48 ++++++ modules/robot/module.go | 33 ++-- modules/robot/modulerobot_user.go | 66 ++++++++ modules/robot/modulerobot_wtask.go | 238 +++++++++++++++++++++++++++++ modules/robot/options.go | 27 ++++ modules/robot/robot.go | 169 ++++++++++++++++++++ modules/robot/robotmgrcomp.go | 70 +++++++++ services/robot/main.go | 20 +-- 11 files changed, 846 insertions(+), 90 deletions(-) create mode 100644 modules/robot/configure.go create mode 100644 modules/robot/core.go create mode 100644 modules/robot/modulerobot_user.go create mode 100644 modules/robot/modulerobot_wtask.go create mode 100644 modules/robot/options.go create mode 100644 modules/robot/robot.go create mode 100644 modules/robot/robotmgrcomp.go diff --git a/comm/const.go b/comm/const.go index db2c32fd8..6b18eec87 100644 --- a/comm/const.go +++ b/comm/const.go @@ -103,6 +103,7 @@ const ( ModuleStoryLine core.M_Modules = "storyline" //剧情活动 ModulePushgiftbag core.M_Modules = "pushgiftbag" //推送礼包 ModulePuzzle core.M_Modules = "uigame" //小游戏 + ModuleRobot core.M_Modules = "robot" //压测机器人 ) // 数据表名定义处 @@ -644,49 +645,50 @@ const ( // 随机任务类型 const ( - Rtype1 TaskType = 1 //英雄指定 - Rtype2 TaskType = 2 //主线之内触发了剧情Id - Rtype3 TaskType = 3 //每日任务 - Rtype4 TaskType = 4 //指定英雄的等级限制 - Rtype5 TaskType = 5 //指定英雄的装备数量 - Rtype6 TaskType = 6 //指定英雄的星级 - Rtype7 TaskType = 7 //日常登录一次 - Rtype8 TaskType = 8 //累计登陆xx天 - Rtype9 TaskType = 9 //连续登陆xx天 - Rtype10 TaskType = 10 //拥有xx个好友 - Rtype11 TaskType = 11 //赠送X次友情点 - Rtype12 TaskType = 12 //使用好友助战英雄xx次 - Rtype13 TaskType = 13 //更换X次助战英雄 - Rtype14 TaskType = 14 //累计xx次普通招募 - Rtype15 TaskType = 15 //累计xx次阵营招募 - Rtype16 TaskType = 16 //招募获得xx品质英雄xx个 - Rtype17 TaskType = 17 //普通招募十连,获得xx个以上xx星英雄 - Rtype18 TaskType = 18 //xx次普通招募 - Rtype19 TaskType = 19 //xx次阵营招募 - Rtype20 TaskType = 20 //用户等级达到xx级 - Rtype21 TaskType = 21 //英雄合成xx次 - Rtype22 TaskType = 22 //合成xx英雄 - Rtype23 TaskType = 23 //拥有xx个xx星级的xx等级英雄 - Rtype24 TaskType = 24 //为任意英雄提升xx次等级 - Rtype25 TaskType = 25 //xx名xx英雄升至xx星 - Rtype26 TaskType = 26 //xx名英雄从三星升四星 - Rtype27 TaskType = 27 //xx名英雄从四星升五星 - Rtype28 TaskType = 28 //xx名英雄从五星升六星 - Rtype29 TaskType = 29 //拥有xx个xx级及以上的【xx】英雄 - Rtype30 TaskType = 30 //获得xx个品质为xx的英雄 - Rtype31 TaskType = 31 //获得xx个品质为xx以上的英雄 - Rtype32 TaskType = 32 //xx个品质为xx的英雄升到xx级 - Rtype33 TaskType = 33 //xx个品质为xx以及以上英雄升到xx级 - Rtype34 TaskType = 34 //xx个英雄觉醒达到xx阶段 - Rtype35 TaskType = 35 //xx英雄觉醒达到xx阶段 - Rtype36 TaskType = 36 //xx位xx品质xx职业英雄(xx阵营)觉醒达到xx阶段(检查满级,满共鸣,满觉醒的英雄数量,每有一个进度+1) - Rtype37 TaskType = 37 //xx名xx品质英雄 - Rtype38 TaskType = 38 //xx英雄满级 - Rtype39 TaskType = 39 //累计英雄共鸣xx次 - Rtype40 TaskType = 40 //将xx个英雄共鸣xx次 - Rtype41 TaskType = 41 //任意一名英雄穿戴xx件xx星级的装备 - Rtype42 TaskType = 42 //任意一名英雄穿戴xx件xx等级的装备 - Rtype43 TaskType = 43 //将xx件装备强化至xx级 + Rtype20001 TaskType = 20001 //对话埋点 前端主动完成 + Rtype1 TaskType = 1 //英雄指定 + Rtype2 TaskType = 2 //主线之内触发了剧情Id + Rtype3 TaskType = 3 //每日任务 + Rtype4 TaskType = 4 //指定英雄的等级限制 + Rtype5 TaskType = 5 //指定英雄的装备数量 + Rtype6 TaskType = 6 //指定英雄的星级 + Rtype7 TaskType = 7 //日常登录一次 + Rtype8 TaskType = 8 //累计登陆xx天 + Rtype9 TaskType = 9 //连续登陆xx天 + Rtype10 TaskType = 10 //拥有xx个好友 + Rtype11 TaskType = 11 //赠送X次友情点 + Rtype12 TaskType = 12 //使用好友助战英雄xx次 + Rtype13 TaskType = 13 //更换X次助战英雄 + Rtype14 TaskType = 14 //累计xx次普通招募 + Rtype15 TaskType = 15 //累计xx次阵营招募 + Rtype16 TaskType = 16 //招募获得xx品质英雄xx个 + Rtype17 TaskType = 17 //普通招募十连,获得xx个以上xx星英雄 + Rtype18 TaskType = 18 //xx次普通招募 + Rtype19 TaskType = 19 //xx次阵营招募 + Rtype20 TaskType = 20 //用户等级达到xx级 + Rtype21 TaskType = 21 //英雄合成xx次 + Rtype22 TaskType = 22 //合成xx英雄 + Rtype23 TaskType = 23 //拥有xx个xx星级的xx等级英雄 + Rtype24 TaskType = 24 //为任意英雄提升xx次等级 + Rtype25 TaskType = 25 //xx名xx英雄升至xx星 + Rtype26 TaskType = 26 //xx名英雄从三星升四星 + Rtype27 TaskType = 27 //xx名英雄从四星升五星 + Rtype28 TaskType = 28 //xx名英雄从五星升六星 + Rtype29 TaskType = 29 //拥有xx个xx级及以上的【xx】英雄 + Rtype30 TaskType = 30 //获得xx个品质为xx的英雄 + Rtype31 TaskType = 31 //获得xx个品质为xx以上的英雄 + Rtype32 TaskType = 32 //xx个品质为xx的英雄升到xx级 + Rtype33 TaskType = 33 //xx个品质为xx以及以上英雄升到xx级 + Rtype34 TaskType = 34 //xx个英雄觉醒达到xx阶段 + Rtype35 TaskType = 35 //xx英雄觉醒达到xx阶段 + Rtype36 TaskType = 36 //xx位xx品质xx职业英雄(xx阵营)觉醒达到xx阶段(检查满级,满共鸣,满觉醒的英雄数量,每有一个进度+1) + Rtype37 TaskType = 37 //xx名xx品质英雄 + Rtype38 TaskType = 38 //xx英雄满级 + Rtype39 TaskType = 39 //累计英雄共鸣xx次 + Rtype40 TaskType = 40 //将xx个英雄共鸣xx次 + Rtype41 TaskType = 41 //任意一名英雄穿戴xx件xx星级的装备 + Rtype42 TaskType = 42 //任意一名英雄穿戴xx件xx等级的装备 + Rtype43 TaskType = 43 //将xx件装备强化至xx级 // Rtype44 TaskType = 44 //任意装备强化到xx级 合并到43 Rtype45 TaskType = 45 //将xx件xx星【xx】套装装备强化至xx级 Rtype46 TaskType = 46 //为xx名英雄穿戴完整xx星【xx】套装装备 diff --git a/modules/robot/client.go b/modules/robot/client.go index 7184abe87..112b487e5 100644 --- a/modules/robot/client.go +++ b/modules/robot/client.go @@ -1,22 +1,42 @@ package robot import ( - "go_dreamfactory/lego/sys/log" "go_dreamfactory/pb" "sync" "sync/atomic" + "time" "github.com/gorilla/websocket" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" ) type Client struct { - sessionId string - uId string - wsConn *websocket.Conn - state int32 //状态 0 关闭 1 运行 2 关闭中 - closeSignal chan bool - wg sync.WaitGroup + client IClient + wsConn *websocket.Conn + writeChan chan []byte + state int32 //状态 0 关闭 1 运行 2 关闭中 + closeSignal chan bool + wg sync.WaitGroup + account, sid string +} + +func (this *Client) Init(addr string, client IClient) (err error) { + var ( + comm *websocket.Conn + ) + if comm, _, err = websocket.DefaultDialer.Dial(addr, nil); err != nil { + return + } + this.client = client + this.state = 1 + this.writeChan = make(chan []byte, 2) + this.closeSignal = make(chan bool) + this.wsConn = comm + this.wg.Add(2) + go this.readLoop() + go this.writeLoop() + return } func (this *Client) readLoop() { @@ -29,24 +49,56 @@ func (this *Client) readLoop() { locp: for { if _, data, err = this.wsConn.ReadMessage(); err != nil { - log.Errorf("agent:%s uId:%s ReadMessage err:%v", this.sessionId, this.uId, err) - go this.Close() + go this.client.Close() break locp } if err = proto.Unmarshal(data, msg); err != nil { - log.Errorf("agent:%s uId:%s Unmarshal err:%v", this.sessionId, this.uId, err) - go this.Close() + go this.client.Close() break locp } else { // this.gateway.Debugf("----------2 agent:%s uId:%s MainType:%s SubType:%s ", this.sessionId, this.uId, msg.MainType, msg.SubType) - if err = this.messageDistribution(msg); err != nil { - break locp - } - + this.client.Receive(msg) } } - log.Debugf("agent:%s uId:%s readLoop end!", this.sessionId, this.uId) +} +func (this *Client) writeLoop() { + defer this.wg.Done() + var ( + err error + timer *time.Ticker + ) + timer = time.NewTicker(time.Second * 30) +locp: + for { + select { + case <-this.closeSignal: + break locp + case msg, ok := <-this.writeChan: + if ok { + if err = this.wsConn.WriteMessage(websocket.BinaryMessage, msg); err != nil { + go this.client.Close() + } + } else { + go this.client.Close() + } + case <-timer.C: + this.client.Heartbeat() + } + } +} +func (this *Client) WriteMsg(msg *pb.UserMessage) (err error) { + if atomic.LoadInt32(&this.state) != 1 { + return + } + var ( + data []byte + ) + + if data, err = proto.Marshal(msg); err == nil { + this.writeChan <- data + } + return } // 外部代用关闭 @@ -58,10 +110,26 @@ func (this *Client) Close() { this.closeSignal <- true this.wg.Wait() atomic.StoreInt32(&this.state, 0) + this.client.OnClose() } // 分发用户消息 -func (this *Client) messageDistribution(msg *pb.UserMessage) (err error) { +func (this *Client) Receive(msg *pb.UserMessage) (err error) { return } +func (this *Client) SendMessage(mtype, stype string, msg proto.Message) (err error) { + data, _ := anypb.New(msg) + message := &pb.UserMessage{ + MainType: mtype, + SubType: stype, + Data: data, + } + + err = this.WriteMsg(message) + return +} + +func (this *Client) Heartbeat() { + +} diff --git a/modules/robot/configure.go b/modules/robot/configure.go new file mode 100644 index 000000000..e5771bae7 --- /dev/null +++ b/modules/robot/configure.go @@ -0,0 +1,75 @@ +package robot + +import ( + "go_dreamfactory/comm" + "go_dreamfactory/lego/core" + "go_dreamfactory/lego/core/cbase" + "go_dreamfactory/lego/sys/log" + "go_dreamfactory/sys/configure" + cfg "go_dreamfactory/sys/configure/structs" +) + +const ( + gameWorldTask = "game_worldtask.json" + gameWorldtaskBattle = "game_worldbattle.json" + game_buriedcondi = "game_buriedcondi.json" + // gameWorldAll = "game_worldall.json" + // gameburiedCond = "game_buriedcondi.json" + // gamerdtasknpc = "game_rdtasknpc.json" + // gamesearchitemall = "game_searchitemall.json" + // gamesearchitembox = "game_searchitembox.json" + // game_worlddeal = "game_worlddeal.json" + // game_worldrd = "game_worldrd.json" +) + +type configureComp struct { + cbase.ModuleCompBase + module *RobotModule +} + +func (this *configureComp) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) { + err = this.ModuleCompBase.Init(service, module, comp, options) + this.module = module.(*RobotModule) + configure.RegisterConfigure(gameWorldTask, cfg.NewGameWorldTask, nil) + configure.RegisterConfigure(gameWorldtaskBattle, cfg.NewGameWorldBattle, nil) + configure.RegisterConfigure(game_buriedcondi, cfg.NewGameBuriedCondi, nil) + return +} + +//获取任务配置 +func (this *configureComp) getGameWorldTaskData(tid int32) (conf *cfg.GameWorldTaskData, err error) { + + var ( + v interface{} + ok bool + ) + if v, err = configure.GetConfigure(gameWorldTask); err != nil { + return + } else { + if conf, ok = v.(*cfg.GameWorldTask).GetDataMap()[tid]; !ok { + err = comm.NewNotFoundConfErr(string(this.module.GetType()), gameWorldTask, tid) + log.Errorf("err:%v", err) + return + } + } + return +} + +//获取战斗配置 +func (this *configureComp) getGameWorldBattleData(confId int32) (conf *cfg.GameWorldBattleData, err error) { + + var ( + v interface{} + ok bool + ) + if v, err = configure.GetConfigure(gameWorldtaskBattle); err != nil { + return + } else { + if conf, ok = v.(*cfg.GameWorldBattle).GetDataMap()[confId]; !ok { + err = comm.NewNotFoundConfErr(string(this.module.GetType()), gameWorldtaskBattle, confId) + log.Errorf("err:%v", err) + return + } + } + return +} diff --git a/modules/robot/core.go b/modules/robot/core.go new file mode 100644 index 000000000..51c9cbca8 --- /dev/null +++ b/modules/robot/core.go @@ -0,0 +1,48 @@ +package robot + +import ( + "go_dreamfactory/lego/core" + "go_dreamfactory/pb" + cfg "go_dreamfactory/sys/configure/structs" + + "google.golang.org/protobuf/proto" +) + +//客户端端 +type IClient interface { + Init(addr string, client IClient) (err error) + Heartbeat() + Receive(msg *pb.UserMessage) (err error) + WriteMsg(msg *pb.UserMessage) (err error) + SendMessage(mtype, stype string, msg proto.Message) (err error) + Close() + OnClose() +} + +//机器人 +type IRobot interface { + IClient + Account() string + ServerId() string + SetData(key string, data interface{}) + GetData(key string) interface{} + DoTask(taskconf *cfg.GameWorldTaskData, condconf *cfg.GameBuriedCondiData, module core.M_Modules) (err error) +} + +//机器人模块 +type IModuleRobot interface { + //接收到回应和推送消息 + Receive(robot IRobot, stype string, message proto.Message) (err error) + //错误码接收 + ErrReceive(robot IRobot, stype string, code pb.ErrorCode) (err error) + //执行流水线任务 + DoPipeline(robot IRobot) (err error) + //执行任务 + DoTask(robot IRobot, taskconf *cfg.GameWorldTaskData, condconf *cfg.GameBuriedCondiData) (err error) +} + +type SecBuild struct { + Account string `json:"account"` + ServerId string `json:"serverId"` + TimeStamp int64 `json:"timestamp"` +} diff --git a/modules/robot/module.go b/modules/robot/module.go index b95529f8c..ce2a0c6f2 100644 --- a/modules/robot/module.go +++ b/modules/robot/module.go @@ -4,7 +4,7 @@ import ( "go_dreamfactory/comm" "go_dreamfactory/lego/base" "go_dreamfactory/lego/core" - "go_dreamfactory/modules" + "go_dreamfactory/lego/core/cbase" ) /* @@ -13,34 +13,43 @@ import ( 开发:李伟 */ func NewModule() core.IModule { - m := new(Reddot) + m := new(RobotModule) return m } -type Reddot struct { - modules.ModuleBase - service base.IRPCXService +type RobotModule struct { + cbase.ModuleBase + options *Options + service base.IRPCXService + robotmgr *robotmgrComp + configure *configureComp } // 模块名 -func (this *Reddot) GetType() core.M_Modules { - return comm.ModuleReddot +func (this *RobotModule) GetType() core.M_Modules { + return comm.ModuleRobot +} + +// 重构模块配置对象 +func (this *RobotModule) NewOptions() (options core.IModuleOptions) { + return new(Options) } // 模块初始化接口 注册用户创建角色事件 -func (this *Reddot) Init(service core.IService, module core.IModule, options core.IModuleOptions) (err error) { +func (this *RobotModule) Init(service core.IService, module core.IModule, options core.IModuleOptions) (err error) { err = this.ModuleBase.Init(service, module, options) + this.options = options.(*Options) this.service = service.(base.IRPCXService) return } -func (this *Reddot) Start() (err error) { +func (this *RobotModule) Start() (err error) { err = this.ModuleBase.Start() - return } // 装备组件 -func (this *Reddot) OnInstallComp() { +func (this *RobotModule) OnInstallComp() { this.ModuleBase.OnInstallComp() - + this.configure = this.RegisterComp(new(configureComp)).(*configureComp) + this.robotmgr = this.RegisterComp(new(robotmgrComp)).(*robotmgrComp) } diff --git a/modules/robot/modulerobot_user.go b/modules/robot/modulerobot_user.go new file mode 100644 index 000000000..31a54142f --- /dev/null +++ b/modules/robot/modulerobot_user.go @@ -0,0 +1,66 @@ +package robot + +import ( + "fmt" + "go_dreamfactory/pb" + cfg "go_dreamfactory/sys/configure/structs" + + "google.golang.org/protobuf/proto" +) + +//用户模块 机器人 +type ModuleRobot_User struct { +} + +//接收到消息 +func (this *ModuleRobot_User) Receive(robot IRobot, stype string, message proto.Message) (err error) { + switch stype { + case "login": + resp := message.(*pb.UserLoginResp) + robot.SetData("user", resp.Data) + robot.SetData("userex", resp.Ex) + break + case "create": + // resp := message.(*pb.UserCreateResp) + break + } + return +} + +//接收到消息 +func (this *ModuleRobot_User) ErrReceive(robot IRobot, stype string, code pb.ErrorCode) (err error) { + switch stype { + case "login": + err = fmt.Errorf("登录错误:%d", code) + break + case "create": + break + } + return +} + +//机器人执行流 +func (this *ModuleRobot_User) DoPipeline(robot IRobot) (err error) { + //登录 + if err = robot.SendMessage("user", "login", &pb.UserLoginReq{ + Account: robot.Account(), + Sid: robot.ServerId(), + }); err != nil { + return + } + //创角 + if err = robot.SendMessage("user", "create", &pb.UserCreateReq{ + NickName: robot.Account(), + Figure: 100, + Gender: 1, + }); err != nil { + return + } + return +} + +//做任务 +func (this *ModuleRobot_User) DoTask(robot IRobot, taskconf *cfg.GameWorldTaskData, condconf *cfg.GameBuriedCondiData) (err error) { + + return +} diff --git a/modules/robot/modulerobot_wtask.go b/modules/robot/modulerobot_wtask.go new file mode 100644 index 000000000..42a71ee1b --- /dev/null +++ b/modules/robot/modulerobot_wtask.go @@ -0,0 +1,238 @@ +package robot + +import ( + "fmt" + "go_dreamfactory/comm" + "go_dreamfactory/lego/core" + "go_dreamfactory/lego/sys/log" + "go_dreamfactory/pb" + "go_dreamfactory/sys/configure" + cfg "go_dreamfactory/sys/configure/structs" + + "google.golang.org/protobuf/proto" +) + +//用户模块 机器人 +type ModuleRobot_WTask struct { + info *pb.DBWTask + progress []*pb.DBWTaskItem //任务进度 +} + +//接收到消息 +func (this *ModuleRobot_WTask) Receive(robot IRobot, stype string, message proto.Message) (err error) { + switch stype { + case "info": + resp := message.(*pb.WTaskInfoResp) + this.info = resp.Info + this.progress = resp.Accepts + break + case "accept": + resp := message.(*pb.WTaskAcceptResp) + this.progress = resp.Accepts + if this.info != nil { + this.info.Activations = resp.Activations + this.info.Accepts = make([]int32, 0) + for _, v := range this.progress { + this.info.Accepts = append(this.info.Accepts, v.Tid) + } + } + break + case "completecondi": + resp := message.(*pb.WTaskCompleteCondiResp) + for i, v := range this.progress { + if v.Tid == resp.TaskId { + this.progress[i] = resp.Progress + break + } + } + break + case "finish": + resp := message.(*pb.WTaskFinishResp) + for i, v := range this.info.Accepts { + if v == resp.Tid { + this.info.Accepts = append(this.info.Accepts[0:i], this.info.Accepts[i+1:]...) + } + } + break + case "activationschange": + resp := message.(*pb.WTaskActivationsChangePush) + if this.info != nil { + this.info.Activations = resp.Activations + } + break + case "acceptchange": + resp := message.(*pb.WTaskAcceptChangePush) + this.progress = resp.Accepts + if this.info != nil { + this.info.Accepts = make([]int32, 0) + for _, v := range this.progress { + this.info.Accepts = append(this.info.Accepts, v.Tid) + } + } + break + } + return +} + +//接收到消息 +func (this *ModuleRobot_WTask) ErrReceive(robot IRobot, stype string, code pb.ErrorCode) (err error) { + switch stype { + case "info": + err = fmt.Errorf("信息获取:%d", code) + break + } + return +} + +//机器人执行流 +func (this *ModuleRobot_WTask) DoPipeline(robot IRobot) (err error) { + //获取任务列表 + if err = robot.SendMessage("wtask", "info", &pb.WTaskInfoReq{}); err != nil { + return + } + var ( + tconf *cfg.GameWorldTaskData + cconf *cfg.GameBuriedCondiData + module core.M_Modules + ) +locp: + for { + //寻找可做任务 + tconf = this.findtask() + if tconf == nil { + break locp + } + if this.checkaccept(tconf) { //是否需要接收任务 + if err = robot.SendMessage("wtask", "accept", &pb.WTaskAcceptReq{Tid: tconf.Key}); err != nil { + return + } + continue + } + //找到能做的任务 + cconf, err = this.findconlds(tconf) + if err != nil { + break locp + } + //有问完成的子任务 + if cconf != nil { + switch comm.TaskType(cconf.Type) { + case comm.Rtype1: + module = comm.ModuleHero + case comm.Rtype20001: + module = comm.ModuleWtask + default: + log.Error("[Robot DoTask]", log.Field{Key: "ctype", Value: cconf.Type}, log.Field{Key: "conld", Value: cconf.Id}, log.Field{Key: "err", Value: "Not Achieved !"}) + break locp + } + if err = robot.DoTask(tconf, cconf, module); err != nil { + log.Error("[Robot DoTask]", log.Field{Key: "task", Value: tconf.Key}, log.Field{Key: "conld", Value: cconf.Id}, log.Field{Key: "err", Value: err.Error()}) + break locp + } + continue + } else { //任务已完成直接完成 + if err = robot.SendMessage("wtask", "finish", &pb.WTaskFinishReq{Tid: tconf.Key}); err != nil { + return + } + } + } + return +} + +//做任务 +func (this *ModuleRobot_WTask) DoTask(robot IRobot, taskconf *cfg.GameWorldTaskData, condconf *cfg.GameBuriedCondiData) (err error) { + switch comm.TaskType(condconf.Type) { + case comm.Rtype20001: + if err = robot.SendMessage("wtask", "completecondi", &pb.WTaskCompleteCondiReq{TaskId: taskconf.Key, CondiId: condconf.Id}); err != nil { + return + } + break + } + return +} + +func (this *ModuleRobot_WTask) findtask() (conf *cfg.GameWorldTaskData) { + var ( + confs []*cfg.GameWorldTaskData + err error + ) + for _, v := range this.info.Accepts { + if conf, err = this.getGameWorldTaskData(v); err != nil { + log.Error("[Robot 世界任务配置未找到]", log.Field{Key: "task", Value: v}, log.Field{Key: "err", Value: err.Error()}) + } + if conf.Des == 2 { //优先找到主线任务 + return + } + confs = append(confs, conf) + } + + for _, v := range this.info.Activations { //可接取任务列表 + if conf, err = this.getGameWorldTaskData(v); err != nil { + log.Error("[Robot 世界任务配置未找到]", log.Field{Key: "task", Value: v}, log.Field{Key: "err", Value: err.Error()}) + } + if conf.Des == 2 { //优先找到主线任务 + return + } + } + + return +} + +func (this *ModuleRobot_WTask) findconlds(conf *cfg.GameWorldTaskData) (cconf *cfg.GameBuriedCondiData, err error) { + for _, tp := range this.progress { + if tp.Tid == conf.Key { + for _, v := range tp.Conlds { + if v.State == pb.BuriedItemFinishState_buried_unfinish { //未完成 + if cconf, err = this.getburiedcondidata(v.Conid); err != nil { + log.Error("[Robot 埋点任务配置未找到]", log.Field{Key: "conld", Value: v.Conid}, log.Field{Key: "err", Value: err.Error()}) + return + } + return + } + } + } + } + return +} + +func (this *ModuleRobot_WTask) checkaccept(conf *cfg.GameWorldTaskData) bool { + for _, v := range this.info.Accepts { + if v == conf.Key { + return false + } + } + return true +} + +//获取任务配置 +func (this *ModuleRobot_WTask) getGameWorldTaskData(tid int32) (conf *cfg.GameWorldTaskData, err error) { + var ( + v interface{} + ok bool + ) + if v, err = configure.GetConfigure(gameWorldTask); err != nil { + return + } else { + if conf, ok = v.(*cfg.GameWorldTask).GetDataMap()[tid]; !ok { + err = comm.NewNotFoundConfErr("robot", gameWorldTask, tid) + return + } + } + return +} + +// 读取条件任务id配置 +func (this *ModuleRobot_WTask) getburiedcondidata(cid int32) (conf *cfg.GameBuriedCondiData, err error) { + var ( + v interface{} + ok bool + ) + if v, err = configure.GetConfigure(game_buriedcondi); err != nil { + return + } else { + if conf, ok = v.(*cfg.GameBuriedCondi).GetDataMap()[cid]; !ok { + err = comm.NewNotFoundConfErr("robot", game_buriedcondi, cid) + return + } + } + return +} diff --git a/modules/robot/options.go b/modules/robot/options.go new file mode 100644 index 000000000..9cc4c8e6d --- /dev/null +++ b/modules/robot/options.go @@ -0,0 +1,27 @@ +package robot + +import ( + "go_dreamfactory/lego/utils/mapstructure" + "go_dreamfactory/modules" +) + +type ( + Options struct { + modules.Options + ServerAddr string //服务地址 + RobotTotalNum int32 //机器人总数 + RobotSingleNum int32 //单词机器人进入数量 + Intervals int32 //间隔时间 单位秒 + Pipeline []string //执行流水线 + } +) + +func (this *Options) LoadConfig(settings map[string]interface{}) (err error) { + if settings != nil { + if err = this.Options.LoadConfig(settings); err != nil { + return + } + err = mapstructure.Decode(settings, this) + } + return +} diff --git a/modules/robot/robot.go b/modules/robot/robot.go new file mode 100644 index 000000000..a76473a4e --- /dev/null +++ b/modules/robot/robot.go @@ -0,0 +1,169 @@ +package robot + +import ( + "fmt" + "go_dreamfactory/comm" + "go_dreamfactory/lego/core" + "go_dreamfactory/lego/sys/log" + "go_dreamfactory/pb" + cfg "go_dreamfactory/sys/configure/structs" + "go_dreamfactory/utils" + "time" + + jsoniter "github.com/json-iterator/go" + "github.com/nacos-group/nacos-sdk-go/util" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" +) + +type Robot struct { + Client + index int32 //编号 + account, serverId string + curreq string //当前请求 + await chan string + modules map[core.M_Modules]IModuleRobot + datas map[string]interface{} + pipeline []string //执行流水线 +} + +func (this *Robot) Account() string { + return this.account +} + +func (this *Robot) ServerId() string { + return this.serverId +} +func (this *Robot) SetData(key string, data interface{}) { + this.datas[key] = data +} +func (this *Robot) GetData(key string) interface{} { + return this.datas[key] +} + +//初始化 +func (this *Robot) Init(addr string, client IClient) (err error) { + this.Client.Init(addr, client) + this.datas = make(map[string]interface{}) + this.await = make(chan string) + this.modules = make(map[core.M_Modules]IModuleRobot) + this.modules[comm.ModuleUser] = new(ModuleRobot_User) + this.modules[comm.ModuleWtask] = new(ModuleRobot_WTask) + go this.run() + return +} + +//接收消息 +func (this *Robot) Receive(msg *pb.UserMessage) (err error) { + var ( + msgpath string + message proto.Message + module IModuleRobot + ok bool + ) + msgpath = fmt.Sprintf("%s.%s", msg.MainType, msg.SubType) + + if msgpath == "gateway.heartbeat" { //心跳 屏蔽掉 + return + } + // log.Debug("[机器人 Resp]", log.Field{Key: "Account", Value: this.account}, log.Field{Key: "message", Value: msgpath}) + //序列化用户消息对象 + if message, err = msg.Data.UnmarshalNew(); err != nil { + log.Errorf("[Robot Receive] UserMessage:%s Unmarshal err:%v", msgpath, err) + return err + } + if msgpath == "notify.errornotify" { //错误通知 + req := message.(*pb.NotifyErrorNotifyPush) + reqpath := fmt.Sprintf("%s.%s", req.ReqMainType, req.ReqSubType) + if module, ok = this.modules[core.M_Modules(req.ReqMainType)]; ok { + if err = module.ErrReceive(this, req.ReqSubType, req.Code); err != nil { + log.Error("[Robot NotifyErrorNotifyPush]", log.Field{Key: "Account", Value: this.account}, log.Field{Key: "message", Value: reqpath}, log.Field{Key: "err", Value: err.Error()}) + return + } + } + if reqpath == this.curreq { //收到回应 + this.await <- msgpath + } + return + } + if module, ok = this.modules[core.M_Modules(msg.MainType)]; ok { + module.Receive(this, msg.SubType, message) + } else { + // log.Errorf("[Robot Receive] no register module:%s", msg.MainType) + return + } + + if msgpath == this.curreq { //收到回应 + this.await <- msgpath + } + return +} + +func (this *Robot) WriteMsg(msg *pb.UserMessage) (err error) { + msg.Sec = this.buildSecStr() + return this.Client.WriteMsg(msg) +} + +//发送消息 +func (this *Robot) SendMessage(mtype, stype string, msg proto.Message) (err error) { + stime := time.Now() + data, _ := anypb.New(msg) + message := &pb.UserMessage{ + MainType: mtype, + SubType: stype, + Data: data, + } + err = this.WriteMsg(message) + if mtype != "gateway" { + this.curreq = fmt.Sprintf("%s.%s", mtype, stype) + <-this.await //等待回应 + log.Debug("[机器人 Message]", log.Field{Key: "t", Value: time.Since(stime).Milliseconds()}, log.Field{Key: "Account", Value: this.account}, log.Field{Key: "message", Value: fmt.Sprintf("%s.%s", mtype, stype)}) + } + return +} + +func (this *Robot) buildSecStr() string { + jsonByte, _ := jsoniter.Marshal(&SecBuild{ + Account: this.account, + ServerId: this.serverId, + TimeStamp: time.Now().Unix(), + }) + jsonBase64 := utils.Base64Encode(jsonByte) + // log.Printf("client base64:%s", jsonBase64) + clientMd5key := util.Md5(jsonBase64) + // log.Printf("client md5:%s", clientMd5key) + return fmt.Sprintf("CE:%s%s", clientMd5key, jsonBase64) +} +func (this *Robot) Heartbeat() { + this.SendMessage("gateway", "heartbeat", &pb.GatewayHeartbeatReq{}) +} + +func (this *Robot) OnClose() { + log.Debug("[机器人 End]", log.Field{Key: "Account", Value: this.account}) +} + +func (this *Robot) DoTask(taskconf *cfg.GameWorldTaskData, condconf *cfg.GameBuriedCondiData, moduleStr core.M_Modules) (err error) { + var ( + ok bool + module IModuleRobot + ) + if module, ok = this.modules[moduleStr]; ok { + err = module.DoTask(this, taskconf, condconf) + } else { + err = fmt.Errorf("no fund module:%s", moduleStr) + return + } + return +} + +//运行 +func (this *Robot) run() { + var ( + module IModuleRobot + ) + for _, v := range this.pipeline { + module = this.modules[core.M_Modules(v)] + module.DoPipeline(this) + } + this.Close() +} diff --git a/modules/robot/robotmgrcomp.go b/modules/robot/robotmgrcomp.go new file mode 100644 index 000000000..d76862a91 --- /dev/null +++ b/modules/robot/robotmgrcomp.go @@ -0,0 +1,70 @@ +package robot + +import ( + "fmt" + "go_dreamfactory/lego/core" + "go_dreamfactory/lego/core/cbase" + "go_dreamfactory/lego/sys/log" + "time" +) + +/* +客户端管理组件 +*/ +type robotmgrComp struct { + cbase.ModuleCompBase + service core.IService + module *RobotModule + currRobotNum int32 +} + +//组件初始化接口 +func (this *robotmgrComp) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) { + this.ModuleCompBase.Init(service, module, comp, options) + this.module = module.(*RobotModule) + this.service = service + return +} + +func (this *robotmgrComp) Start() (err error) { + err = this.ModuleCompBase.Start() + go this.run() + return +} + +func (this *robotmgrComp) run() { + timer := time.NewTicker(time.Second) + defer timer.Stop() +locp: + for { + select { + case <-timer.C: + if this.currRobotNum <= this.module.options.RobotSingleNum { + for i := 0; i < int(this.module.options.RobotSingleNum); i++ { + this.createRobot(this.currRobotNum) + this.currRobotNum++ + } + } else { + break locp + } + } + } +} + +func (this *robotmgrComp) createRobot(index int32) { + var ( + robot *Robot + err error + ) + robot = &Robot{ + index: index, + account: fmt.Sprintf("test%d", index), + serverId: "df01", + pipeline: this.module.options.Pipeline, + } + if err = robot.Init(this.module.options.ServerAddr, robot); err != nil { + log.Errorln(err) + return + } + return +} diff --git a/services/robot/main.go b/services/robot/main.go index 44d1b8f4b..c0424bbb0 100644 --- a/services/robot/main.go +++ b/services/robot/main.go @@ -2,15 +2,12 @@ package main import ( "flag" - "fmt" + "go_dreamfactory/modules/robot" "go_dreamfactory/services" - "go_dreamfactory/sys/db" "go_dreamfactory/lego" "go_dreamfactory/lego/base/rpcx" "go_dreamfactory/lego/core" - "go_dreamfactory/lego/sys/cron" - "go_dreamfactory/lego/sys/log" ) /* @@ -31,7 +28,7 @@ func main() { s.OnInstallComp( //装备组件 //services.NewGateRouteComp(), //此服务需要接受用户的消息 需要装备网关组件 ) - lego.Run(s) //运行模块 + lego.Run(s, robot.NewModule()) //运行模块 } @@ -49,17 +46,4 @@ type Service struct { // 初始化worker需要的一些系统工具 func (this *Service) InitSys() { this.ServiceBase.InitSys() - - //定时系统 - if err := cron.OnInit(nil); err != nil { - panic(fmt.Sprintf("init sys.cron err: %s", err.Error())) - } else { - log.Infof("init sys.cron success!") - } - //存储系统 - if err := db.OnInit(this.GetSettings().Sys["db"]); err != nil { - panic(fmt.Sprintf("init sys.db err: %s", err.Error())) - } else { - log.Infof("init sys.db success!") - } }