go_dreamfactory/modules/user/module.go
2023-11-16 18:09:41 +08:00

1439 lines
36 KiB
Go

// package
// 用户
// 赵长远
package user
import (
"context"
"fmt"
"go_dreamfactory/comm"
"go_dreamfactory/modules"
"go_dreamfactory/pb"
"go_dreamfactory/sys/configure"
"go_dreamfactory/sys/db"
"go_dreamfactory/utils"
"strings"
"sync"
"time"
"go_dreamfactory/lego/base"
"go_dreamfactory/lego/core"
"go_dreamfactory/lego/sys/event"
"go_dreamfactory/lego/sys/log"
cfg "go_dreamfactory/sys/configure/structs"
"github.com/pkg/errors"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
)
const (
// 跨服玩家
Rpc_GetAllOnlineUser string = "Rpc_GetAllOnlineUser"
// 跨服用户
Rpc_GetCrossUser string = "Rpc_GetCrossUser"
// 跨服用户会话
Rpc_GetCrossUserSession string = "Rpc_GetCrossUserSession"
// 搜索用户
Rpc_QueryUser = "Rpc_QueryUser"
//创建公会
Rpc_CreateSociaty string = "Rpc_CreateSociaty"
)
var _ comm.IUser = (*User)(nil)
func NewModule() core.IModule {
m := new(User)
return m
}
type User struct {
modules.ModuleBase
chat comm.IChat
api *apiComp
modelUser *ModelUser
modelSession *ModelSession
modelSetting *ModelSetting
modelExpand *ModelExpand
service base.IRPCXService
configure *configureComp
globalConf *cfg.GameGlobalData
modelSign *ModelSign // 签到
timerLock sync.Mutex
timerMap map[string]*time.Ticker
reddot comm.IReddot
}
func (this *User) GetType() core.M_Modules {
return comm.ModuleUser
}
func (this *User) Init(service core.IService, module core.IModule, options core.IModuleOptions) (err error) {
if err = this.ModuleBase.Init(service, module, options); err != nil {
return
}
this.service = service.(base.IRPCXService)
this.timerMap = make(map[string]*time.Ticker)
return
}
func (this *User) Start() (err error) {
if err = this.ModuleBase.Start(); err != nil {
return
}
event.RegisterGO(comm.EventUserOffline, this.CleanSession)
this.service.RegisterFunctionName(Rpc_GetAllOnlineUser, this.RpcGetAllOnlineUser)
this.service.RegisterFunctionName(Rpc_GetCrossUser, this.RpcGetCrossUser)
this.service.RegisterFunctionName(Rpc_GetCrossUserSession, this.RpcGetCrossUserSession)
this.service.RegisterFunctionName(Rpc_QueryUser, this.RpcQueryUser)
this.service.RegisterFunctionName(string(comm.Rpc_AccountBan), this.Rpc_AccountBan)
//date 3.10
this.service.RegisterFunctionName(Rpc_CreateSociaty, this.RpcCreateSociaty)
this.globalConf = this.ModuleTools.GetGlobalConf()
if this.globalConf == nil {
err = errors.New("global config not found")
}
this.ResetSession()
var module core.IModule
if module, err = this.service.GetModule(comm.ModuleChat); err != nil {
return
}
this.chat = module.(comm.IChat)
if module, err = this.service.GetModule(comm.ModuleReddot); err != nil {
return
}
this.reddot = module.(comm.IReddot)
return
}
func (this *User) OnInstallComp() {
this.ModuleBase.OnInstallComp()
this.api = this.RegisterComp(new(apiComp)).(*apiComp)
this.modelUser = this.RegisterComp(new(ModelUser)).(*ModelUser)
this.modelSession = this.RegisterComp(new(ModelSession)).(*ModelSession)
this.modelSetting = this.RegisterComp(new(ModelSetting)).(*ModelSetting)
this.modelExpand = this.RegisterComp(new(ModelExpand)).(*ModelExpand)
this.modelSign = this.RegisterComp(new(ModelSign)).(*ModelSign)
this.configure = this.RegisterComp(new(configureComp)).(*configureComp)
}
// 获取用户数据
func (this *User) GetUser(uid string) (user *pb.DBUser, err error) {
user, err = this.modelUser.GetUser(uid)
return
}
// 获取用户数据
func (this *User) GetCrossUsers(uid []string) (user []*pb.DBUser, err error) {
if !this.IsCross() {
return
}
user, err = this.modelUser.GetCrossUsers(uid)
return
}
// 获取跨服用户数据
func (this *User) GetCrossUser(uid string) (*pb.DBUser, error) {
reply := &pb.DBUser{}
err := this.service.AcrossClusterRpcCall(context.Background(), this.GetCrossTag(),
comm.Service_Worker, Rpc_GetCrossUser, &pb.UIdReq{Uid: uid}, reply)
return reply, err
}
// 获取远程用户数据
func (this *User) getRemoteUser(uid string) (*pb.DBUser, error) {
reply := &pb.DBUser{}
if err := this.getUserFromRemoteDb(uid, reply); err != nil {
this.Errorln("getRemoteUser", err)
return nil, err
}
return reply, nil
}
// 获取用户会话
func (this *User) GetUserSession(uid string) *pb.CacheUser {
return this.modelSession.getUserSession(uid)
}
// 获取用户会话
func (this *User) GetUserSessions(uids []string) []*pb.CacheUser {
return this.modelSession.getUserSessions(uids)
}
func (this *User) ResetSession() {
us, err := this.UserOnlineList()
if err != nil {
return
}
for _, v := range us {
this.modelSession.DelListlds(comm.RDS_EMPTY, []string{v.Uid})
}
this.modelSession.Del(comm.RDS_EMPTY)
}
// 清除session
func (this *User) CleanSession(uid, sessionid string) {
// this.stopTicker(uid)
if !this.IsCross() {
this.modelUser.updateOfflineTime(uid)
}
// sId := fmt.Sprintf("%s-%s", comm.RDS_EMPTY, session.GetUserId())
// this.modelSession.Del(sId, db.SetDBMgoLog(false))
// this.modelSession.DelListlds(comm.RDS_EMPTY, session.GetUserId())
//确保删除的会话是目标会话 不是就不要删除了
if user := this.modelSession.getUserSession(uid); user != nil && user.SessionId == sessionid {
this.modelSession.Del(uid, db.SetDBMgoLog(false))
this.modelSession.DelListlds(comm.RDS_EMPTY, []string{uid}, db.SetDBMgoLog(false))
}
this.modelUser.DelByUId(uid, db.SetDBMgoLog(false))
this.modelExpand.DelByUId(uid, db.SetDBMgoLog(false))
this.modelSetting.DelByUId(uid, db.SetDBMgoLog(false))
}
// 在线玩家列表
func (this *User) UserOnlineList() ([]*pb.CacheUser, error) {
var cache []*pb.CacheUser
if !this.IsCross() {
if err := this.modelSession.GetList(comm.RDS_EMPTY, &cache); err != nil {
return nil, err
}
} else {
var err error
if cache, err = this.CrossUserOnlineList(); err != nil {
return nil, err
}
}
return cache, nil
}
// 跨服玩家列表
func (this *User) CrossUserOnlineList() ([]*pb.CacheUser, error) {
conn, err := db.Local()
if err != nil {
return nil, err
}
model := db.NewDBModelByExpired(comm.TableSession, conn)
var cache []*pb.CacheUser
if err := model.GetList(comm.RDS_EMPTY, &cache); err != nil {
return nil, err
}
this.Debug("在线玩家数FromDB", log.Field{Key: "count", Value: len(cache)})
return cache, nil
}
func (this *User) crossUser(uid string) (*pb.CacheUser, error) {
conn, err := db.Local()
if err != nil {
return nil, err
}
model := db.NewDBModelByExpired(comm.TableSession, conn)
cache := &pb.CacheUser{}
if err := model.Get(uid, cache); err != nil {
return nil, err
}
return cache, nil
}
func (this *User) IsOnline(uid string) bool {
if this.IsCross() {
cache, err := this.crossUser(uid)
if err != nil {
return false
}
if cache.Uid == "" {
return false
}
}
return true
}
// 跨服玩家会话
func (this *User) CrossUserSession(uid string) *pb.CacheUser {
cacheUser := &pb.CacheUser{}
err := this.service.AcrossClusterRpcCall(context.Background(), this.GetCrossTag(),
comm.Service_Worker, Rpc_GetCrossUserSession, &pb.UIdReq{Uid: uid}, cacheUser)
if err != nil {
return nil
}
return cacheUser
}
// 跨服创建玩家公会 date 3.10
// Deprecated
func (this *User) CrossCreateSociaty(uid, sociatyName string) *pb.DBSociaty {
sociaty := &pb.DBSociaty{}
this.service.AcrossClusterRpcCall(context.Background(), this.GetCrossTag(),
comm.Service_Worker, Rpc_CreateSociaty, &pb.RPCGeneralReqA2{Param1: uid, Param2: sociatyName}, sociaty)
return sociaty
}
// date 3.10
// Deprecated
func (this *User) RpcCreateSociaty(ctx context.Context, req *pb.RPCGeneralReqA2, rsp *pb.DBSociaty) error {
conn, err := db.Local()
if err != nil {
return err
}
model := db.NewDBModel(comm.TableSociaty, conn)
sociaty := &pb.DBSociaty{}
_id := primitive.NewObjectID().Hex()
sociaty.Creater = req.Param1
sociaty.Name = req.Param2
sociaty.Icon = "wp_icon_10015"
sociaty.ApplyLv = 1
sociaty.Id = _id
sociaty.Ctime = configure.Now().Unix()
sociaty.Lv = 1 //默认1级
sociaty.Members = append(sociaty.Members, &pb.SociatyMember{
Uid: req.Param1,
Job: pb.SociatyJob_PRESIDENT,
Ctime: configure.Now().Unix(),
})
if err := model.AddList(comm.RDS_EMPTY, sociaty.Id, sociaty); err != nil {
if err != mongo.ErrNoDocuments {
return err
}
}
rsp.Id = sociaty.Id
return nil
}
// 跨服搜索用户
func (this *User) CrossSearchUser(nickName string) ([]*pb.DBUser, error) {
name := strings.TrimSpace(nickName)
if name == "" {
return nil, errors.New("search name is empty")
}
reply := &pb.UserDataListResp{}
err := this.service.AcrossClusterRpcCall(context.Background(), this.GetCrossTag(),
comm.Service_Worker, Rpc_QueryUser, &pb.NameReq{Name: name}, reply)
if err != nil {
return nil, err
}
return reply.Users, nil
}
// 远程搜索用户
func (this *User) SearchRmoteUser(nickname string) ([]*pb.DBUser, error) {
reply := &pb.UserDataListResp{}
if err := this.queryUserFromRemoteDb(nickname, reply); err != nil {
return nil, err
}
return reply.Users, nil
}
// 查询用户属性值 例如 金币 经验
func (this *User) QueryAttributeValue(uid string, attr string) (value int64) {
var (
user *pb.DBUser
userEx *pb.DBUserExpand
err error
)
user, err = this.modelUser.GetUser(uid)
if err != nil {
return
}
userEx, err = this.GetUserExpand(uid)
if err != nil {
return
}
if user == nil || userEx == nil {
return
}
switch attr {
case comm.ResGold:
return user.Gold
case comm.ResExp:
return user.Exp
case comm.VipExp:
return user.Vipexp
case comm.StarCoin:
return user.Starcoin
case comm.ResDiamond:
return user.Diamond
case comm.ResPs:
return int64(user.Ps)
case comm.SociatyCoin:
return int64(userEx.Guildcoin)
case comm.ArenaCoin:
return int64(userEx.Arenacoin)
case comm.ResFriend:
return int64(userEx.FriendPoint)
case comm.Moongold:
return int64(user.Moongold)
case comm.Talent1:
return int64(user.Talent1)
case comm.Talent2:
return int64(user.Talent2)
case comm.Talent3:
return int64(user.Talent3)
case comm.Talent4:
return int64(user.Talent4)
case comm.Merchantmoney:
return int64(user.Merchantmoney)
case comm.Integral:
return int64(user.Integral)
case comm.Profit:
return int64(user.Profit)
case comm.Consumeexp:
return int64(user.Consumeexp)
case comm.Consumemoney:
return int64(user.Consumemoney)
}
return
}
func (this *User) change(session comm.IUserSession, attrs map[string]int32) (atno []*pb.UserAtno, change *pb.UserResChangedPush, errdata *pb.ErrorData) {
uid := session.GetUserId()
var (
user *pb.DBUser
userEx *pb.DBUserExpand
vipexpchange bool
temp *pb.UserAtno
err error
)
user, err = this.GetUser(uid)
if err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserSessionNobeing,
Title: pb.ErrorCode_UserSessionNobeing.ToString(),
Message: err.Error(),
}
return
}
userEx, err = this.GetUserExpand(uid)
if err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserExpandNull,
Title: pb.ErrorCode_UserExpandNull.ToString(),
Message: err.Error(),
}
return
}
if user == nil || userEx == nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserSessionNobeing,
Title: pb.ErrorCode_UserSessionNobeing.ToString(),
}
return
}
change = &pb.UserResChangedPush{
Gold: user.Gold,
Exp: user.Exp,
Lv: user.Lv,
Vipexp: user.Vipexp,
Vip: user.Vip,
Diamond: user.Diamond,
Friend: userEx.FriendPoint,
Starcoin: user.Starcoin,
Guildcoin: userEx.Guildcoin,
Arenacoin: userEx.Arenacoin,
Ps: user.Ps,
Moongold: user.Moongold,
Talent1: user.Talent1,
Talent2: user.Talent2,
Talent3: user.Talent3,
Talent4: user.Talent4,
Merchantmoney: user.Merchantmoney,
Integral: user.Integral,
Profit: user.Profit,
Deposit: user.Deposit,
Consumeexp: user.Consumeexp,
Consumemoney: user.Consumemoney,
}
atno = make([]*pb.UserAtno, 0, len(attrs))
for attr, add := range attrs {
if add == 0 {
log.Warn("attr no changed",
log.Field{Key: "uid", Value: session.GetUserId()},
log.Field{Key: "attr", Value: attr},
log.Field{Key: "add", Value: add},
)
continue
}
temp = &pb.UserAtno{
A: comm.AttrType,
T: attr,
N: add,
}
switch attr {
case comm.ResGold:
if add < 0 {
if user.Gold+int64(add) < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_GoldNoEnough,
Title: pb.ErrorCode_GoldNoEnough.ToString(),
}
return
}
}
change.Gold += int64(add)
case comm.ResExp:
var (
lvchange bool
loseexp int32
rewards []*cfg.Gameatn
)
if add < 0 {
if user.Exp+int64(add) < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserExpNoEnough,
Title: pb.ErrorCode_UserExpNoEnough.ToString(),
}
return
}
}
change.Exp += int64(add)
if lvchange, loseexp, rewards = this.modelUser.computeLevel(change); lvchange {
go this.modelUser.changelv(session.Clone(), change.Lv, change.Exp, user.Name, rewards)
}
temp.N = temp.N - loseexp
case comm.VipExp:
if add < 0 {
if user.Vipexp+int64(add) < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserExpNoEnough,
Title: pb.ErrorCode_UserExpNoEnough.ToString(),
}
return
}
}
change.Vipexp += int64(add)
vipexpchange = true
case comm.ResDiamond:
if add < 0 {
if user.Diamond+int64(add) < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_DiamondNoEnough,
Title: pb.ErrorCode_DiamondNoEnough.ToString(),
}
return
}
}
change.Diamond += int64(add)
case comm.Moongold:
if add < 0 {
if user.Moongold+int32(add) < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserMoongoldNoEnough,
Title: pb.ErrorCode_UserMoongoldNoEnough.ToString(),
}
pb.ErrorCode_PayRenewTimeErr.Enum().Descriptor().ReservedNames()
}
}
change.Moongold += int32(add)
case comm.ResFriend:
if add < 0 {
if userEx.FriendPoint+add < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserFriendNoEnough,
Title: pb.ErrorCode_UserFriendNoEnough.ToString(),
}
return
}
}
change.Friend += add
case comm.StarCoin:
if add < 0 {
if user.Starcoin+int64(add) < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserStarCoinNoEnough,
Title: pb.ErrorCode_UserStarCoinNoEnough.ToString(),
}
return
}
}
change.Starcoin += int64(add)
case comm.SociatyCoin:
if add < 0 {
if userEx.Guildcoin+add < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserSociatyCoinNoEnough,
Title: pb.ErrorCode_UserSociatyCoinNoEnough.ToString(),
}
return
}
}
change.Guildcoin += add
case comm.ArenaCoin:
if add < 0 {
if userEx.Arenacoin+add < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserArenaCoinNoEnough,
Title: pb.ErrorCode_UserArenaCoinNoEnough.ToString(),
}
return
}
}
change.Arenacoin += add
case comm.ResPs:
ggd := this.ModuleTools.GetGlobalConf()
if ggd == nil {
return
}
if add < 0 {
if user.Ps+add < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserVitNoEnough,
Title: pb.ErrorCode_UserVitNoEnough.ToString(),
}
return
}
user.Ps += add
userEx.ConsumPs += -add
this.recoverUserPs(user)
change.Ps = user.Ps
go this.ModuleUiGame.HDPSTodayConsum(session.GetUserId(), userEx.ConsumPs)
} else {
if change.Ps+add > ggd.PsUl {
change.Ps = ggd.PsUl
} else {
change.Ps += add
}
}
case comm.Talent1:
if add < 0 {
if user.Talent1+add < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserTalent1NoEnough,
Title: pb.ErrorCode_UserTalent1NoEnough.ToString(),
}
return
}
}
change.Talent1 += add
case comm.Talent2:
if add < 0 {
if user.Talent2+add < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserTalent2NoEnough,
Title: pb.ErrorCode_UserTalent2NoEnough.ToString(),
}
return
}
}
change.Talent2 += add
case comm.Talent3:
if add < 0 {
if user.Talent3+add < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserTalent3NoEnough,
Title: pb.ErrorCode_UserTalent3NoEnough.ToString(),
}
return
}
}
change.Talent3 += add
case comm.Talent4:
if add < 0 {
if user.Talent4+add < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserTalent4NoEnough,
Title: pb.ErrorCode_UserTalent4NoEnough.ToString(),
}
return
}
}
change.Talent4 += add
case comm.Merchantmoney:
if add < 0 {
if user.Merchantmoney+add < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserMerchantNoEnough,
Title: pb.ErrorCode_UserMerchantNoEnough.ToString(),
}
return
}
}
change.Merchantmoney += add
case comm.Integral:
if add < 0 {
if user.Integral+int64(add) < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserMerchantNoEnough,
Title: pb.ErrorCode_UserMerchantNoEnough.ToString(),
}
return
}
}
change.Integral += int64(add)
case comm.Profit:
if add < 0 {
if user.Profit+int64(add) < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserProfitNoEnough,
Title: pb.ErrorCode_UserProfitNoEnough.ToString(),
}
return
}
}
change.Profit += int64(add)
case comm.Consumeexp:
if add < 0 {
if user.Consumeexp+add < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserProfitNoEnough,
Title: pb.ErrorCode_UserProfitNoEnough.ToString(),
}
return
}
}
change.Consumeexp += add
case comm.Consumemoney:
if add < 0 {
if user.Consumemoney+add < 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserProfitNoEnough,
Title: pb.ErrorCode_UserProfitNoEnough.ToString(),
}
return
}
}
change.Consumemoney += add
default:
err = errors.New(fmt.Sprintf("%s no supported", attr))
return
}
atno = append(atno, temp)
}
if vipexpchange {
if this.modelUser.changeVipExp(change) { //vip等级变化
session.SendMsg(string(this.GetType()), UserSubTypeVipChangedPush,
&pb.UserVipChangedPush{
Uid: session.GetUserId(),
VipExp: change.Exp,
VipLv: change.Lv,
})
go this.ModulePrivilege.AddVipData(session.Clone(), user.Vip, change.Vip)
}
}
//user
update := map[string]interface{}{
comm.ResGold: change.Gold,
comm.ResDiamond: change.Diamond,
comm.ResExp: change.Exp,
comm.Lv: change.Lv,
comm.VipExp: change.Vipexp,
comm.Vip: change.Vip,
comm.StarCoin: change.Starcoin,
comm.ResPs: change.Ps,
comm.Moongold: change.Moongold,
comm.Talent1: change.Talent1,
comm.Talent2: change.Talent2,
comm.Talent3: change.Talent3,
comm.Talent4: change.Talent4,
comm.Merchantmoney: change.Merchantmoney,
comm.Integral: change.Integral,
comm.Profit: change.Profit,
comm.Deposit: change.Deposit,
comm.Consumeexp: change.Consumeexp,
comm.Consumemoney: change.Consumemoney,
"lastRecoverPsSec": user.LastRecoverPsSec,
}
//user ex
updateEx := map[string]interface{}{
comm.ResFriend: change.Friend,
comm.SociatyCoin: change.Guildcoin,
comm.ArenaCoin: change.Arenacoin,
"consumPs": userEx.ConsumPs,
}
if err := this.modelUser.updateUserAttr(uid, update); err != nil {
this.Errorf("AddAttributeValue err:%v", err)
errdata = &pb.ErrorData{
Code: pb.ErrorCode_DBError,
Title: pb.ErrorCode_DBError.ToString(),
Message: err.Error(),
}
}
if err := this.modelExpand.ChangeUserExpand(uid, updateEx); err != nil {
this.Errorf("AddAttributeValue ex err:%v", err)
errdata = &pb.ErrorData{
Code: pb.ErrorCode_DBError,
Title: pb.ErrorCode_DBError.ToString(),
Message: err.Error(),
}
}
return
}
// // 用户资源
// func (this *User) AddAttributeValue(session comm.IUserSession, attr string, add int32, bPush bool) (errdata *pb.ErrorData) {
// var _change *pb.UserResChangedPush
// _change, errdata = this.change(session, attr, add)
// if errdata != nil {
// return
// }
// if _change == nil {
// return
// }
// if bPush { //推送玩家账号信息变化消息
// session.SendMsg(string(this.GetType()), "reschanged", _change)
// }
// return
// }
// 用户资源
func (this *User) AddAttributeValues(session comm.IUserSession, attrs map[string]int32, bPush bool) (atno []*pb.UserAtno, errdata *pb.ErrorData) {
var (
tasks []*pb.BuriedParam = make([]*pb.BuriedParam, 0)
_change *pb.UserResChangedPush
)
atno, _change, errdata = this.change(session, attrs)
if errdata != nil {
return
}
for key, add := range attrs {
if key == comm.ResPs && add < 0 { //消耗体力
tasks = append(tasks, comm.GetBuriedParam(comm.Rtype213, -add))
}
if key == comm.ResGold && add < 0 { //消耗体力
tasks = append(tasks, comm.GetBuriedParam(comm.Rtype68, -add))
}
if key == comm.ResDiamond && add < 0 { //消耗钻石
tasks = append(tasks, comm.GetBuriedParam(comm.Rtype104, -add))
}
if key == comm.Integral && add > 0 { //积分获取
tasks = append(tasks, comm.GetBuriedParam(comm.Rtype214, add))
}
}
if bPush { //推送玩家账号信息变化消息
session.SendMsg(string(this.GetType()), "reschanged", _change)
}
if len(tasks) > 0 {
go this.AsynHandleSession(session.Clone(), func(session comm.IUserSession) {
this.ModuleBuried.TriggerBuried(session, tasks...)
})
}
return
}
func (this *User) GetUserExpand(uid string) (result *pb.DBUserExpand, err error) {
return this.modelExpand.GetUserExpand(uid)
}
func (this *User) ChangeUserExpand(uid string, value map[string]interface{}) error {
return this.modelExpand.ChangeUserExpand(uid, value)
}
// 从远程库查询用户
func (this *User) getUserFromRemoteDb(uid string, rsp *pb.DBUser) error {
sid, _, ok := utils.UIdSplit(uid)
if !ok {
return fmt.Errorf("sid split err,uid: %v", uid)
}
conn, err := db.ServerDBConn(sid)
if err != nil {
return err
}
model := db.NewDBModel(comm.TableUser, conn)
if err := model.Get(uid, rsp); err != nil {
this.Errorln("Get User:", err)
return err
}
return nil
}
func (this *User) getUserExpandFromRemoteDb(uid string, rsp *pb.DBUserExpand) error {
sid, _, ok := utils.UIdSplit(uid)
if !ok {
return errors.New("sid split error")
}
conn, err := db.ServerDBConn(sid)
if err != nil {
return err
}
model := db.NewDBModel(comm.TableUserExpand, conn)
if err := model.Get(uid, rsp); err != nil {
return err
}
return nil
}
func (this *User) changeUserExpandFromRemoteDb(uid string, data map[string]interface{}) error {
sid, _, ok := utils.UIdSplit(uid)
if !ok {
return errors.New("sid split error")
}
conn, err := db.ServerDBConn(sid)
if err != nil {
return err
}
model := db.NewDBModel(comm.TableUserExpand, conn)
if err := model.Change(uid, data); err != nil {
return err
}
return nil
}
func (this *User) queryUserFromRemoteDb(name string, reply *pb.UserDataListResp) error {
// 区服列表
for _, tag := range db.GetServerTags() {
conn, err := db.ServerDBConn(tag)
if err != nil {
return fmt.Errorf("db tag:%v err:%v", tag, err)
}
//查询用户
filter := bson.M{
"name": name,
}
sr := conn.Mgo.FindOne(comm.TableUser, filter)
user := &pb.DBUser{}
if err = sr.Decode(user); err != nil {
if err != mongo.ErrNoDocuments {
return err
}
}
if user.Uid != "" {
reply.Users = append(reply.Users, user)
}
}
return nil
}
func (this *User) RpcGetAllOnlineUser(ctx context.Context, args *pb.EmptyReq, reply *pb.UserOnlineResp) error {
conn, err := db.Local()
if err != nil {
return err
}
model := db.NewDBModelByExpired(comm.TableSession, conn)
var cache []*pb.CacheUser
if err := model.GetList(comm.RDS_EMPTY, &cache); err != nil {
return err
}
reply.Users = cache
return nil
}
func (this *User) RpcGetCrossUser(ctx context.Context, req *pb.UIdReq, reply *pb.DBUser) error {
return this.getUserFromRemoteDb(req.Uid, reply)
}
func (this *User) RpcGetCrossUserSession(ctx context.Context, req *pb.UIdReq, reply *pb.CacheUser) error {
conn, err := db.Local()
if err != nil {
return err
}
model := db.NewDBModelByExpired(comm.TableSession, conn)
if err := model.GetListObj(comm.RDS_EMPTY, req.Uid, reply); err != nil {
if err != mongo.ErrNoDocuments {
return err
}
}
return nil
}
func (this *User) RpcQueryUser(ctx context.Context, req *pb.NameReq, reply *pb.UserDataListResp) error {
return this.queryUserFromRemoteDb(req.Name, reply)
}
func (this *User) CheckTujianHero(session comm.IUserSession, heros []string) []bool {
sz := make([]bool, len(heros))
index := 0
list := this.ModuleHero.GetHeroList(session.GetUserId())
for _, v1 := range heros {
for _, h := range list {
if v1 == h.HeroID {
sz[index] = true
index++
break
}
}
}
return sz
}
func (this *User) BingoSetUserLv(session comm.IUserSession, lv int32) error {
if lv <= 0 {
return comm.NewCustomError(pb.ErrorCode_ReqParameterError)
}
if conf := this.configure.GetPlayerlvConfList(); len(conf) > 0 {
maxlv := conf[len(this.configure.GetPlayerlvConfList())-1].Lv
if lv > maxlv {
lv = maxlv
}
}
update := map[string]interface{}{
"lv": lv,
"exp": 0,
}
if err := this.modelUser.Change(session.GetUserId(), update); err == nil {
if err := session.SendMsg(string(this.GetType()), UserSubTypeLvChangedPush,
&pb.UserLvChangedPush{Uid: session.GetUserId(), Exp: 0, Lv: lv}); err != nil {
this.Error("Bingo玩家等级变化 UserSubTypeLvChangedPush推送失败",
log.Field{Key: "uid", Value: session.GetUserId()},
log.Field{Key: "exp", Value: 0},
log.Field{Key: "lv", Value: lv},
)
}
}
this.ModuleSys.CheckOpenCond(session, comm.OpencondTypePlatlv, lv)
// 触发埋点
return nil
}
// // 玩家体力恢复
// func (this *User) RecoverUserPsStart(session comm.IUserSession) (recoverTime int64) {
// var (
// yu int32
// add int32
// changed int32
// )
// // 推送红点信息
// re := this.ModuleTools.GetGlobalConf().PsRecovery
// if re <= 0 {
// return
// }
// u, err := this.GetUser(session.GetUserId())
// if err != nil {
// return
// }
// if u.LastRecoverPsSec == 0 {
// u.LastRecoverPsSec = configure.Now().Unix()
// }
// diff := configure.Now().Unix() - u.LastRecoverPsSec
// yu = int32(diff / int64(re))
// if yu > 0 {
// pconf := this.configure.GetPlayerlvConf(u.Lv)
// if pconf == nil {
// return
// }
// if u.Ps < pconf.PsCeiling {
// total := u.Ps + yu
// if total > pconf.PsCeiling {
// add = pconf.PsCeiling - u.Ps
// changed = pconf.PsCeiling
// } else {
// add = yu
// changed = total
// u.LastRecoverPsSec += int64(yu * re)
// }
// } else {
// add = 0
// }
// //u.LastRecoverPsSec = time.Now().Unix()
// update := map[string]interface{}{}
// if add > 0 {
// u.Ps += add
// update["ps"] = u.Ps
// update["lastRecoverPsSec"] = u.LastRecoverPsSec
// }
// if err := this.modelUser.Change(u.Uid, update); err == nil {
// if changed > 0 {
// this.reddot.PushReddot(session, &pb.ReddotItem{
// Rid: int32(comm.Reddot30100),
// Nextchanagetime: u.LastRecoverPsSec + int64(re),
// })
// session.Push()
// }
// }
// }
// recoverTime = u.LastRecoverPsSec + int64(re)
// return recoverTime
// }
// 玩家体力恢复
func (this *User) recoverUserPs(user *pb.DBUser) (change bool, total int32, nexttime int64) {
var (
yu int32
add int32
)
ggd := this.ModuleTools.GetGlobalConf()
if ggd == nil {
return
}
pconf := this.configure.GetPlayerlvConf(user.Lv)
if pconf == nil {
return
}
if user.Ps >= pconf.PsCeiling {
return
}
total = pconf.PsCeiling
cur := time.Now().Unix()
if user.LastRecoverPsSec == 0 {
user.LastRecoverPsSec = cur
change = true
return
} else {
diff := cur - user.LastRecoverPsSec
yu = int32(diff / int64(ggd.PsRecovery))
}
if yu > 0 {
total := user.Ps + yu
if total > pconf.PsCeiling {
add = pconf.PsCeiling - user.Ps
} else {
add = yu
}
user.LastRecoverPsSec = cur
user.Ps += add
change = true
}
nexttime = user.LastRecoverPsSec + int64(ggd.PsRecovery)
return
}
func (this *User) BingoSetUserVipLv(session comm.IUserSession, lv int32) (errdata *pb.ErrorData) {
if lv <= 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_ConfigNoFound,
Title: pb.ErrorCode_ConfigNoFound.ToString(),
}
return
}
update := map[string]interface{}{
"vip": lv,
"vipexp": 0,
}
// vip 等级校验
if conf := this.configure.GetVipConfigureData(lv); conf == nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_ConfigNoFound,
Title: pb.ErrorCode_ConfigNoFound.ToString(),
}
return
}
if err := this.modelUser.Change(session.GetUserId(), update); err == nil {
if err := session.SendMsg(string(this.GetType()), UserSubTypeVipChangedPush,
&pb.UserVipChangedPush{Uid: session.GetUserId(), VipExp: 0, VipLv: lv}); err != nil {
this.Error("Bingo玩家等级变化 UserVipChangedPush推送失败",
log.Field{Key: "uid", Value: session.GetUserId()},
log.Field{Key: "vipexp", Value: 0},
log.Field{Key: "viplv", Value: lv},
)
}
}
return nil
}
// 添加用户皮肤数据
func (this *User) AddPer(session comm.IUserSession, pers map[string]int32, bPush bool) (errdata *pb.ErrorData) {
var (
err error
conf *cfg.GamePlayerInfor_overviewData
user *pb.DBUser
change map[string]interface{} = make(map[string]interface{})
adds []string = make([]string, 0)
iskeep bool
)
if user, err = this.GetUser(session.GetUserId()); err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserSessionNobeing,
Title: pb.ErrorCode_UserSessionNobeing.ToString(),
Message: err.Error(),
}
return
}
for k, _ := range pers {
iskeep = false
for _, v1 := range user.Skins {
if k == v1 {
iskeep = true
break
}
}
if !iskeep {
if user.CurSkin == "" || user.CurAction == "" || user.CurBg == "" || user.Curaframe == "" {
if conf, err = this.configure.GetPlayerOverview(k, user.Gender); err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_ConfigNoFound,
Title: pb.ErrorCode_ConfigNoFound.ToString(),
Message: err.Error(),
}
return
} else {
if user.CurSkin == "" && conf.Type == 1 {
user.CurSkin = k
user.Avatar = conf.Playerhead
change["curSkin"] = k
change["avatar"] = conf.Playerhead
}
if user.CurAction == "" && conf.Type == 2 {
user.CurAction = k
change["curAction"] = k
}
if user.CurBg == "" && conf.Type == 3 {
user.CurBg = k
change["curBg"] = k
}
if user.Curaframe == "" && conf.Type == 4 {
user.Curaframe = k
change["curaframe"] = k
}
}
}
adds = append(adds, k)
}
}
user.Skins = append(user.Skins, adds...)
change["skins"] = user.Skins
if err = this.modelUser.Change(session.GetUserId(), change); err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_DBError,
Title: pb.ErrorCode_DBError.ToString(),
Message: err.Error(),
}
return
}
if bPush {
session.SendMsg(string(this.GetType()), "skinlist", &pb.UserSkinlistPush{
Skins: user.Skins,
CurSkin: user.CurSkin,
CurAction: user.CurAction,
CurBg: user.CurBg,
Avatar: user.Avatar,
CurAframe: user.Curaframe,
})
}
return
}
func (this *User) ConsumePsAddExp(session comm.IUserSession, ps int32) (atno []*pb.UserAtno, errdata *pb.ErrorData) {
var addExp int32
if ps <= 0 {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_ReqParameterError,
Title: pb.ErrorCode_ReqParameterError.ToString(),
Message: "ConsumePsAddExp ps is zero",
}
return
}
ggd := this.ModuleTools.GetGlobalConf()
if ggd == nil {
return
}
//体力消耗,增加玩家经验
addExp = ps * ggd.FightPs
attrs := make(map[string]int32, 0)
attrs["exp"] = addExp
atno, errdata = this.AddAttributeValues(session, attrs, true)
return
}
// 剩余体力
func (this *User) RemainingPS(uid string) (ps int32) {
var (
user *pb.DBUser
err error
)
if user, err = this.GetUser(uid); err != nil {
return
}
ggd := this.ModuleTools.GetGlobalConf()
if ggd == nil {
return
}
return ggd.PsUl - user.Ps
}
// 查询每日红点信息
func (this *User) Reddot(session comm.IUserSession, rid ...comm.ReddotType) (reddot map[comm.ReddotType]*pb.ReddotItem) {
var (
user *pb.DBUser
info *pb.DBSign
progress int32
err error
)
reddot = make(map[comm.ReddotType]*pb.ReddotItem)
if info, err = this.modelSign.GetUserSign(session.GetUserId()); err != nil {
this.Errorln(err)
return
}
for _, v := range rid {
switch v {
case comm.Reddot27101:
if info.Puzzle[info.Day] == 1 {
progress = 1
}
reddot[comm.Reddot27101] = &pb.ReddotItem{
Rid: int32(comm.Reddot27101),
Activated: true,
Progress: progress,
Total: 1,
}
break
case comm.Reddot30100: // 体力恢复
user, err = this.GetUser(session.GetUserId())
if err != nil {
this.Errorln(err)
return
}
change, total, t := this.recoverUserPs(user)
reddot[comm.Reddot30100] = &pb.ReddotItem{
Rid: int32(comm.Reddot30100),
Activated: true,
Nextchanagetime: t,
Progress: user.Ps,
Total: total,
}
if change {
this.modelUser.Change(session.GetUserId(), map[string]interface{}{
"ps": user.Ps,
"lastRecoverPsSec": user.LastRecoverPsSec,
})
}
break
}
}
return
}
func (this *User) CleanUserMerchantmoney(session comm.IUserSession) (err error) {
return this.modelUser.CleanUserMerchantmoney(session)
}
func (this *User) ChangeUserCaravanLv(session comm.IUserSession, lv int32) (errdata *pb.ErrorData) {
update := map[string]interface{}{
"caravanlv": lv,
}
if err := this.modelUser.Change(session.GetUserId(), update); err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_DBError,
Title: pb.ErrorCode_DBError.ToString(),
Message: err.Error(),
}
}
return
}
// 添加用户皮肤数据
func (this *User) AddTitle(session comm.IUserSession, titles map[string]int32, bPush bool) (errdata *pb.ErrorData) {
var (
err error
user *pb.DBUser
change map[string]interface{} = make(map[string]interface{})
iskeep bool
)
if user, err = this.GetUser(session.GetUserId()); err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_UserSessionNobeing,
Title: pb.ErrorCode_UserSessionNobeing.ToString(),
Message: err.Error(),
}
return
}
for k, _ := range titles {
iskeep = false
for _, v1 := range user.Titles {
if k == v1 {
iskeep = true
break
}
}
if !iskeep {
user.Titles = append(user.Titles, k)
change["titles"] = user.Titles
}
}
if len(change) > 0 {
if err = this.modelUser.Change(session.GetUserId(), change); err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_DBError,
Title: pb.ErrorCode_DBError.ToString(),
Message: err.Error(),
}
return
}
if bPush {
session.SendMsg(string(this.GetType()), "titlelist", &pb.UserTitleListPush{
Titles: user.Titles,
Curtitle: user.Curtitle,
})
}
}
return
}
func (this *User) Rpc_AccountBan(ctx context.Context, req *pb.RPCAccountBan, reply *pb.UserDataListResp) error {
var (
err error
)
if _, err = this.GetUser(req.Uid); err != nil {
return err
}
if req.Key == 0 { // 封号
bBan := false
if req.Value > 0 {
bBan = true
}
update := map[string]interface{}{
"ban": bBan,
}
if err := this.modelUser.Change(req.Uid, update); err != nil {
return err
}
} else if req.Key == 1 { // 禁言
update := map[string]interface{}{
"prohibition": req.Value,
}
if err := this.modelUser.Change(req.Uid, update); err != nil {
return err
}
}
return err
}
func (this *User) ChangeUserMoonLv(session comm.IUserSession, lv int32) (errdata *pb.ErrorData) {
update := map[string]interface{}{
"moonlv": lv,
}
if err := this.modelUser.Change(session.GetUserId(), update); err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_DBError,
Title: pb.ErrorCode_DBError.ToString(),
Message: err.Error(),
}
}
return
}