package operation import ( "context" "errors" "fmt" "game/common/model" "game/common/model/user" "game/common/proto/pb" "game/common/utils" "github.com/fox/fox/log" "github.com/fox/fox/xrand" "github.com/go-redis/redis/v8" "github.com/google/uuid" "gorm.io/gorm" "strconv" ) type UserOp struct { db *gorm.DB userRedis *redis.Client *model.TableOp[user.User] } // 玩家表 func NewUserOp() *UserOp { return &UserOp{ db: UserDB, userRedis: UserRedis, TableOp: model.NewTableOp[user.User](UserDB, UserRedis), } } func (s *UserOp) redisKey(accountId int64) string { return fmt.Sprintf("account_id:%v", accountId) } func (s *UserOp) GetUserByAccountId(accountId int64) (*user.User, pb.ErrCode) { sUid, err := s.userRedis.Get(context.Background(), s.redisKey(accountId)).Result() if err != nil { if errors.Is(err, redis.Nil) { us, code := s.FindCondition(map[string]any{"account_id": accountId}) if code != pb.ErrCode_OK { // db中没有则创建玩家 if us, code = s.createUserAccountId(accountId); code == pb.ErrCode_OK { _, _ = NewUserResourcesOp().Create(&user.UserResources{UID: us.ID}) return us, pb.ErrCode_OK } else { log.DebugF("create user by account id:%v", accountId) return nil, pb.ErrCode_SystemErr } } return us, pb.ErrCode_OK } else { log.ErrorF("find user by account id:%v err:%v", accountId, err) return nil, pb.ErrCode_SystemErr } } uid, _ := strconv.ParseInt(sUid, 10, 64) if uid < 0 { log.ErrorF("get user failed, account id:%d, uid:%v", accountId, sUid) return nil, pb.ErrCode_SystemErr } return s.Find(uid) } func (s *UserOp) generateUniqueNickname(db *gorm.DB) (string, error) { // 基础昵称模板 baseNick := "用户_" + uuid.New().String()[:8] nickname := baseNick // 检查是否唯一,不唯一则追加随机字符 for i := 0; i < 5; i++ { // 最多尝试5次 var count int64 err := db.Model(&user.User{}).Where("nickname = ?", nickname).Count(&count).Error if err != nil { return "", err } if count == 0 { return nickname, nil } nickname = baseNick + xrand.RandomString(2) // 追加2位随机字符 } return "", fmt.Errorf("无法生成唯一昵称") } // 创建用户 func (s *UserOp) createUserAccountId(accountId int64) (*user.User, pb.ErrCode) { nickname, err := s.generateUniqueNickname(s.db) if err != nil { log.ErrorF("generate unique nickname err:%v", err) return nil, pb.ErrCode_SystemErr } us := &user.User{ AccountId: accountId, Nickname: nickname, } var code pb.ErrCode us, code = s.Create(us) log.DebugF("create user:%v", utils.JsonMarshal(us)) if code != pb.ErrCode_OK { return nil, code } // 建立索引 _ = s.userRedis.Set(context.Background(), s.redisKey(us.AccountId), us.ID, model.TableExpire).Err() return us, pb.ErrCode_OK }