package user import ( "fmt" "go_dreamfactory/comm" "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" "time" uuid "github.com/satori/go.uuid" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/x/bsonx" ) type ModelUser struct { modules.MCompModel module *User } func (this *ModelUser) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) { this.TableName = comm.TableUser err = this.MCompModel.Init(service, module, comp, options) this.module = module.(*User) // 通过uid创建索引 this.DB.CreateIndex(core.SqlTable(this.TableName), mongo.IndexModel{ Keys: bsonx.Doc{{Key: "uid", Value: bsonx.Int32(1)}}, }) this.DB.CreateIndex(core.SqlTable(this.TableName), mongo.IndexModel{ Keys: bsonx.Doc{{Key: "name", Value: bsonx.Int32(1)}}, }) this.DB.CreateIndex(core.SqlTable(this.TableName), mongo.IndexModel{ Keys: bsonx.Doc{{Key: "logintime", Value: bsonx.Int32(1)}}, }) this.DB.CreateIndex(core.SqlTable(this.TableName), mongo.IndexModel{ Keys: bsonx.Doc{{Key: "merchantmoney", Value: bsonx.Int32(1)}}, }) return } func (this *ModelUser) FindByAccount(sid string, account string) (*pb.DBUser, error) { filter := bson.M{ "sid": sid, "binduid": account, } sr := this.DB.FindOne(comm.TableUser, filter) var nd *pb.DBUser err := sr.Decode(&nd) return nd, err } // 查询昵称 func (this *ModelUser) NickNameIsExist(name string) bool { if err := this.DB.FindOne(comm.TableUser, bson.M{"name": name}).Err(); err != nil { if err == mongo.ErrNoDocuments { //无记录 return true } } return false } // 创建初始用户 func (this *ModelUser) User_Create(user *pb.DBUser) (err error) { now := configure.Now().Unix() _id := primitive.NewObjectID().Hex() user.Id = _id user.Uid = fmt.Sprintf("%s_%s", user.Sid, _id) user.Uuid = uuid.NewV4().String() user.Lv = 1 //初始等级 user.Ctime = now user.Logintime = now if _, err = this.DB.InsertOne(comm.TableUser, user); err != nil { this.module.Error("创建用户", log.Field{Key: "sid", Value: user.Sid}, log.Field{Key: "account", Value: user.Binduid}, log.Field{Key: "err", Value: err.Error()}) return } key := fmt.Sprintf("%s:%s", this.TableName, user.Uid) if err = this.Redis.HMSet(key, user); err != nil { this.module.Error("创建用户", log.Field{Key: "sid", Value: user.Sid}, log.Field{Key: "account", Value: user.Binduid}, log.Field{Key: "err", Value: err.Error()}) return } return } // 获取用户 func (this *ModelUser) GetUser(uid string) (user *pb.DBUser, err error) { user = &pb.DBUser{} if this.module.IsCross() { var model *db.DBModel if model, err = this.module.GetDBModelByUid(uid, this.TableName); err != nil { this.module.Errorln(err) } else { if err = model.Get(uid, user); err != nil { this.module.Errorf("uid:%s err:%v", uid, err) } } } else { if err = this.Get(uid, user); err != nil { this.module.Errorf("uid:%s err:%v", uid, err) } } return } // 获取用户 func (this *ModelUser) GetCrossUsers(uids []string) (users []*pb.DBUser, err error) { var ( stage string usergroup map[string][]string = make(map[string][]string) conn *db.DBConn model *db.DBModel usersSlice []*pb.DBUser ) for _, v := range uids { if stage, err = comm.UidToSTag(v); err != nil { return } usergroup[stage] = append(usergroup[stage], v) } for k, v := range usergroup { if conn, err = db.ServerDBConn(k); err != nil { return } model = db.NewDBModel(k, this.TableName, conn) usersSlice = make([]*pb.DBUser, 0) if _, err = model.Gets(v, &usersSlice); err != nil { return } users = append(users, usersSlice...) } return } // 设置属性 func (this *ModelUser) updateUserAttr(uid string, data map[string]interface{}) error { if this.module.IsCross() { if model, err := this.module.GetDBModelByUid(uid, this.TableName); err != nil { this.module.Errorln(err) } else { if err = model.Change(uid, data); err != nil { this.module.Errorf("err:%v", err) } } } else { return this.Change(uid, data) } return nil } // 是否今天首次登录 func (this *ModelUser) isLoginFirst(timestamp int64) bool { now := configure.Now() if timestamp == 0 || timestamp > now.Unix() { //this.module.Debugf("lastlogin time great now") return false } tt := time.Unix(timestamp, 0) if !utils.IsToday(timestamp) { if tt.Before(now) { return true } } return false } // 删除用户数据 func (this *ModelUser) delete(uid string) { if err := this.DelByUId(uid); err != nil { log.Errorf("%v", err) } } // 修改玩家名字 func (this *ModelUser) modifyName(uid string, newName string) (errdata *pb.ErrorData) { if _, err := this.GetUser(uid); err != nil { errdata = &pb.ErrorData{ Code: pb.ErrorCode_UserSessionNobeing, Title: pb.ErrorCode_UserSessionNobeing.ToString(), Message: err.Error(), } return } // 修改名称 update := map[string]interface{}{ "name": newName, } if err := this.Change(uid, update); err != nil { errdata = &pb.ErrorData{ Code: pb.ErrorCode_DBError, Title: pb.ErrorCode_DBError.ToString(), Message: err.Error(), } return } return } func (this *ModelUser) updateOfflineTime(uid string) { if err := this.updateUserAttr(uid, map[string]interface{}{"offlinetime": configure.Now().Unix()}); err != nil { this.module.Errorln(err) } } // change vipexp func (this *ModelUser) changeVipExp(change *pb.UserResChangedPush) (lvchange bool) { var ( curExp int64 ) vipExp := change.Vipexp vipLv := change.Vip conf := this.module.configure.GetVipConfigureData(vipLv + 1) if conf == nil { return } curExp = int64(conf.UpExp) for vipExp >= curExp { vipLv++ vipExp -= curExp tmpConf := this.module.configure.GetVipConfigureData(vipLv + 1) if tmpConf == nil { vipLv-- vipExp += curExp break } curExp = int64(tmpConf.UpExp) lvchange = true } return } // change level func (this *ModelUser) computeLevel(change *pb.UserResChangedPush) (lvchange bool, loseexp int32, rewards []*cfg.Gameatn) { var ( curLv int32 = change.Lv nextLvConf *cfg.GamePlayerlvData curExp int64 = change.Exp res int64 ) rewards = make([]*cfg.Gameatn, 0) for { nextLvConf = this.module.configure.GetPlayerlvConf(curLv + 1) if nextLvConf == nil { break } if curExp >= int64(nextLvConf.Exp) { curExp = curExp - int64(nextLvConf.Exp) curLv++ //叠加奖励 rewards = append(rewards, nextLvConf.Reward...) } else { break } } if nextLvConf == nil { //满级了 curLvConf := this.module.configure.GetPlayerlvConf(curLv) reward := this.module.globalConf.OverexpReward if curExp > int64(curLvConf.Exp) { loseexp = int32(curExp) - curLvConf.Exp res = int64(loseexp * reward.N) curExp = int64(curLvConf.Exp) change.Deposit += res change.Exp = curExp } } // 等级有递增时再更新 if curLv > change.Lv { lvchange = true change.Lv = curLv change.Exp = curExp } return } func (this *ModelUser) changelv(session comm.IUserSession, lv int32, exp int64, name string) { go this.module.AsynHandleSession(session.Clone(), func(session comm.IUserSession) { var ( tasks []*pb.BuriedParam = make([]*pb.BuriedParam, 0) ) if err := session.SendMsg(string(this.module.GetType()), UserSubTypeLvChangedPush, &pb.UserLvChangedPush{Uid: session.GetUserId(), Exp: exp, Lv: lv}); err != nil { this.module.Error("玩家等级变化 UserSubTypeLvChangedPush推送失败", log.Field{Key: "uid", Value: session.GetUserId()}, log.Field{Key: "exp", Value: exp}, log.Field{Key: "lv", Value: lv}, ) } this.module.chat.SendSysChatToUser(session, comm.ChatSystem12, lv, 0, name) this.module.ModuleSys.CheckOpenCond(session.Clone(), comm.OpencondTypePlatlv, lv) tasks = append(tasks, comm.GetBuriedParam(comm.Rtype20, lv)) this.module.ModuleBuried.TriggerBuried(session, tasks...) }) } func (this *ModelUser) CleanUserMerchantmoney(session comm.IUserSession) (err error) { var ( model *db.DBModel update map[string]interface{} uid string ) uid = session.GetUserId() user := &pb.DBUser{} update = make(map[string]interface{}, 0) update["profit"] = 0 update["merchantmoney"] = 0 if user.Caravanlv == 0 { // 默认1级 user.Caravanlv = 1 update["caravanlv"] = user.Caravanlv } if db.IsCross() { if model, err = this.module.GetDBModelByUid(uid, this.TableName); err == nil { if err := this.Get(uid, user); err == nil { err = model.Change(uid, update) } else { this.module.Errorf("err:%v", err) } } else { this.module.Errorln(err) } } else { if err := this.Get(uid, user); err == nil { err = this.Change(uid, update) } else { this.module.Errorf("err:%v", err) } } return } ///资源自动恢复 func (this *ModelUser) ResAutoReplies(session comm.IUserSession, resreplies map[int32]int64) { var ( confs []*cfg.GameRestoreData restore []*cfg.GameRestoreData amount int64 add []*cfg.Gameatn subtract []*cfg.Gameatn ok bool err error ) if confs, err = this.module.configure.getGameRestoreData(); err != nil { return } if resreplies == nil { resreplies = make(map[int32]int64) } //计算是否有大到重置周期的 for _, v := range confs { if configure.Now().Sub(time.Unix(resreplies[v.Key], 0)).Hours() > float64(v.Cycle*24) { restore = append(restore, v) } } for _, conf := range restore { ok = false for _, v := range conf.Maximums { amount = 0 switch v.A { case comm.AttrType: amount = this.module.ModuleUser.QueryAttributeValue(session.GetUserId(), v.T) case comm.ItemType: default: this.module.Error("not support res type", log.Field{Key: "Type", Value: v.A}) continue } if conf.Tpye == 1 { //恢复 if amount < int64(v.N) { //需要补充 add = append(add, &cfg.Gameatn{A: v.A, T: v.T, N: int32(int64(v.N) - amount)}) ok = true } } else { //重置 if amount != int64(v.N) { ok = true if amount < int64(v.N) { //需要补充 add = append(add, &cfg.Gameatn{A: v.A, T: v.T, N: int32(int64(v.N) - amount)}) } else { //需要消减 subtract = append(add, &cfg.Gameatn{A: v.A, T: v.T, N: int32(amount - int64(v.N))}) } } } } if ok { resreplies[conf.Key] = configure.Now().Unix() } } if len(add) > 0 || len(subtract) > 0 { this.module.DispenseAtno(session, add, true) this.module.ConsumeRes(session, subtract, true) if err = this.Change(session.GetUserId(), map[string]interface{}{ "resreplies": resreplies, }); err != nil { this.module.Errorln(err) } } }