package caravan import ( "context" "go_dreamfactory/comm" "go_dreamfactory/lego/base" "go_dreamfactory/lego/core" "go_dreamfactory/lego/sys/log" "go_dreamfactory/modules" "go_dreamfactory/pb" "go_dreamfactory/sys/configure" cfg "go_dreamfactory/sys/configure/structs" "go_dreamfactory/sys/db" "go_dreamfactory/utils" "math" "strconv" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo/options" ) type Caravan struct { modules.ModuleBase modelCaravan *modelCaravan api *apiComp configure *configureComp service base.IRPCXService mail comm.Imail rank *ModelRank } func NewModule() core.IModule { return &Caravan{} } func (this *Caravan) GetType() core.M_Modules { return comm.ModuleCaravan } func (this *Caravan) Init(service core.IService, module core.IModule, options core.IModuleOptions) (err error) { if err = this.ModuleBase.Init(service, module, options); err != nil { return } this.service = service.(base.IRPCXService) return } func (this *Caravan) Start() (err error) { if err = this.ModuleBase.Start(); err != nil { return } var module core.IModule if module, err = this.service.GetModule(comm.ModuleMail); err != nil { return } this.mail = module.(comm.Imail) this.service.RegisterFunctionName(string(comm.Rpc_ModuleCaravanSettlement), this.Rpc_ModuleCaravanSettlement) return } func (this *Caravan) OnInstallComp() { this.ModuleBase.OnInstallComp() this.api = this.RegisterComp(new(apiComp)).(*apiComp) this.modelCaravan = this.RegisterComp(new(modelCaravan)).(*modelCaravan) this.configure = this.RegisterComp(new(configureComp)).(*configureComp) this.rank = this.RegisterComp(new(ModelRank)).(*ModelRank) } // 接口信息 修改数据 func (this *Caravan) ModifyCaravanData(uid string, data map[string]interface{}) (errdata *pb.ErrorData) { err := this.modelCaravan.modifyCaravanDataByObjId(uid, data) if err != nil { errdata = &pb.ErrorData{ Code: pb.ErrorCode_DBError, Title: pb.ErrorCode_DBError.ToString(), Message: err.Error(), } } return } // 初始化城市信息 func (this *Caravan) InitCaravanCityData(uid string, data *pb.DBCaravan) { list := this.configure.GetAllCaravanCity() data.City = make(map[int32]*pb.CityInfo, 0) for _, v := range list { city := &pb.CityInfo{ Special: []string{}, Count: map[string]int32{}, // 数量默认0 Exspecial: []string{}, // 想要玩家买的商品 ExspecialPCT: 0, Nextexspecial: []string{}, // 下一次变动时间 NextexspecialPCT: 0, } if len(v.Special) > int(v.Citytypenum) { ids := utils.RandomNumbers(0, len(v.Special), int(v.Citytypenum)) for _, id := range ids { city.Special = append(city.Special, v.Special[id]) } } else { city.Special = append(city.Special, v.Special...) } if len(v.Exspecial) > int(v.ExspecialNum) { ids := utils.RandomNumbers(0, len(v.Exspecial), int(v.ExspecialNum)) for _, id := range ids { city.Exspecial = append(city.Exspecial, v.Exspecial[id]) } } else { city.Exspecial = append(city.Exspecial, v.Exspecial...) } city.ExspecialPCT = v.Exspecialnum[comm.GetRandW(v.ExspecialnumWeight)] // 获取权重 if len(v.Exspecial) > int(v.ExspecialNum) { ids := utils.RandomNumbers(0, len(v.Exspecial), int(v.ExspecialNum)) for _, id := range ids { city.Nextexspecial = append(city.Nextexspecial, v.Exspecial[id]) } } else { city.Nextexspecial = append(city.Nextexspecial, v.Exspecial...) } city.NextexspecialPCT = v.Exspecialnum[int(comm.GetRandW(v.ExspecialnumWeight))] // 获取权重 data.City[v.Id] = city } data.Citystime = utils.GetZeroTime(configure.Now().Unix()) data.Rtime = configure.Now().Unix() // 修改时间 } // 初始化货物信息 func (this *Caravan) InitCaravanItemData(uid string, data *pb.DBCaravan) { if len(data.Allgoods) != 0 { return } items := this.configure.GetAllCaravanItem() data.Allgoods = make(map[int32]*pb.GoodsInfo, 0) if data.Period == nil { data.Period = make(map[string]*pb.GoodPeriod) } var index int32 for index = 0; index < this.configure.GetCityRefreshTime(); index++ { goodinfo := &pb.GoodsInfo{ Goods: make(map[string]int32, 0), } for _, c := range items { var price int32 if _, ok := data.Period[c.Itemid]; !ok { data.Period[c.Itemid] = &pb.GoodPeriod{} } if _, ok := data.Allgoods[index-1]; ok { if _, ok := data.Allgoods[index-1].Goods[c.Itemid]; ok { price = data.Allgoods[index-1].Goods[c.Itemid] // 获取上一次价格 } } if price == 0 { // price = c.Goodsprice // 获取默认值 } data.Period[c.Itemid].CurPeriod += 1 if len(c.Changeperiod) == 2 && data.Period[c.Itemid].Period == 0 { data.Period[c.Itemid].Period = comm.GetRandNum(c.Changeperiod[0], c.Changeperiod[1]) data.Period[c.Itemid].Weightpos = comm.GetRandW(c.PriceChangeWeight) } if data.Period[c.Itemid].Period < data.Period[c.Itemid].CurPeriod { data.Period[c.Itemid].Period = comm.GetRandNum(c.Changeperiod[0], c.Changeperiod[1]) data.Period[c.Itemid].CurPeriod = 0 data.Period[c.Itemid].Weightpos = comm.GetRandW(c.PriceChangeWeight) // 随机涨幅 } bUp := false if data.Period[c.Itemid].Weightpos == 0 { if comm.GetRandW(c.PriceChangeWeightOne) == 0 { // 走配置表一类涨幅 bUp = true } } else if data.Period[c.Itemid].Weightpos == 1 { if comm.GetRandW(c.PriceChangeWeightTwo) == 0 { bUp = true } } else if data.Period[c.Itemid].Weightpos == 2 { if comm.GetRandW(c.PriceChangeWeightThree) == 0 { bUp = true } } if len(c.FluctuationRange) == 2 { p := comm.GetRandNum(c.PriceChangeWeightThree[0], c.PriceChangeWeightThree[1]) if bUp { // 价格上涨 price = int32(math.Floor(float64(price) * (1.0 + float64(p)/1000.0))) } else { price = int32(math.Floor(float64(price) * (1.0 - float64(p)/1000.0))) } } if price < c.Pricemin { // 设置最小值 price = c.Pricemin } if price > c.Pricemax { // 设置最大值 price = c.Pricemax } goodinfo.Goods[c.Itemid] = price } data.Allgoods[index] = goodinfo } } // 初始化门票和虚拟币 func (this *Caravan) InitCaravanTicket(session comm.IUserSession, conf *cfg.GameCaravanLvData) (errdata *pb.ErrorData) { var res []*cfg.Gameatn res = append(res, conf.Tickettop) res = append(res, conf.Moneynumtop) errdata = this.DispenseRes(session, res, true) // 推送门票和虚拟币资源 go this.AsynHandleSession(session.Clone(), func(session comm.IUserSession) { this.WriteUserLog(session.GetUserId(), 0, "InitCaravanTicket", res) }) return } // 刷新城市货物信息 func (this *Caravan) refreshCaravanCityInfo(uid string, caravan *pb.DBCaravan) { var ( bChange bool update map[string]interface{} cityRtime int64 ) update = make(map[string]interface{}) cityRtime = utils.GetZeroTime(configure.Now().Unix()) // 刷新城市货物信息 if cityRtime != caravan.Citystime { list := this.configure.GetAllCaravanCity() for _, conf := range list { if v, ok := caravan.City[conf.Id]; ok { v.Count = make(map[string]int32) // 初始化城市信息 v.Special = []string{} if len(conf.Special) > int(conf.Citytypenum) { ids := utils.RandomNumbers(0, len(conf.Special), int(conf.Citytypenum)) for _, id := range ids { v.Special = append(v.Special, conf.Special[id]) } } else { v.Special = append(v.Special, conf.Special...) } if utils.IsToday(caravan.Citystime) { v.Exspecial = make([]string, 0) v.Exspecial = append(v.Exspecial, v.Nextexspecial...) v.ExspecialPCT = v.NextexspecialPCT } else { // 初始化今天 v.Exspecial = make([]string, 0) // 初始化下一天的信息 if len(conf.Exspecial) > int(conf.ExspecialNum) { ids := utils.RandomNumbers(0, len(conf.Exspecial), int(conf.ExspecialNum)) for _, id := range ids { v.Exspecial = append(v.Exspecial, conf.Exspecial[id]) } } else { v.Exspecial = append(v.Exspecial, conf.Exspecial...) } v.ExspecialPCT = conf.Exspecialnum[comm.GetRandW(conf.ExspecialnumWeight)] // 获取权重 } ///////////////////// v.Nextexspecial = []string{} // 初始化下一天的信息 if len(v.Exspecial) > int(conf.ExspecialNum) { ids := utils.RandomNumbers(0, len(conf.Exspecial), int(conf.ExspecialNum)) for _, id := range ids { v.Nextexspecial = append(v.Nextexspecial, conf.Exspecial[id]) } } else { v.Nextexspecial = append(v.Nextexspecial, conf.Exspecial...) } v.NextexspecialPCT = conf.Exspecialnum[comm.GetRandW(conf.ExspecialnumWeight)] // 获取权重 } } caravan.Citystime = cityRtime // 设置第二天0点的时间 update["city"] = caravan.City update["citystime"] = caravan.Citystime bChange = true } if bChange { this.modelCaravan.modifyCaravanDataByObjId(uid, update) } } // 校验随机事件是否超时 func (this *Caravan) CheckCaravanTask(session comm.IUserSession, data *pb.DBCaravan) (bTimeOut bool) { if data.Tasktime != 0 { if list, err := this.configure.GetCaravanEventById(data.Eventid); err == nil { // 校验任务是否超时 if configure.Now().Unix()-data.Tasktime > int64(list.Eventtime) { //TODO 任务超时 通知任务模块处理 并清理相关数据 module, err := this.service.GetModule(comm.ModuleWtask) if err != nil { return } if wt, ok := module.(comm.IWtask); ok { wt.ClearCaravanTask(session, data.Taskid) // 通知任务模块 任务超时 } this.CleanCaravanTask(session.GetUserId(), data) //任务超时 清理任务数据 data.Eventid = 0 data.Tasktime = 0 data.Eventid = 0 update := make(map[string]interface{}) update["eventid"] = data.Eventid update["tasktime"] = data.Tasktime update["eventid"] = data.Eventid this.modelCaravan.modifyCaravanDataByObjId(session.GetUserId(), update) // 任务超时发送任务失败推送 resp := &pb.CaravanTaskCompletePush{} resp.Data = data resp.BSuccess = false bTimeOut = true if len(list.Unreword) == 2 && list.Unreword[0] == 1 { // 类型为1 的 直接扣除虚拟币 this.ConsumeRes(session, []*cfg.Gameatn{{ A: "attr", T: "merchantmoney", N: list.Unreword[1], }}, true) resp.Reward = append(resp.Reward, &pb.UserAtno{ A: "attr", T: "merchantmoney", N: -list.Unreword[1], // 扣除虚拟币 O: "", }) go this.AsynHandleSession(session.Clone(), func(session comm.IUserSession) { this.WriteUserLog(session.GetUserId(), comm.GMResDelType, "CheckCaravanTask", resp.Reward) // 消耗资源 }) } session.SendMsg(string(this.GetType()), "taskcomplete", resp) } } } return false } func (this *Caravan) CleanCaravanTask(uid string, data *pb.DBCaravan) { if data.Eventid != 0 { data.Eventid = 0 data.Taskid = 0 data.Tasktime = 0 update := make(map[string]interface{}) update["eventid"] = data.Eventid update["taskid"] = data.Taskid update["tasktime"] = data.Tasktime this.modelCaravan.modifyCaravanDataByObjId(uid, update) } } func (this *Caravan) TaskComplete(session comm.IUserSession, taskid ...int32) { this.Debug("Caravan TaskComplete", log.Field{Key: "session", Value: session.GetUserId()}, log.Field{Key: "taskid", Value: taskid}, ) var ( resp *pb.CaravanTaskCompletePush ) if !this.IsCross() { for _, t := range taskid { list, _ := this.modelCaravan.getCaravanList(session.GetUserId()) if list.Taskid == t { if conf, err := this.configure.GetCaravanEventById(list.Eventid); err == nil { this.CleanCaravanTask(session.GetUserId(), list) //任务完成 清理任务数据 resp = &pb.CaravanTaskCompletePush{} resp.Data = list resp.BSuccess = true if errdata, reward := this.ModuleBase.DispenseAtno(session, conf.Reword, true); errdata != nil { this.Errorf("Caravan DispenseRes err:%v", conf.Reword) } else { resp.Reward = reward } session.SendMsg(string(this.GetType()), "taskcomplete", resp) go this.AsynHandleSession(session.Clone(), func(session comm.IUserSession) { this.WriteUserLog(session.GetUserId(), 0, "TaskComplete", conf.Reword) }) } } } } } // 整理背包 (true 表示背包装不下) func (this *Caravan) ArrayBag(data *pb.DBCaravan) { for k, v := range data.Items { if v.Count == 0 { delete(data.Items, k) } } return } // 校验货物是否超重 func (this *Caravan) CheckOverweight(data *pb.DBCaravan) (b bool) { var weight int32 for k, v := range data.Items { if d, err := this.configure.GetCaravanGoods(k); err == nil { weight += d.Weight * v.Count if weight > data.Baglimit { return true } } } return false } // 获得利润判断是否能提升商队等级 func (this *Caravan) CheckCaravavLvUp(data *pb.DBCaravan) (curLv int32) { curLv = 1 for { if conf, err := this.configure.GetCaravanLv(curLv); err == nil { if conf.Newmoneyexp <= int32(data.Profit) { //data.Profit -= int64(conf.Newmoneyexp) curLv++ } else { break } } else { break } } return curLv } // 赛季结算 func (this *Caravan) Rpc_ModuleCaravanSettlement(ctx context.Context, args *pb.EmptyReq, reply *pb.EmptyResp) (err error) { this.Debug("Rpc_ModuleCaravanSettlement", log.Field{Key: "args", Value: args.String()}, ) go func() { var ( rankIndex int32 stag string ) conn_, err := db.Cross() // 获取跨服数据库对象 if err != nil { return } model := db.NewDBModelByExpired(comm.TableCaravanRank, conn_) if model == nil { return } var maxKey int32 for _, v := range this.configure.GetCaravanReward() { if v.Key > maxKey { maxKey = v.Key } } moreReard, err := this.configure.GetCaravanMoreReward() // 超过部分 if err != nil { return } min := this.ModuleTools.GetGlobalConf().BusinessRankmoney if _data, err := model.DB.Find(comm.TableCaravanRank, bson.M{"merchantmoney": bson.M{"$gte": min}}, options.Find().SetSort(bson.M{"merchantmoney": -1}).SetLimit(int64(comm.MaxRankNum))); err == nil { //if _data, err := this.modelCaravan.DB.Find(comm.TableUser, bson.M{"merchantmoney": bson.M{"$gt": 0}}, options.Find().SetSort(bson.M{"merchantmoney": -1}).SetLimit(comm.MaxRankList)); err == nil { for _data.Next(context.TODO()) { rankIndex++ temp := &pb.DBCaravanRank{} if err = _data.Decode(temp); err == nil { if stag, err = comm.UidToSTag(temp.Uid); err != nil { return } if this.service.GetTag() == stag { if carConf, err := this.configure.GetCaravanRank(rankIndex); err == nil { this.mail.SendMailByUID(temp.Uid, "CaravanRank", carConf.Reward, []string{strconv.Itoa(int(rankIndex))}) } if maxKey < temp.Merchantmoney { // 超过部分转换其他奖励发送 var res []*cfg.Gameatn for _, v := range moreReard.Reward { if v.N == 0 { continue } atn := &cfg.Gameatn{ A: v.A, T: v.T, N: v.N * (temp.Merchantmoney - maxKey), } res = append(res, atn) } this.mail.SendMailByUID(temp.Uid, "CaravanRewards", res, []string{}) } } } } } Query := bson.M{} Query["merchantmoney"] = 0 Query["profit"] = 0 if _, err = model.DB.UpdateMany(core.SqlTable(comm.TableUser), bson.M{"merchantmoney": bson.M{"$gt": 0}}, bson.M{"$set": Query}, options.MergeUpdateOptions().SetUpsert(true)); err != nil { this.Errorf("Update Merchantmoney Many error: %v", err) } return }() return } func (this *Caravan) TaskGroupComplete(session comm.IUserSession, group int32) { if list, err := this.modelCaravan.getCaravanList(session.GetUserId()); err != nil { if _, ok := list.Group[group]; !ok { list.Group[group] = true update := make(map[string]interface{}) update["group"] = list.Group this.modelCaravan.modifyCaravanDataByObjId(session.GetUserId(), update) } } }