diff --git a/bin/robot.txt b/bin/robot.txt new file mode 100644 index 000000000..ddec176fa --- /dev/null +++ b/bin/robot.txt @@ -0,0 +1,23 @@ +机器人总数: 1 +成功数量: 1 +失败数量: 0 +消息总吞吐量: 46 +---消息压测详情---------------------------------------------------------------------------------------------------- +消息名:wtask.accept 请求次数:12 耗时最小:1 ms 耗时最大:5 ms 平均耗时:2.83 ms 中位耗时:3.00 ms +消息名:wtask.completecondi 请求次数:3 耗时最小:1 ms 耗时最大:5 ms 平均耗时:3.67 ms 中位耗时:5.00 ms +消息名:wtask.finish 请求次数:10 耗时最小:2 ms 耗时最大:19 ms 平均耗时:8.40 ms 中位耗时:9.00 ms +消息名:practice.practice 请求次数:1 耗时最小:6 ms 耗时最大:6 ms 平均耗时:6.00 ms 中位耗时:6.00 ms +消息名:mainline.info 请求次数:1 耗时最小:5 ms 耗时最大:5 ms 平均耗时:5.00 ms 中位耗时:5.00 ms +消息名:sys.funcgetlist 请求次数:1 耗时最小:21 ms 耗时最大:21 ms 平均耗时:21.00ms 中位耗时:21.00ms +消息名:equipment.getlist 请求次数:1 耗时最小:0 ms 耗时最大:0 ms 平均耗时:0.00 ms 中位耗时:0.00 ms +消息名:wtask.info 请求次数:1 耗时最小:0 ms 耗时最大:0 ms 平均耗时:0.00 ms 中位耗时:0.00 ms +消息名:wtask.battlefinish 请求次数:4 耗时最小:1 ms 耗时最大:9 ms 平均耗时:3.50 ms 中位耗时:2.00 ms +消息名:practice.info 请求次数:1 耗时最小:8 ms 耗时最大:8 ms 平均耗时:8.00 ms 中位耗时:8.00 ms +消息名:user.login 请求次数:1 耗时最小:586 ms 耗时最大:586 ms 平均耗时:586.00ms 中位耗时:586.00ms +消息名:user.create 请求次数:1 耗时最小:16 ms 耗时最大:16 ms 平均耗时:16.00ms 中位耗时:16.00ms +消息名:items.getlist 请求次数:1 耗时最小:0 ms 耗时最大:0 ms 平均耗时:0.00 ms 中位耗时:0.00 ms +消息名:sys.funcactivate 请求次数:1 耗时最小:3 ms 耗时最大:3 ms 平均耗时:3.00 ms 中位耗时:3.00 ms +消息名:hero.list 请求次数:1 耗时最小:1 ms 耗时最大:1 ms 平均耗时:1.00 ms 中位耗时:1.00 ms +消息名:hero.talentlist 请求次数:1 耗时最小:0 ms 耗时最大:0 ms 平均耗时:0.00 ms 中位耗时:0.00 ms +消息名:wtask.battlestart 请求次数:4 耗时最小:1 ms 耗时最大:4 ms 平均耗时:2.25 ms 中位耗时:2.00 ms +消息名:hero.drawcard 请求次数:1 耗时最小:15 ms 耗时最大:15 ms 平均耗时:15.00ms 中位耗时:15.00ms diff --git a/lego/sys/rpcx/client.go b/lego/sys/rpcx/client.go index d6e888d03..b10af1153 100644 --- a/lego/sys/rpcx/client.go +++ b/lego/sys/rpcx/client.go @@ -333,16 +333,16 @@ func (this *Client) getclient(ctx *context.Context, clusterTag string, servicePa if d, err = client.NewConsulDiscovery(clusterTag, spath[0], this.options.ConsulServers, nil); err != nil { return } - c = client.NewBidirectionalXClient(spath[0], client.Failfast, client.RandomSelect, d, client.DefaultOption, this.msgChan) + c = client.NewBidirectionalXClient(spath[0], client.Failfast, client.RoundRobin, d, client.DefaultOption, this.msgChan) cluster.Mu.Lock() cluster.clients[spath[0]] = c cluster.Mu.Unlock() c.GetPlugins().Add(this) - if this.options.RpcxStartType == RpcxStartByClient && this.options.AutoConnect { - c.SetSelector(newSelector(this.options.Log, clusterTag, this.UpdateServer)) - } else { - c.SetSelector(newSelector(this.options.Log, clusterTag, nil)) - } + // if this.options.RpcxStartType == RpcxStartByClient && this.options.AutoConnect { + c.SetSelector(newSelector(this.options.Log, clusterTag, this.UpdateServer)) + // } else { + // c.SetSelector(newSelector(this.options.Log, clusterTag, nil)) + // } } *ctx = context.WithValue(*ctx, share.ReqMetaDataKey, map[string]string{ diff --git a/lego/sys/rpcx/selector.go b/lego/sys/rpcx/selector.go index 363ae7de6..7023ba4e5 100644 --- a/lego/sys/rpcx/selector.go +++ b/lego/sys/rpcx/selector.go @@ -103,11 +103,11 @@ func (this *Selector) UpdateServer(servers map[string]string) { continue } else { ss[node.ServiceId] = node - if ssts, ok := sst[node.ServiceType]; !ok { + if _, ok := sst[node.ServiceType]; !ok { sst[node.ServiceType] = make([]*ServiceNode, 0) sst[node.ServiceType] = append(sst[node.ServiceType], node) } else { - ssts = append(ssts, node) + sst[node.ServiceType] = append(sst[node.ServiceType], node) } } diff --git a/modules/robot/core.go b/modules/robot/core.go index 2e86fc0eb..5ee0a8edb 100644 --- a/modules/robot/core.go +++ b/modules/robot/core.go @@ -8,6 +8,18 @@ import ( "google.golang.org/protobuf/proto" ) +//监控 +type IRobotMonitor interface { + //成功 + AddSuccClient(robot *Robot) + //失败 + AddFailClient(robot *Robot, err error) + //结束 + RobotFinishedTest(robot *Robot) + //报表 + OutReport() +} + //客户端端 type IClient interface { Init(addr string, client IClient) (err error) diff --git a/modules/robot/module.go b/modules/robot/module.go index ce2a0c6f2..f02dcc613 100644 --- a/modules/robot/module.go +++ b/modules/robot/module.go @@ -19,10 +19,11 @@ func NewModule() core.IModule { type RobotModule struct { cbase.ModuleBase - options *Options - service base.IRPCXService - robotmgr *robotmgrComp - configure *configureComp + options *Options + service base.IRPCXService + robotmgr *robotmgrComp + configure *configureComp + statisticalComp *statisticalComp } // 模块名 @@ -52,4 +53,5 @@ func (this *RobotModule) OnInstallComp() { this.ModuleBase.OnInstallComp() this.configure = this.RegisterComp(new(configureComp)).(*configureComp) this.robotmgr = this.RegisterComp(new(robotmgrComp)).(*robotmgrComp) + this.statisticalComp = this.RegisterComp(new(statisticalComp)).(*statisticalComp) } diff --git a/modules/robot/modulerobot_gm.go b/modules/robot/modulerobot_gm.go new file mode 100644 index 000000000..12a0276d7 --- /dev/null +++ b/modules/robot/modulerobot_gm.go @@ -0,0 +1,34 @@ +package robot + +import ( + cfg "go_dreamfactory/sys/configure/structs" + + "google.golang.org/protobuf/proto" +) + +//用户模块 机器人 +type ModuleRobot_GM struct { +} + +func (this *ModuleRobot_GM) Init() (err error) { + + return +} + +//接收到消息 +func (this *ModuleRobot_GM) Receive(robot IRobot, stype string, message proto.Message) (err error) { + + return +} + +//机器人执行流 +func (this *ModuleRobot_GM) DoPipeline(robot IRobot) (err error) { + + return +} + +//做任务 +func (this *ModuleRobot_GM) 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 index 07b37ba08..95357c4f9 100644 --- a/modules/robot/modulerobot_wtask.go +++ b/modules/robot/modulerobot_wtask.go @@ -145,12 +145,13 @@ locp: case comm.Rtype104: module = comm.ModuleShop 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 !"}) + err = fmt.Errorf("[Robot DoTask] ctype:%d conld:%d Not Achieved !", cconf.Type, cconf.Id) + // 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()}) + // 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 } time.Sleep(time.Second * 2) diff --git a/modules/robot/options.go b/modules/robot/options.go index 7206bc190..70ae49343 100644 --- a/modules/robot/options.go +++ b/modules/robot/options.go @@ -8,12 +8,15 @@ import ( type ( Options struct { modules.Options - ServerAddr string //服务地址 - ServerID string //服务ID - RobotTotalNum int32 //机器人总数 - RobotSingleNum int32 //单词机器人进入数量 - Intervals int32 //间隔时间 单位秒 - RobotName string //机器人名称 + OutFilePath string //输出文件报表 + ServerAddr string //服务地址 + ServerID string //服务ID + RobotTotalNum int32 //机器人总数 + RobotSingleNum int32 //单词机器人进入数量 + Intervals int32 //间隔时间 单位秒 + RobotName string //机器人名称 + RobotStart int32 //机器人初始下标 + RobotLog bool Pipeline []string //执行流水线 } ) diff --git a/modules/robot/robot.go b/modules/robot/robot.go index 7093ccb97..48d86f852 100644 --- a/modules/robot/robot.go +++ b/modules/robot/robot.go @@ -24,7 +24,8 @@ type RobotStatistics struct { type Robot struct { Client - robotmgrComp *robotmgrComp + monitor IRobotMonitor + debug bool index int32 //编号 account, serverId string curreq string //当前请求 @@ -54,6 +55,7 @@ func (this *Robot) Init(addr string, client IClient) (err error) { this.statistics = make([]*RobotStatistics, 0, 100) this.modules[comm.ModuleUser] = new(ModuleRobot_User) this.modules[comm.ModuleSys] = new(ModuleRobot_Sys) + this.modules[comm.ModuleGM] = new(ModuleRobot_GM) this.modules[comm.ModuleHero] = new(ModuleRobot_Hero) this.modules[comm.ModuleEquipment] = new(ModuleRobot_Equipment) this.modules[comm.ModuleItems] = new(ModuleRobot_Item) @@ -154,7 +156,9 @@ func (this *Robot) SendMessage(mtype, stype string, msg proto.Message) (resp pro message: fmt.Sprintf("%s.%s", mtype, stype), time: time.Since(stime).Milliseconds(), }) - // 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)}, log.Field{Key: "resp", Value: errdata == nil}) + if this.debug { + 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)}, log.Field{Key: "resp", Value: errdata == nil}) + } } return } @@ -185,11 +189,14 @@ func (this *Robot) SendTaskMessage(task, comdi int32, mtype, stype string, msg p messageresp = <-this.await //等待回应 resp = messageresp.resp errdata = messageresp.errdata - if errdata == nil { - log.Debug("[机器人 Message]", log.Field{Key: "t", Value: time.Since(stime).Milliseconds()}, log.Field{Key: "Account", Value: this.account}, log.Field{Key: "Task", Value: fmt.Sprintf("[%d-%d]", task, comdi)}, log.Field{Key: "message", Value: fmt.Sprintf("%s.%s", mtype, stype)}, log.Field{Key: "errdata", Value: errdata == nil}) - } else { - log.Error("[机器人 Message]", log.Field{Key: "t", Value: time.Since(stime).Milliseconds()}, log.Field{Key: "Account", Value: this.account}, log.Field{Key: "Task", Value: fmt.Sprintf("[%d-%d]", task, comdi)}, log.Field{Key: "message", Value: fmt.Sprintf("%s.%s", mtype, stype)}, log.Field{Key: "errdata", Value: errdata.String()}) + if this.debug { + if errdata == nil { + log.Debug("[机器人 Message]", log.Field{Key: "t", Value: time.Since(stime).Milliseconds()}, log.Field{Key: "Account", Value: this.account}, log.Field{Key: "Task", Value: fmt.Sprintf("[%d-%d]", task, comdi)}, log.Field{Key: "message", Value: fmt.Sprintf("%s.%s", mtype, stype)}, log.Field{Key: "errdata", Value: errdata == nil}) + } else { + log.Error("[机器人 Message]", log.Field{Key: "t", Value: time.Since(stime).Milliseconds()}, log.Field{Key: "Account", Value: this.account}, log.Field{Key: "Task", Value: fmt.Sprintf("[%d-%d]", task, comdi)}, log.Field{Key: "message", Value: fmt.Sprintf("%s.%s", mtype, stype)}, log.Field{Key: "errdata", Value: errdata.String()}) + } } + this.statistics = append(this.statistics, &RobotStatistics{ message: fmt.Sprintf("%s.%s", mtype, stype), time: time.Since(stime).Milliseconds(), @@ -216,7 +223,7 @@ func (this *Robot) Heartbeat() { func (this *Robot) OnClose() { log.Debug("[机器人 End]", log.Field{Key: "Account", Value: this.account}) - this.robotmgrComp.robotEnd(this) + this.monitor.RobotFinishedTest(this) } func (this *Robot) DoTask(taskconf *cfg.GameWorldTaskData, condconf *cfg.GameBuriedCondiData, moduleStr core.M_Modules) (err error) { diff --git a/modules/robot/robotmgrcomp.go b/modules/robot/robotmgrcomp.go index f62d1dbed..fcbceffb7 100644 --- a/modules/robot/robotmgrcomp.go +++ b/modules/robot/robotmgrcomp.go @@ -4,7 +4,6 @@ import ( "fmt" "go_dreamfactory/lego/core" "go_dreamfactory/lego/core/cbase" - "go_dreamfactory/lego/sys/log" "sync" "time" ) @@ -61,21 +60,17 @@ func (this *robotmgrComp) createRobot(index int32) { err error ) robot = &Robot{ - robotmgrComp: this, - index: index, - account: fmt.Sprintf("%s_%d", this.module.options.RobotName, index), - serverId: this.module.options.ServerID, - pipeline: this.module.options.Pipeline, + debug: this.module.options.RobotLog, + monitor: this.module.statisticalComp, + index: index, + account: fmt.Sprintf("%s_%d", this.module.options.RobotName, this.module.options.RobotStart+index), + serverId: this.module.options.ServerID, + pipeline: this.module.options.Pipeline, } if err = robot.Init(this.module.options.ServerAddr, robot); err != nil { - log.Errorln(err) + this.module.statisticalComp.AddFailClient(robot, err) return } + this.module.statisticalComp.AddSuccClient(robot) return } - -func (this *robotmgrComp) robotEnd(robot *Robot) { - this.lock.Lock() - this.statistical[robot.account] = robot.statistics - this.lock.Unlock() -} diff --git a/modules/robot/statisticalcomp.go b/modules/robot/statisticalcomp.go index 4554b4694..7039eb3df 100644 --- a/modules/robot/statisticalcomp.go +++ b/modules/robot/statisticalcomp.go @@ -1,8 +1,13 @@ package robot import ( + "fmt" "go_dreamfactory/lego/core" "go_dreamfactory/lego/core/cbase" + "go_dreamfactory/lego/sys/log" + "os" + "sort" + "sync" ) /* @@ -10,15 +15,19 @@ import ( */ type statisticalComp struct { cbase.ModuleCompBase + module *RobotModule succclientNum int32 //链接成功客户端数 failclientNum int32 //链接失败客户端数 + endClientnum int32 //结束 totalmessage int32 //总消息两 robotdata map[string][]*RobotStatistics //机器人统计数据 + lock sync.RWMutex } //组件初始化接口 func (this *statisticalComp) 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.robotdata = make(map[string][]*RobotStatistics) return } @@ -31,9 +40,66 @@ func (this *statisticalComp) AddSuccClient(robot *Robot) { //添加失败客户端数 func (this *statisticalComp) AddFailClient(robot *Robot, err error) { this.succclientNum++ + this.endClientnum++ } //机器人测试结束 func (this *statisticalComp) RobotFinishedTest(robot *Robot) { - + this.lock.Lock() + this.robotdata[robot.Account()] = robot.statistics + this.lock.Unlock() + this.endClientnum++ + if this.endClientnum >= this.module.options.RobotTotalNum { //压测结束 + this.OutReport() + } +} + +//输出报表 +func (this *statisticalComp) OutReport() { + var ( + messages map[string][]int64 = make(map[string][]int64) + ok bool + ) + + for _, datas := range this.robotdata { + for _, v := range datas { + this.totalmessage++ + if _, ok = messages[v.message]; !ok { + messages[v.message] = make([]int64, 0) + } + messages[v.message] = append(messages[v.message], v.time) + } + } + + file, err := os.Create(this.module.options.OutFilePath) + if err != nil { + fmt.Println(err) + return + } + defer file.Close() + file.WriteString(fmt.Sprintf("机器人总数: %d\n", this.module.options.RobotTotalNum)) + file.WriteString(fmt.Sprintf("成功数量: %d\n", this.succclientNum)) + file.WriteString(fmt.Sprintf("失败数量: %d\n", this.failclientNum)) + file.WriteString(fmt.Sprintf("消息总吞吐量: %d\n", this.totalmessage)) + file.WriteString("---消息压测详情----------------------------------------------------------------------------------------------------\n") + for message, data := range messages { + sort.Slice(data, func(i, j int) bool { + return data[i] < data[j] + }) + max := data[len(data)-1] + min := data[0] + sum := int64(0) + for _, num := range data { + sum += num + } + avg := float64(sum) / float64(len(data)) + var median float64 + if len(data)%2 == 0 { + median = float64(data[len(data)/2-1]+data[len(data)/2]) / 2.0 + } else { + median = float64(data[len(data)/2]) + } + file.WriteString(fmt.Sprintf("消息名:%-20s 请求次数:%-5d 耗时最小:%-5dms 耗时最大:%-5dms 平均耗时:%-5.2fms 中位耗时:%-5.2fms \n", message, len(data), min, max, avg, median)) + } + log.Debugf("机器人报表已输出!") } diff --git a/modules/wtask/api_battlefinish.go b/modules/wtask/api_battlefinish.go index 2615f861b..4954d8954 100644 --- a/modules/wtask/api_battlefinish.go +++ b/modules/wtask/api_battlefinish.go @@ -92,7 +92,6 @@ func (this *apiComp) BattleFinish(session comm.IUserSession, req *pb.WTaskBattle } //触发任务 go this.module.ModuleBuried.TriggerBuried(session.Clone(), comm.GetBuriedParam(comm.Rtype70, 1, req.BattleConfId)) - } else { go this.module.ModuleBuried.TriggerBuried(session.Clone(), comm.GetBuriedParam(comm.Rtype227, 1, req.BattleConfId)) } diff --git a/services/cmd/main.go b/services/cmd/main.go index b25b6dccf..455c69efd 100644 --- a/services/cmd/main.go +++ b/services/cmd/main.go @@ -353,9 +353,8 @@ func convertServiceSttings(config *comm.GameConfig, id int, stype string, ip str "Alias": sseting.Id, "FileName": fmt.Sprintf("./log/%s.log", sseting.Id), "IsDebug": false, - "Loglevel": log.ErrorLevel, + "Loglevel": log.InfoLevel, "MaxAgeTime": 7, - "UniqueLog": true, } } diff --git a/sys/configure/structs/Game.BuzkashiQteLv.go b/sys/configure/structs/Game.BuzkashiQteLv.go new file mode 100644 index 000000000..799fa033b --- /dev/null +++ b/sys/configure/structs/Game.BuzkashiQteLv.go @@ -0,0 +1,42 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +package cfg + +type GameBuzkashiQteLv struct { + _dataMap map[int32]*GameBuzkashiQteLvData + _dataList []*GameBuzkashiQteLvData +} + +func NewGameBuzkashiQteLv(_buf []map[string]interface{}) (*GameBuzkashiQteLv, error) { + _dataList := make([]*GameBuzkashiQteLvData, 0, len(_buf)) + dataMap := make(map[int32]*GameBuzkashiQteLvData) + for _, _ele_ := range _buf { + if _v, err2 := DeserializeGameBuzkashiQteLvData(_ele_); err2 != nil { + return nil, err2 + } else { + _dataList = append(_dataList, _v) + dataMap[_v.Num] = _v + } + } + return &GameBuzkashiQteLv{_dataList:_dataList, _dataMap:dataMap}, nil +} + +func (table *GameBuzkashiQteLv) GetDataMap() map[int32]*GameBuzkashiQteLvData { + return table._dataMap +} + +func (table *GameBuzkashiQteLv) GetDataList() []*GameBuzkashiQteLvData { + return table._dataList +} + +func (table *GameBuzkashiQteLv) Get(key int32) *GameBuzkashiQteLvData { + return table._dataMap[key] +} + + diff --git a/sys/configure/structs/Game.BuzkashiQteLvData.go b/sys/configure/structs/Game.BuzkashiQteLvData.go new file mode 100644 index 000000000..223df62d2 --- /dev/null +++ b/sys/configure/structs/Game.BuzkashiQteLvData.go @@ -0,0 +1,39 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +package cfg + +import "errors" + +type GameBuzkashiQteLvData struct { + Num int32 + Time float32 + Value int32 +} + +const TypeId_GameBuzkashiQteLvData = 795602659 + +func (*GameBuzkashiQteLvData) GetTypeId() int32 { + return 795602659 +} + +func (_v *GameBuzkashiQteLvData)Deserialize(_buf map[string]interface{}) (err error) { + { var _ok_ bool; var _tempNum_ float64; if _tempNum_, _ok_ = _buf["num"].(float64); !_ok_ { err = errors.New("num error"); return }; _v.Num = int32(_tempNum_) } + { var _ok_ bool; var _tempNum_ float64; if _tempNum_, _ok_ = _buf["time"].(float64); !_ok_ { err = errors.New("time error"); return }; _v.Time = float32(_tempNum_) } + { var _ok_ bool; var _tempNum_ float64; if _tempNum_, _ok_ = _buf["value"].(float64); !_ok_ { err = errors.New("value error"); return }; _v.Value = int32(_tempNum_) } + return +} + +func DeserializeGameBuzkashiQteLvData(_buf map[string]interface{}) (*GameBuzkashiQteLvData, error) { + v := &GameBuzkashiQteLvData{} + if err := v.Deserialize(_buf); err == nil { + return v, nil + } else { + return nil, err + } +} diff --git a/sys/configure/structs/Tables.go b/sys/configure/structs/Tables.go index f0afb2ae8..de5f8e068 100644 --- a/sys/configure/structs/Tables.go +++ b/sys/configure/structs/Tables.go @@ -176,6 +176,7 @@ type Tables struct { Navigation *GameNavigation BuzkashiMount *GameBuzkashiMount BuzkashiLv *GameBuzkashiLv + BuzkashiQteLv *GameBuzkashiQteLv BuzkashiGrade *GameBuzkashiGrade BuzkashiReward *GameBuzkashiReward BuzkashiFm *GameBuzkashiFm @@ -1255,6 +1256,12 @@ func NewTables(loader JsonLoader) (*Tables, error) { if tables.BuzkashiLv, err = NewGameBuzkashiLv(buf) ; err != nil { return nil, err } + if buf, err = loader("game_buzkashiqtelv") ; err != nil { + return nil, err + } + if tables.BuzkashiQteLv, err = NewGameBuzkashiQteLv(buf) ; err != nil { + return nil, err + } if buf, err = loader("game_buzkashigrade") ; err != nil { return nil, err }