go_dreamfactory/modules/user/model_user.go
2024-01-17 10:07:54 +08:00

414 lines
11 KiB
Go

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
curLvConf *cfg.GamePlayerlvData
curExp int64 = change.Exp
res int64
err error
)
rewards = make([]*cfg.Gameatn, 0)
for {
if nextLvConf, err = this.module.configure.GetPlayerlvConf(curLv + 1); err != nil {
break
}
if curExp >= int64(nextLvConf.Exp) {
curExp = curExp - int64(nextLvConf.Exp)
curLv++
//叠加奖励
rewards = append(rewards, nextLvConf.Reward...)
} else {
break
}
}
if nextLvConf == nil { //满级了
if curLvConf, err = this.module.configure.GetPlayerlvConf(curLv); err != nil {
log.Errorln(err)
return
}
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) {
// 获取本服的数据
if m, e := this.module.GetDBModelByUid(session.GetUserId(), this.TableName); e == nil {
user := &pb.DBUser{}
if err := m.Get(session.GetUserId(), user); err == nil {
if user.Caravanlv == 0 {
user.Caravanlv = 1
}
err = m.Change(session.GetUserId(), map[string]interface{}{
"profit": 0,
"caravanlv": user.Caravanlv,
"merchantmoney": 0,
})
} 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)
}
}
}
func (this *ModelUser) CleanUserConsumeMoney(session comm.IUserSession) (err error) {
// 获取本服的数据
if m, e := this.module.GetDBModelByUid(session.GetUserId(), this.TableName); e == nil {
err = m.Change(session.GetUserId(), map[string]interface{}{
"consumemoney": 0,
})
}
return
}