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/utils" "math" "strconv" "time" "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 } 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) { err = this.ModuleBase.Init(service, module, options) this.service = service.(base.IRPCXService) return } func (this *Caravan) Start() (err error) { err = this.ModuleBase.Start() 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) } // 接口信息 修改数据 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: []int32{}, // 城市卖给玩家的商品 (注意 这里有库存 必须初始化 Count 字段数据) Count: map[int32]int32{}, // key 货物ID } 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...) } data.City[v.Id] = city } } // 初始化货物信息 func (this *Caravan) InitCaravanItemData(uid string, data *pb.DBCaravan) { items := this.configure.GetAllCaravanItem() data.Goods = make(map[int32]*pb.Goods, 0) for _, v := range items { goods := &pb.Goods{ Period: 0, // 变动周期 CurPeriod: 1, // 当前变动周期 Price: 0, // 当前价格 } if len(v.Changeperiod) == 2 { goods.Period = comm.GetRandNum(v.Changeperiod[0], v.Changeperiod[1]) goods.Price = v.Goodsprice data.Goods[v.Id] = goods } data.Oldprice[v.Id] = v.Goodsprice } } // 初始化门票和虚拟币 func (this *Caravan) InitCaravanTicket(session comm.IUserSession, lv int32) (errdata *pb.ErrorData) { if conf, _ := this.modelCaravan.module.configure.GetCaravanLv(lv); conf != nil { var res []*cfg.Gameatn res = append(res, conf.Tickettop) res = append(res, conf.Moneynumtop) errdata = this.DispenseRes(session, res, true) // 推送门票和虚拟币资源 } return } // 刷新城市货物信息 func (this *Caravan) refreshCaravanCityInfo(uid string, caravan *pb.DBCaravan) { var ( bChange bool update map[string]interface{} changeTime int32 ) update = make(map[string]interface{}) changeTime = this.configure.GetCityRefreshTime() // 180 if int32(configure.Now().Unix()-caravan.Citystime) >= changeTime { bChange = true for k, v := range caravan.City { if c, _ := this.configure.GetCaravanCity(k); c != nil { v.Count = make(map[int32]int32) // 初始化城市信息 v.Special = []int32{} if len(c.Special) > int(c.Citytypenum) { ids := utils.RandomNumbers(0, len(c.Special), int(c.Citytypenum)) for _, id := range ids { v.Special = append(v.Special, c.Special[id]) } } else { v.Special = append(v.Special, c.Special...) } } } subTime := configure.Now().Unix() - caravan.Citystime icount := int32(subTime / int64(changeTime)) // 循环周期 caravan.Citystime += int64(changeTime * icount) for k, v := range caravan.Goods { if c, err := this.configure.GetCaravanGoods(k); err == nil { caravan.Oldprice[k] = v.Price if icount > 50 { //超过一定的周期 则不计算 // 随机出新的变动周期 v.Period = comm.GetRandNum(c.Changeperiod[0], c.Changeperiod[1]) v.CurPeriod = 0 } else { for i := 0; i < int(icount); i++ { // 计算当前的价格 // 价格涨跌权重 PriceChangeWeight bUp := false // true 涨 ipos := comm.GetRandW(c.PriceChangeWeight) if ipos == 1 { if comm.GetRandW(c.PriceChangeWeightOne) == 0 { bUp = true } } else if ipos == 2 { if comm.GetRandW(c.PriceChangeWeightTwo) == 0 { bUp = true } } else if ipos == 3 { if comm.GetRandW(c.PriceChangeWeightThree) == 0 { bUp = true } } if bUp { // 价格上涨 v.Price = int32(math.Floor(float64(v.Price) * (1.0 + float64(c.FluctuationRange)/1000.0))) } else { v.Price = int32(math.Floor(float64(v.Price) * (1.0 - float64(c.FluctuationRange)/1000.0))) } if v.Price < c.Pricemin { // 设置最小值 v.Price = c.Pricemin } if v.Price > c.Pricemax { // 设置最大值 v.Price = c.Pricemax } v.CurPeriod += 1 // 更新周期+1 if v.CurPeriod+icount > v.Period { // 随机出新的变动周期 v.Period = comm.GetRandNum(c.Changeperiod[0], c.Changeperiod[1]) v.CurPeriod = 0 } } } } } } if configure.Now().Unix() >= caravan.Resettime { sTime := int64(this.ModuleTools.GetGlobalConf().BusinessRewardday * 24 * 3600) // 单位s openTime := this.service.GetOpentime().Unix() // 获取开服时间 subTime := configure.Now().Unix() - openTime caravan.Resettime = configure.Now().Unix() - (subTime % sTime) + sTime update["resettime"] = caravan.Resettime bChange = true } if bChange { update["city"] = caravan.City update["goods"] = caravan.Goods update["oldprice"] = caravan.Oldprice update["citystime"] = caravan.Citystime this.modelCaravan.modifyCaravanDataByObjId(uid, update) } } // 校验随机事件是否超时 func (this *Caravan) CheckCaravanTask(session comm.IUserSession, data *pb.DBCaravan) (bTimeOut bool) { if data.Eventid != 0 { if list, err := this.configure.GetCaravanEventById(data.Eventid); err == nil { // 校验任务是否超时 if data.Tasktime-configure.Now().Unix() > int64(list.Eventtime) { //TODO 任务超时 通知任务模块处理 并清理相关数据 module, err := this.service.GetModule(comm.ModuleWorldtask) if err != nil { return } if wt, ok := module.(comm.IWorldtask); ok { wt.UpdateTaskStatus(session.GetUserId(), data.Taskid) // 通知任务模块 任务超时 } this.CleanCaravanTask(session.GetUserId(), data) //任务超时 清理任务数据 // 任务超时发送任务失败推送 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.UserAssets{ A: "attr", T: "merchantmoney", N: -list.Unreword[1], // 扣除虚拟币 }) } 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() { if conf, err := this.configure.GetCaravanEventById(taskid); err == nil { list, _ := this.modelCaravan.getCaravanList(session.GetUserId()) if list.Taskid == taskid { this.CleanCaravanTask(session.GetUserId(), list) //任务完成 清理任务数据 resp = &pb.CaravanTaskCompletePush{} resp.Data = list resp.BSuccess = true for _, v := range conf.Reword { resp.Reward = append(resp.Reward, &pb.UserAssets{ A: v.A, T: v.T, N: v.N, }) } if errdata := this.ModuleBase.DispenseRes(session, conf.Reword, true); errdata != nil { this.Errorf("Caravan DispenseRes err:%v", conf.Reword) } session.SendMsg(string(this.GetType()), "taskcomplete", resp) } } } } // 整理背包 (true 表示背包装不下) func (this *Caravan) ArrayBag(data *pb.DBCaravan, limit int32) (bFull bool) { var count int32 for k, v := range data.Items { if v.Count == 0 { delete(data.Items, k) } else { tmp := v.Count for { count++ if tmp > limit { tmp -= limit } else { break } } } } if count > data.Baglimit { return true } data.UseCount = count return false } // 获得利润判断是否能提升商队等级 func (this *Caravan) CheckCaravavLvUp(data *pb.DBCaravan) (curLv int32) { curLv = data.Lv for { if conf, err := this.configure.GetCaravanLv(curLv + 1); err == nil { if conf.Newmoneyexp <= int32(data.Profit) { curLv++ } else { break } } else { break } } return curLv } func (this *Caravan) TestFunc(session comm.IUserSession) { this.modelCaravan.module.api.GetList(session, &pb.CaravanGetListReq{}) this.modelCaravan.module.api.BuyOrSell(session, &pb.CaravanBuyOrSellReq{ City: 105, Items: map[int32]int32{ 6: 80, }, IsBuy: true, }) } // 赛季结算 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() { sTime := time.Now() var rankIndex int32 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.DBUser{} if err = _data.Decode(temp); err == nil { c, err := this.configure.GetCaravanRank(rankIndex) if err == nil { this.mail.SendMailByUID(temp.Uid, "CaravanRank", c.Reward, []string{strconv.Itoa(int(rankIndex))}) } } } } // 发送虚拟币奖励 if _data, err := this.modelCaravan.DB.Find(comm.TableUser, bson.M{"merchantmoney": bson.M{"$gt": comm.CaravanMerchantmoney}}); err == nil { for _data.Next(context.TODO()) { temp := &pb.DBUser{} if err = _data.Decode(temp); err == nil { for _, v := range this.configure.GetCaravanReward() { s := v.Moneystart e := v.Moneyend more := false if e == -1 { e = math.MaxInt32 more = true } if s < temp.Merchantmoney && e <= temp.Merchantmoney { var res []*cfg.Gameatn if more { // 超过的部分 r := this.ModuleTools.GetGlobalConf().BusinessMaxintReward m := this.ModuleTools.GetGlobalConf().BusinessMaxint n := (temp.Merchantmoney - s) / m atn := &cfg.Gameatn{ A: r.A, T: r.T, N: r.N * n, } res = append(res, atn) } res = append(res, v.Reward...) this.mail.SendMailByUID(temp.Uid, "CaravanRewards", v.Reward, []string{}) } } } } } Query := bson.M{} Query["merchantmoney"] = 0 _, err := this.modelCaravan.DB.UpdateMany(core.SqlTable(comm.TableUser), bson.M{"merchantmoney": bson.M{"$gt": 0}}, bson.M{"$set": Query}, options.MergeUpdateOptions().SetUpsert(true)) //, new(options.UpdateOptions).SetUpsert(true) if err != nil { this.Errorf("UpdateMany error: %v", err) } this.Debugf("sub time:%d", time.Now().Local().Sub(sTime).Milliseconds()) }() return }