| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734 |
- package model
- import (
- "math"
- "rocommon/util"
- "roserver/baseserver/set"
- "roserver/serverproto"
- "sort"
- )
- const DayMS = DaySec * 1000
- const DaySec = 24 * 60 * 60
- const MaxMailNum = 50
- type RoleMail struct {
- SaveObject
- updateTimer util.DurationTimer //保存数据定时器
- mailMap map[int32]*serverproto.MailContent
- //未读取邮件列表
- unreadMailList map[int32]*serverproto.MailContent
- //拥有附件邮件列表
- unRewardMailList map[int32]*serverproto.MailContent
- maxMailId int32
- curGlobalMailId int32
- delMailSet []int32
- saveMailSet set.Interface
- addMailList set.Interface
- }
- func newRoleMail(r *Role) *RoleMail {
- mail := &RoleMail{
- SaveObject: SaveObject{
- role: r,
- },
- mailMap: map[int32]*serverproto.MailContent{},
- maxMailId: 0,
- saveMailSet: set.New(set.NonThreadSafe),
- addMailList: set.New(set.NonThreadSafe),
- unreadMailList: map[int32]*serverproto.MailContent{},
- unRewardMailList: map[int32]*serverproto.MailContent{},
- }
- return mail
- }
- func (this *RoleMail) LoadOther(msg interface{}) bool {
- return true
- }
- func (this *RoleMail) Load(msg interface{}) bool {
- proRole := msg.(*serverproto.Role)
- mailInfo := proRole.RoleMail
- if mailInfo == nil {
- return true
- }
- nowTime := util.GetTimeMilliseconds()
- this.maxMailId = mailInfo.MaxMailId
- this.curGlobalMailId = mailInfo.CurrGlobalMailId
- for _, mail := range mailInfo.MailList {
- //记录当前领取到的最大平台发送邮件ID
- if mail.Type == int32(serverproto.MailType_MailType_GM) && mail.BeginTime == 0 {
- if this.curGlobalMailId < mail.Id {
- this.curGlobalMailId = mail.Id
- }
- this.maxMailId++
- mail.Id = this.maxMailId //重新复制邮件ID,之前的ID表示全局邮件ID
- this.SetDirty(true)
- }
- //离线添加的邮件在玩家登陆时进行初始化
- if mail.BeginTime <= 0 {
- mail.BeginTime = nowTime
- //通过gmweb方式添加的邮件
- if mail.Type != int32(serverproto.MailType_MailType_GM) {
- cfgData, ok := serverproto.MailCfgLoader[mail.ConfigId]
- if ok {
- mail.ExpireTime = nowTime + uint64(cfgData.Time)*DayMS
- }
- } else {
- mail.ExpireTime = nowTime + 30*DayMS
- }
- this.SetDirty(true)
- this.saveMailSet.Add(mail.Id)
- }
- //判断过期邮件
- if this.isExpired(mail, nowTime) {
- this.delMailSet = append(this.delMailSet, mail.Id)
- this.SetDirty(true)
- continue
- }
- //邮件内容是否正确,不正确在初始化时删除
- bDel := false
- for idx := 0; idx < len(mail.RewardList); idx++ {
- if GetItemCfg(mail.RewardList[idx].Key) == nil {
- bDel = true
- break
- }
- }
- if bDel {
- this.delMailSet = append(this.delMailSet, mail.Id)
- this.SetDirty(true)
- continue
- }
- this.mailMap[mail.Id] = mail
- if this.isMailCanRead(mail) {
- this.unreadMailList[mail.Id] = mail
- }
- if this.isMailCanReward(mail) {
- this.unRewardMailList[mail.Id] = mail
- }
- }
- util.InfoF("uid=%v maxMailId=%v", this.role.GetUUid(), this.maxMailId)
- this.updateTimer.Reset(util.GetTimeMilliseconds(), 60*1000, false)
- //邮件数量超过上限处理
- delMailIdList := this.refreshMailNum()
- for idx := 0; idx < len(delMailIdList); idx++ {
- this.addDelMail(delMailIdList[idx])
- }
- if len(this.unreadMailList) <= 0 {
- this.role.GetRoleRed().SetUnRedMail(false, false)
- } else {
- this.role.GetRoleRed().SetUnRedMail(true, false)
- }
- return true
- }
- func (this *RoleMail) Save() {
- this.SetDirty(false)
- //util.DebugF("uid=%v RoleMail save...", this.role.GetUUid())
- saveMsg := &serverproto.SSMailSaveNtf{}
- //邮件状态变更
- for {
- if this.saveMailSet.Size() <= 0 {
- break
- }
- mailId := this.saveMailSet.Pop().(int32)
- if this.mailMap[mailId] != nil {
- saveMsg.MailStateList = append(saveMsg.MailStateList, this.mailMap[mailId])
- }
- }
- //删除邮件
- saveMsg.DelMailList = append(this.delMailSet)
- this.delMailSet = this.delMailSet[:0]
- //添加新邮件
- for {
- if this.addMailList.Size() <= 0 {
- break
- }
- mailId := this.addMailList.Pop().(int32)
- if this.mailMap[mailId] != nil {
- saveMsg.AddMailList = append(saveMsg.AddMailList, this.mailMap[mailId])
- }
- }
- saveMsg.MaxMailId = this.maxMailId
- saveMsg.CurGlobalMailId = this.curGlobalMailId
- this.role.SendDb(saveMsg)
- }
- func (this *RoleMail) Update(ms uint64) {
- //过期邮件处理
- if this.updateTimer.IsStart() && this.updateTimer.IsExpired(ms) {
- var ntfMsg *serverproto.SCMailChangeNtf = nil
- for _, data := range this.mailMap {
- if this.isExpired(data, ms) {
- this.addDelMail(data.Id)
- if ntfMsg == nil {
- ntfMsg = &serverproto.SCMailChangeNtf{}
- }
- ntfMsg.DelMailList = append(ntfMsg.DelMailList, data.Id)
- }
- }
- if ntfMsg != nil && len(ntfMsg.DelMailList) > 0 {
- util.InfoF("uid=%v Update delMailList=%v", this.role.GetUUid(), ntfMsg)
- ntfMsg.TotalMailCount = int32(len(this.mailMap))
- //小红点数据
- if len(this.unreadMailList) > 0 {
- this.role.roleRed.SetUnRedMail(true, true)
- } else {
- this.role.roleRed.SetUnRedMail(false, true)
- }
- this.role.ReplayGate(ntfMsg, true)
- }
- }
- }
- func (this *RoleMail) isExpired(mail *serverproto.MailContent, ms uint64) bool {
- if ms >= mail.ExpireTime && mail.ExpireTime != 0 {
- return true
- }
- return false
- }
- //0未读取 1已读取 | 00未获取 10已获取
- //邮件状态 第1位标识读取状态,第2位标识附件获取状态
- //邮件是否读取
- func (this *RoleMail) isMailCanRead(mail *serverproto.MailContent) bool {
- if mail.State&1 > 0 {
- return false
- }
- return true
- }
- func (this *RoleMail) setMailRead(mail *serverproto.MailContent) {
- mail.State |= 1
- this.saveMailSet.Add(mail.Id)
- delete(this.unreadMailList, mail.Id)
- this.SetDirty(true)
- }
- //附件是否领取
- func (this *RoleMail) isMailCanReward(mail *serverproto.MailContent) bool {
- if len(mail.RewardList) <= 0 {
- return false
- }
- if (mail.State>>1)&1 > 0 {
- return false
- }
- this.saveMailSet.Add(mail.Id)
- this.SetDirty(true)
- return true
- }
- func (this *RoleMail) setMailReward(mail *serverproto.MailContent) {
- mail.State |= 2
- delete(this.unRewardMailList, mail.Id)
- delete(this.unreadMailList, mail.Id)
- }
- func (this *RoleMail) addDelMail(mailId int32) {
- this.delMailSet = append(this.delMailSet, mailId)
- this.saveMailSet.Remove(mailId)
- this.addMailList.Remove(mailId)
- delete(this.unreadMailList, mailId)
- delete(this.unRewardMailList, mailId)
- delete(this.mailMap, mailId)
- this.SetDirty(true)
- }
- func (this *RoleMail) GetMailList() {
- ackMsg := &serverproto.SCMailListAck{}
- if len(this.mailMap) <= 0 {
- this.role.ReplayGate(ackMsg, true)
- return
- }
- ackMsg.TotalMailCount = int32(len(this.mailMap))
- for _, data := range this.mailMap {
- ackMsg.MailList = append(ackMsg.MailList, data)
- }
- this.role.ReplayGate(ackMsg, true)
- }
- func (this *RoleMail) MailRead(idList []int32) serverproto.ErrorCode {
- ntfMsg := &serverproto.SCMailChangeNtf{}
- ntfMsg.TotalMailCount = int32(len(this.mailMap))
- if len(idList) <= 0 {
- if len(this.unreadMailList) <= 0 {
- return serverproto.ErrorCode_ERROR_MAIL_NO_READ_MAIL
- }
- //一键读取
- for _, mail := range this.unreadMailList {
- if !this.isMailCanRead(mail) {
- continue
- }
- this.setMailRead(mail)
- ntfMsg.MailStateList = append(ntfMsg.MailStateList, &serverproto.KeyValueType{
- Key: mail.Id,
- Value: mail.State,
- })
- }
- } else {
- for _, id := range idList {
- mail, ok := this.mailMap[id]
- if !ok {
- continue
- }
- if !this.isMailCanRead(mail) {
- delete(this.unreadMailList, id)
- continue
- }
- this.setMailRead(mail)
- ntfMsg.MailStateList = append(ntfMsg.MailStateList, &serverproto.KeyValueType{
- Key: mail.Id,
- Value: mail.State,
- })
- }
- }
- //小红点数据
- if len(this.unreadMailList) > 0 {
- this.role.roleRed.SetUnRedMail(true, true)
- } else {
- this.role.roleRed.SetUnRedMail(false, true)
- }
- if len(ntfMsg.MailStateList) <= 0 {
- return serverproto.ErrorCode_ERROR_MAIL_NO_READ_MAIL
- }
- this.role.ReplayGate(ntfMsg, true)
- util.DebugF("uid=%v MailRead msg=%v", this.role.GetUUid(), ntfMsg)
- return serverproto.ErrorCode_ERROR_OK
- }
- func (this *RoleMail) MailDelRead() serverproto.ErrorCode {
- if len(this.mailMap) <= 0 {
- return serverproto.ErrorCode_ERROR_MAIL_NO_MAIL
- }
- ntfMsg := &serverproto.SCMailChangeNtf{}
- //删除已读文件,一键删除
- for _, data := range this.mailMap {
- //当前邮件未读取状态
- if this.isMailCanRead(data) {
- continue
- }
- //当前邮件附件未领取
- if this.isMailCanReward(data) {
- continue
- }
- ntfMsg.DelMailList = append(ntfMsg.DelMailList, data.Id)
- //添加到邮件删除列表
- this.addDelMail(data.Id)
- }
- if len(ntfMsg.DelMailList) <= 0 {
- return serverproto.ErrorCode_ERROR_MAIL_NO_DEL_MAIL
- }
- ntfMsg.TotalMailCount = int32(len(this.mailMap))
- this.role.ReplayGate(ntfMsg, true)
- util.DebugF("uid=%v MailDelRead msg=%v", this.role.GetUUid(), ntfMsg)
- return serverproto.ErrorCode_ERROR_OK
- }
- func (this *RoleMail) doMailReward(mail *serverproto.MailContent, addItemList map[int32]int32) serverproto.ErrorCode {
- //判断是否能整体添加邮件附件
- for _, data := range mail.RewardList {
- ret := this.role.GetRoleBag().CanAddItem(data.Key, data.Value)
- if ret != serverproto.ErrorCode_ERROR_OK {
- return ret
- }
- }
- for _, data := range mail.RewardList {
- addItemList[data.Key] += data.Value
- }
- this.setMailRead(mail)
- this.setMailReward(mail)
- return serverproto.ErrorCode_ERROR_OK
- }
- func (this *RoleMail) MailReward(idList []int32) serverproto.ErrorCode {
- if len(this.mailMap) <= 0 {
- return serverproto.ErrorCode_ERROR_MAIL_NO_MAIL
- }
- ntfMsg := &serverproto.SCMailChangeNtf{}
- ntfMsg.TotalMailCount = int32(len(this.mailMap))
- //一键领取奖励
- bFull := serverproto.ErrorCode_ERROR_OK
- var addItemList = map[int32]int32{}
- if len(idList) <= 0 {
- if len(this.unRewardMailList) <= 0 {
- return serverproto.ErrorCode_ERROR_MAIL_NO_REWARD_MAIL
- }
- for _, mail := range this.unRewardMailList {
- if !this.isMailCanReward(mail) {
- delete(this.unRewardMailList, mail.Id)
- continue
- }
- if ret := this.doMailReward(mail, addItemList); ret != serverproto.ErrorCode_ERROR_OK {
- bFull = ret
- continue
- }
- ntfMsg.MailStateList = append(ntfMsg.MailStateList, &serverproto.KeyValueType{
- Key: mail.Id,
- Value: mail.State,
- })
- }
- } else {
- for _, id := range idList {
- mail, ok := this.mailMap[id]
- if !ok {
- continue
- }
- if !this.isMailCanReward(mail) {
- delete(this.unRewardMailList, id)
- continue
- }
- if ret := this.doMailReward(mail, addItemList); ret != serverproto.ErrorCode_ERROR_OK {
- bFull = ret
- continue
- }
- ntfMsg.MailStateList = append(ntfMsg.MailStateList, &serverproto.KeyValueType{
- Key: mail.Id,
- Value: mail.State,
- })
- }
- }
- //小红点数据
- if len(this.unreadMailList) > 0 {
- this.role.roleRed.SetUnRedMail(true, true)
- } else {
- this.role.roleRed.SetUnRedMail(false, true)
- }
- if len(ntfMsg.MailStateList) > 0 {
- this.role.ReplayGate(ntfMsg, true)
- util.DebugF("uid=%v MailReward msg=%v", this.role.GetUUid(), ntfMsg)
- }
- //获取附件资源
- if len(addItemList) > 0 {
- ackMsg := &serverproto.SCMailRewardAck{
- Error: int32(serverproto.ErrorCode_ERROR_OK),
- }
- //背包已满
- if bFull != serverproto.ErrorCode_ERROR_OK {
- ackMsg.Error = int32(bFull)
- }
- this.role.AddItemList(addItemList, AddFrom_Mail, true)
- for key, value := range addItemList {
- ackMsg.RewardList = append(ackMsg.RewardList, &serverproto.KeyValueType{
- Key: key,
- Value: value,
- })
- }
- this.role.ReplayGate(ackMsg, true)
- } else if bFull != serverproto.ErrorCode_ERROR_OK {
- ackMsg := &serverproto.SCMailRewardAck{
- Error: int32(bFull),
- }
- this.role.ReplayGate(ackMsg, true)
- }
- return serverproto.ErrorCode_ERROR_OK
- }
- func (this *RoleMail) addMail(mail *serverproto.MailContent, notify bool) {
- ntfMsg := &serverproto.SCMailChangeNtf{}
- //判断当前邮件是否已满
- if len(this.mailMap) >= MaxMailNum {
- var delMailId int32 = math.MaxInt32
- var minMailId int32 = math.MaxInt32
- for _, data := range this.mailMap {
- if !this.isMailCanRead(data) && !this.isMailCanReward(data) && data.Id < delMailId {
- delMailId = data.Id
- }
- if data.Id < minMailId {
- minMailId = data.Id
- }
- }
- if delMailId == 0 || delMailId == math.MaxInt32 {
- delMailId = minMailId
- }
- this.addDelMail(delMailId)
- ntfMsg.DelMailList = append(ntfMsg.DelMailList, delMailId)
- }
- this.mailMap[mail.Id] = mail
- this.addMailList.Add(mail.Id)
- this.unreadMailList[mail.Id] = mail
- if len(mail.RewardList) > 0 {
- this.unRewardMailList[mail.Id] = mail
- }
- ntfMsg.AddMailList = append(ntfMsg.AddMailList, mail)
- ntfMsg.TotalMailCount = int32(len(this.mailMap))
- //有可能是离线玩家
- if this.role.GetState() != ROLE_STATE_OFFLINE {
- //小红点数据
- this.role.roleRed.SetUnRedMail(true, true)
- if notify {
- this.role.ReplayGate(ntfMsg, true)
- }
- }
- util.DebugF("uid=%v AddMail maxMailId=%v msg=%v ", this.role.GetUUid(), this.maxMailId, ntfMsg)
- this.SetDirty(true)
- }
- func (this *RoleMail) refreshMailNum() []int32 {
- delNum := len(this.mailMap) - MaxMailNum
- if delNum <= 0 {
- return nil
- }
- var delMailIdList []int32
- var tmpMailList []*serverproto.MailContent
- for _, data := range this.mailMap {
- tmpMailList = append(tmpMailList, data)
- if !this.isMailCanRead(data) && !this.isMailCanReward(data) {
- delMailIdList = append(delMailIdList, data.Id)
- }
- }
- sort.Slice(tmpMailList, func(i, j int) bool {
- return tmpMailList[i].Id < tmpMailList[j].Id
- })
- if delNum <= len(delMailIdList) {
- sort.Slice(delMailIdList, func(i, j int) bool {
- return delMailIdList[i] < delMailIdList[j]
- })
- return delMailIdList[0:delNum]
- } else {
- for idx := 0; idx < len(tmpMailList); idx++ {
- bFind := false
- for k := 0; k < len(delMailIdList); k++ {
- if delMailIdList[k] == tmpMailList[idx].Id {
- bFind = true
- break
- }
- }
- if bFind {
- continue
- }
- delMailIdList = append(delMailIdList, tmpMailList[idx].Id)
- delNum--
- if delNum <= 0 {
- break
- }
- }
- }
- return delMailIdList
- }
- func (this *RoleMail) AddMail(configId int32, mailType serverproto.MailType,
- itemList map[int32]int32, paramList []int32, title, content string) bool {
- //后台发送的邮件
- if mailType == serverproto.MailType_MailType_GM || mailType == serverproto.MailType_MailType_GM_Self {
- if this.curGlobalMailId < configId && mailType == serverproto.MailType_MailType_GM {
- this.curGlobalMailId = configId
- }
- //获取配置文件
- this.maxMailId++
- nowTime := util.GetTimeMilliseconds()
- mail := &serverproto.MailContent{
- ConfigId: 0,
- Id: this.maxMailId,
- Type: int32(mailType),
- BeginTime: nowTime,
- ExpireTime: nowTime + 30*DayMS,
- Title: title,
- Content: content,
- }
- if len(paramList) > 0 {
- mail.ParamList = append(paramList)
- }
- if len(itemList) > 0 {
- for key, value := range itemList {
- mail.RewardList = append(mail.RewardList, &serverproto.KeyValueType{
- Key: key,
- Value: value,
- })
- }
- }
- this.addMail(mail, true)
- return true
- } else {
- var expireTime uint64 = 30 * DayMS
- if configId > 0 {
- cfgData, ok := serverproto.MailCfgLoader[configId]
- if !ok {
- util.DebugF("uid=%v AddMail mailConfigId=%v not find!!!", this.role.GetUUid(), configId)
- return false
- }
- expireTime = uint64(cfgData.Time) * DayMS
- }
- //获取配置文件
- this.maxMailId++
- nowTime := util.GetTimeMilliseconds()
- mail := &serverproto.MailContent{
- Id: this.maxMailId,
- ConfigId: configId,
- Type: int32(mailType),
- BeginTime: nowTime,
- ExpireTime: nowTime + expireTime,
- Title: title,
- Content: content,
- }
- if len(paramList) > 0 {
- mail.ParamList = append(paramList)
- }
- if len(itemList) > 0 {
- for key, value := range itemList {
- mail.RewardList = append(mail.RewardList, &serverproto.KeyValueType{
- Key: key,
- Value: value,
- })
- }
- }
- //if mailType != serverproto.MailType_MailType_Competition {
- // this.addMail(mail, true)
- //} else {
- // this.addMail(mail, false)
- //}
- this.addMail(mail, true)
- return true
- }
- }
- func (this *RoleMail) AddMail1(configId int32, mailType serverproto.MailType,
- itemList []*serverproto.KeyValueType, paramList []int32, title, content string) bool {
- //后台发送的邮件
- if mailType == serverproto.MailType_MailType_GM ||
- mailType == serverproto.MailType_MailType_GM_Self {
- //全局邮件才处理
- if this.curGlobalMailId < configId && mailType == serverproto.MailType_MailType_GM {
- this.curGlobalMailId = configId
- }
- //获取配置文件
- this.maxMailId++
- nowTime := util.GetTimeMilliseconds()
- mail := &serverproto.MailContent{
- ConfigId: 0,
- Id: this.maxMailId,
- Type: int32(mailType),
- BeginTime: nowTime,
- Title: title,
- Content: content,
- ExpireTime: nowTime + 30*DayMS,
- }
- if len(paramList) > 0 {
- mail.ParamList = append(paramList)
- }
- if len(itemList) > 0 {
- mail.RewardList = append(itemList)
- }
- this.addMail(mail, true)
- return true
- } else {
- var expireTime uint64 = 30 * DayMS
- if configId > 0 {
- cfgData, ok := serverproto.MailCfgLoader[configId]
- if !ok {
- util.DebugF("uid=%v AddMail mailConfigId=%v", this.role.GetUUid(), configId)
- return false
- }
- expireTime = uint64(cfgData.Time) * DayMS
- }
- //获取配置文件
- this.maxMailId++
- nowTime := util.GetTimeMilliseconds()
- mail := &serverproto.MailContent{
- Id: this.maxMailId,
- ConfigId: configId,
- Type: int32(mailType),
- BeginTime: nowTime,
- ExpireTime: nowTime + expireTime,
- Title: title,
- Content: content,
- }
- if len(paramList) > 0 {
- mail.ParamList = append(paramList)
- }
- if len(itemList) > 0 {
- mail.RewardList = append(itemList)
- }
- //if mailType != serverproto.MailType_MailType_Competition {
- // this.addMail(mail, true)
- //} else {
- // this.addMail(mail, false)
- //}
- this.addMail(mail, true)
- return true
- }
- }
- func AddMailOnlineAndOffline(uidList []uint64, configId, mailType int32, itemList []*serverproto.KeyValueType,
- paramList []int32, title, content string) {
- //判断当前玩家是否在线,或者在离线池中
- for idx := 0; idx < len(uidList); {
- uid := uidList[idx]
- if uid <= 0 {
- continue
- }
- role := RoleMag.GetRoleFromUUid(uid)
- if role == nil {
- role = RoleMag.GetRoleFromOffline(uid)
- }
- if role != nil {
- role.(RoleLogicOuter).AddMail1(configId, mailType, itemList, paramList, title, content)
- uidList = append(uidList[:idx], uidList[idx+1:]...)
- } else {
- idx++
- }
- }
- if len(uidList) > 0 {
- msg := &serverproto.SSAddMailNtf{
- NotifyList: uidList,
- MailConfigId: configId,
- MailType: mailType,
- RewardList: itemList,
- MailParamList: paramList,
- Title: title,
- Content: content,
- }
- SendDb(msg)
- }
- }
|