package items import ( "fmt" "go_dreamfactory/comm" "go_dreamfactory/lego/core" "go_dreamfactory/modules" "go_dreamfactory/pb" "go_dreamfactory/sys/configure" cfg "go_dreamfactory/sys/configure/structs" "go_dreamfactory/sys/db" "math" "time" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/x/bsonx" ) ///背包缓存数据管理组件 type ModelItemsComp struct { modules.MCompModel module *Items } //组件初始化接口 func (this *ModelItemsComp) Init(service core.IService, module core.IModule, comp core.IModuleComp, opt core.IModuleOptions) (err error) { this.TableName = comm.TableItems this.MCompModel.Init(service, module, comp, opt) this.module = module.(*Items) //创建uid索引 this.DB.CreateIndex(core.SqlTable(this.TableName), mongo.IndexModel{ Keys: bsonx.Doc{{Key: "uid", Value: bsonx.Int32(1)}}, }) return } ///查询用户背包数据 func (this *ModelItemsComp) QueryUserPack(uId string) (itmes []*pb.DB_UserItemData, err error) { var ( model *db.DBModel ) itmes = make([]*pb.DB_UserItemData, 0) if this.module.IsCross() { if model, err = this.module.GetDBModelByUid(uId, this.TableName); err != nil { this.module.Errorln(err) } else { if err = model.GetList(uId, &itmes); err != nil { this.module.Errorf("err:%v", err) } } } else { if err = this.GetList(uId, &itmes); err != nil { this.module.Errorf("err:%v", err) } } return } ///查询用户指定格子的物品数据 func (this *ModelItemsComp) QueryUserPackByGridId(uId string, grid string) (itme *pb.DB_UserItemData, err error) { var ( model *db.DBModel ) itme = &pb.DB_UserItemData{} if this.module.IsCross() { if model, err = this.module.GetDBModelByUid(uId, this.TableName); err != nil { this.module.Errorln(err) } else { if err = model.GetListObj(uId, grid, itme); err != nil { this.module.Errorf("err:%v", err) } } } else { if err = this.GetListObj(uId, grid, itme); err != nil { this.module.Errorf("err:%v", err) } } return } ///查询用户指定格子的物品数据 func (this *ModelItemsComp) QueryUserPackByGridIds(uId string, grids []string) (itme []*pb.DB_UserItemData, err error) { var ( model *db.DBModel ) itme = make([]*pb.DB_UserItemData, len(grids)) if this.module.IsCross() { if model, err = this.module.GetDBModelByUid(uId, this.TableName); err != nil { this.module.Errorln(err) } else { if err = model.GetListObjs(uId, grids, &itme); err != nil { this.module.Errorf("err:%v", err) } } } else { if err = this.GetListObjs(uId, grids, &itme); err != nil { this.module.Errorf("err:%v", err) } } return } //更新用户的背包信息 func (this *ModelItemsComp) AddUserPack(uId string, itmes ...*pb.DB_UserItemData) (err error) { data := make(map[string]*pb.DB_UserItemData) for _, v := range itmes { data[v.GridId] = v } var ( model *db.DBModel ) if this.module.IsCross() { if model, err = this.module.GetDBModelByUid(uId, this.TableName); err != nil { this.module.Errorln(err) } else { if err = model.AddLists(uId, data); err != nil { this.module.Errorf("err:%v", err) } } } else { if err = this.AddLists(uId, data); err != nil { this.module.Errorln(err) } } return } //更新用户的背包信息 func (this *ModelItemsComp) UpdateUserPack(uid string, itmes ...*pb.DB_UserItemData) (err error) { var ( model *db.DBModel ) if this.module.IsCross() { if model, err = this.module.GetDBModelByUid(uid, this.TableName); err != nil { this.module.Errorln(err) } else { for _, v := range itmes { model.ChangeList(uid, v.GridId, map[string]interface{}{ "amount": v.Amount, "isNewItem": v.IsNewItem, "lastopt": configure.Now().Unix(), }) } } } else { for _, v := range itmes { this.ChangeList(uid, v.GridId, map[string]interface{}{ "amount": v.Amount, "isNewItem": v.IsNewItem, "lastopt": configure.Now().Unix(), }) } } return } //更新用户的背包信息 func (this *ModelItemsComp) DeleteUserPack(uid string, itmes ...*pb.DB_UserItemData) (err error) { var ( model *db.DBModel ) gridIds := make([]string, len(itmes)) for i, v := range itmes { gridIds[i] = v.GridId } if this.module.IsCross() { if model, err = this.module.GetDBModelByUid(uid, this.TableName); err != nil { this.module.Errorln(err) } else { if err = model.DelListlds(uid, gridIds); err != nil { this.module.Errorf("err:%v", err) return } } } else { if len(gridIds) > 0 { if err = this.DelListlds(uid, gridIds); err != nil { this.module.Errorf("err:%v", err) return } } } return } //查询用户背包物品数量 func (this *ModelItemsComp) QueryUserPackItemsAmount(uId string, itemid ...string) (result map[string]uint32) { var ( itmes []*pb.DB_UserItemData err error ) if itmes, err = this.QueryUserPack(uId); err != nil { this.module.Errorf("err:%v", err) return } result = map[string]uint32{} for _, v := range itmes { for _, v1 := range itemid { if v.ItemId == v1 { result[v1] += v.Amount } } } return } ///添加或则减少物品到用户背包 func (this *ModelItemsComp) AddItemToUserPack(uId string, itemId string, addnum int32) (change []*pb.DB_UserItemData, err error) { var ( itmes []*pb.DB_UserItemData add []*pb.DB_UserItemData del []*pb.DB_UserItemData update []*pb.DB_UserItemData leftnum int64 ) if addnum == 0 { return } if itmes, err = this.QueryUserPack(uId); err != nil { this.module.Errorf("err:%v", err) return } change = make([]*pb.DB_UserItemData, 0) if add, update, del, leftnum, err = this.addItemToUserPack(uId, itmes, itemId, addnum); err != nil { return } if leftnum < 0 { err = ItemNotEnoughError return } else if leftnum > 0 { err = PackGridNumUpper return } if len(add) > 0 { if err = this.AddUserPack(uId, add...); err != nil { this.module.Errorf("err:%v", err) return } change = append(change, add...) } if len(del) > 0 { if err = this.DeleteUserPack(uId, del...); err != nil { this.module.Errorf("err:%v", err) return } change = append(change, del...) } if len(update) > 0 { if err = this.UpdateUserPack(uId, update...); err != nil { this.module.Errorf("err:%v", err) return } change = append(change, update...) } return } ///添加或则减少多个物品到用户背包 func (this *ModelItemsComp) AddItemsToUserPack(uId string, items map[string]int32) (change []*pb.DB_UserItemData, err error) { var ( itmes []*pb.DB_UserItemData add []*pb.DB_UserItemData del []*pb.DB_UserItemData update []*pb.DB_UserItemData leftnum int64 ) if itmes, err = this.QueryUserPack(uId); err != nil { this.module.Errorf("err:%v", err) return } change = make([]*pb.DB_UserItemData, 0) for k, v := range items { if add, update, del, leftnum, err = this.addItemToUserPack(uId, itmes, k, v); err != nil { return } if leftnum < 0 { err = ItemNotEnoughError return } else if leftnum > 0 { err = PackGridNumUpper return } if len(add) > 0 { if err = this.AddUserPack(uId, add...); err != nil { this.module.Errorf("err:%v", err) return } change = append(change, add...) // } if len(del) > 0 { if err = this.DeleteUserPack(uId, del...); err != nil { this.module.Errorf("err:%v", err) return } change = append(change, del...) } if len(update) > 0 { if err = this.UpdateUserPack(uId, update...); err != nil { this.module.Errorf("err:%v", err) return } change = append(change, update...) } } return } ///修改指定格子的物品数量 func (this *ModelItemsComp) AddItemToUserPackByGrid(uId string, gridid string, addnum int32) (change []*pb.DB_UserItemData, err error) { var ( conf *cfg.GameItemData itme *pb.DB_UserItemData num int64 amount int64 ) if addnum == 0 { return } if itme, err = this.QueryUserPackByGridId(uId, gridid); err != nil { this.module.Errorf("err:%v", err) return } if conf, err = this.module.configure.GetItemConfigure(itme.ItemId); err != nil { this.module.Errorf("err:%v", err) return } amount = int64(itme.Amount) num = amount + int64(addnum) change = make([]*pb.DB_UserItemData, 0) if num < 0 { err = ItemNotEnoughError } else { if conf.UpperLimit > 0 && num > int64(conf.UpperLimit) { err = GirdAmountUpper return } else { itme.Amount = uint32(num) if itme.Amount > 0 { this.UpdateUserPack(uId, itme) } else { this.DeleteUserPack(uId, itme) } change = append(change, itme) } } return } ///添加移除物品到用户背包 func (this *ModelItemsComp) addItemToUserPack(uid string, items []*pb.DB_UserItemData, itemId string, addnum int32) (add, update, del []*pb.DB_UserItemData, leftnum int64, err error) { var ( conf *cfg.GameItemData num int64 isNew bool ) if addnum == 0 { return } if conf, err = this.module.configure.GetItemConfigure(itemId); err != nil { this.module.Errorln(err) err = NoFoundItemConfig return } if conf.UpperLimit == 0 { err = fmt.Errorf("item UpperLimit is 0") return } isNew = true leftnum = int64(addnum) add = make([]*pb.DB_UserItemData, 0) del = make([]*pb.DB_UserItemData, 0) update = make([]*pb.DB_UserItemData, 0) for _, v := range items { if v.ItemId == itemId { isNew = false num = int64(v.Amount) + int64(leftnum) if num < 0 { leftnum += int64(v.Amount) v.Amount = 0 del = append(del, v) } else if num > 0 && num < int64(v.Amount) { leftnum = 0 v.Amount = uint32(num) update = append(update, v) break } else if num > 0 && num > int64(v.Amount) { if conf.UpperLimit > 0 { if num <= int64(conf.UpperLimit) { leftnum = 0 v.Amount = uint32(num) update = append(update, v) break } else { if v.Amount < uint32(conf.UpperLimit) { leftnum = int64(num - int64(conf.UpperLimit)) v.Amount = uint32(conf.UpperLimit) update = append(update, v) } } } else { leftnum = 0 v.Amount = uint32(num) update = append(update, v) } } else if num == 0 { leftnum = 0 v.Amount = 0 del = append(del, v) } } } if leftnum < 0 { //背包物品不够 return } if leftnum > 0 { //还没有放完 寻找空的格子填充 index := int32(len(items)) for leftnum > 0 { //需要补充格子 if conf.UpperLimit < 0 || (conf.UpperLimit > 0 && leftnum <= int64(conf.UpperLimit)) { grid := &pb.DB_UserItemData{ GridId: primitive.NewObjectID().Hex(), UId: uid, ItemId: itemId, Amount: uint32(leftnum), CTime: configure.Now().Unix(), IsNewItem: isNew, } if conf.Time > 0 { grid.ETime = configure.Now().Add(time.Minute * time.Duration(conf.Time)).Unix() } items = append(items, grid) add = append(add, grid) leftnum = 0 break } else { leftnum -= int64(conf.UpperLimit) grid := &pb.DB_UserItemData{ GridId: primitive.NewObjectID().Hex(), UId: uid, ItemId: itemId, Amount: uint32(conf.UpperLimit), CTime: configure.Now().Unix(), IsNewItem: isNew, } if conf.Time > 0 { grid.ETime = configure.Now().Add(time.Minute * time.Duration(conf.Time)).Unix() } items = append(items, grid) add = append(add, grid) index++ } if index > GridMaxNUm { //格子已达上限 break } } } return } //购买门票 func (this *ModelItemsComp) buyTicket(session comm.IUserSession, buy int32) (info *pb.DBUserExpand, code pb.ErrorCode) { var ( need *cfg.Gameatn needs []*cfg.Gameatn maxbuy, vipbuy int err error ) if info, err = this.module.ModuleUser.GetUserExpand(session.GetUserId()); err != nil { code = pb.ErrorCode_CacheReadError return } this.module.modelItems.recoverTicket(session) if maxbuy, err = this.module.configure.GetchallengeDataCount(); err != nil { code = pb.ErrorCode_ConfigNoFound return } vipbuy = int(this.module.privilege.GetCountByPrivilegeId(session.GetUserId(), comm.PrivilegeType3)) needs = make([]*cfg.Gameatn, 0) for i := int32(0); i < buy; i++ { if int(info.Buyunifiedticket+i+1) > maxbuy+vipbuy { code = pb.ErrorCode_ArenaTicketBuyUp return } if need = this.module.configure.GetchallengeData(int(info.Buyunifiedticket + i + 1)); err != nil || need == nil { code = pb.ErrorCode_ConfigNoFound return } needs = append(needs, need) } if code = this.module.ConsumeRes(session, needs, true); code != pb.ErrorCode_Success { return } atn := this.module.ModuleTools.GetGlobalConf().CopsBuyGet res := &cfg.Gameatn{ A: atn.A, T: atn.T, N: atn.N * buy, } info.Buyunifiedticket += buy if code = this.module.DispenseRes(session, []*cfg.Gameatn{res}, true); code != pb.ErrorCode_Success { return } this.module.ModuleUser.ChangeUserExpand(session.GetUserId(), map[string]interface{}{ "buyunifiedticket": info.Buyunifiedticket, "lasttimeunifiedticket": info.Lasttimeunifiedticket, "recovertimeunifiedticket": info.Recovertimeunifiedticket, }) return } ///回复门票 func (this *ModelItemsComp) recoverTicket(session comm.IUserSession) (code pb.ErrorCode) { var ( user *pb.DBUser info *pb.DBUserExpand duration time.Duration ticket int32 ticketNum int32 err error ) if user = this.module.ModuleUser.GetUser(session.GetUserId()); user == nil { code = pb.ErrorCode_CacheReadError return } if info, err = this.module.ModuleUser.GetUserExpand(session.GetUserId()); err != nil { code = pb.ErrorCode_CacheReadError return } if time.Unix(info.Lasttimeunifiedticket, 0).Day() < configure.Now().Day() { info.Lasttimeunifiedticket = configure.Now().Unix() info.Buyunifiedticket = 0 } global := this.module.ModuleTools.GetGlobalConf() playerlv := this.module.configure.GetPlayerlvConf(user.Lv) ticket = int32(this.module.ModuleItems.QueryItemAmount(session.GetUserId(), comm.UnifiedTicket)) if ticket < global.DreamlandFightnum && info.Recovertimeunifiedticket > 0 { duration = configure.Now().Sub(time.Unix(info.Recovertimeunifiedticket, 0)) ticketNum = int32(math.Floor(duration.Seconds() / float64(global.CopsRecoveryTime))) if ticketNum > 0 { if ticketNum+ticket > playerlv.CopsPsCeiling { ticketNum = playerlv.CopsPsCeiling - ticket } this.module.DispenseRes(session, []*cfg.Gameatn{{A: comm.ItemType, T: comm.UnifiedTicket, N: ticketNum}}, true) info.Recovertimeunifiedticket = time.Unix(info.Recovertimeunifiedticket, 0).Add(time.Duration(ticketNum) * time.Minute).Unix() } } this.module.ModuleUser.ChangeUserExpand(session.GetUserId(), map[string]interface{}{ "buyunifiedticket": info.Buyunifiedticket, "lasttimeunifiedticket": info.Lasttimeunifiedticket, "recovertimeunifiedticket": info.Recovertimeunifiedticket, }) return }